美文网首页
2019-02-08 手动安装包解析resources.arsc

2019-02-08 手动安装包解析resources.arsc

作者: 学海摆渡人 | 来源:发表于2019-02-08 22:30 被阅读26次

    由于工作原因,需要直接扫描apk文件得到文件名,由于应用已经安装,不想通过写java方式获取,所以直接笨一点的直接解析arsc文件:

    http://androidxref.com/7.1.2_r36/xref/frameworks/base/include/androidfw/ResourceTypes.h
    按照上面资料一步一步弄下来,只解析了整个文件,尚未按照需求来整理,由于英文水平过差,踩了不少坑,🤦‍♀️🤦‍♀️

    附上手戳代码,勿喷(c++刚学)。

    #include <iostream>
    #include <string.h>
    
    #define RESOURCES_ARSC "/Users/xxx/Downloads/Apps/release/SocialMonitor_v1.0.2.20190207_release/resources.arsc"
    #define GLOBAL_DBUG false
    #define TYPE_DEBUG true
    #define KEY_DEBUG false
    #define DBUG true
    
    using namespace std;
    
    int keyStringPoolThunkOffset;
    int typeStringPoolThunkOffset;
    
    int baseOffset = 0;
    int specOffset = 0;
    
    string* sGlobalString;
    string* sKeyString;
    string* sTypeString;
    
    int preBoolIdStart = 0;//是否已经ID存在了
    
    struct Header {
        uint16_t type;
        uint16_t headerSize;
        uint32_t thunkSize;
        
        string toString() {
            char header[100];
            sprintf(header, "(type:0x%04x, headerSize:%d, thunkSize:%d)", type, headerSize, thunkSize);
            return header;
        }
    };
    
    struct ResTableHeader {
        Header header;
        uint32_t packageNum;
        
        void toString(){
            printf("ResTableHeader { header:%s, packageNum:%d }\n\n",
                   header.toString().c_str(), packageNum);
        }
    };
    
    ResTableHeader mResTableHeader;
    
    void parseResTableHeader(FILE* mFile) {
        printf("ResTableHeader >> offset 0x%08x\n", baseOffset);
        fseek(mFile, baseOffset, SEEK_SET);
        
        char* temp = new(std::nothrow) char[sizeof(mResTableHeader.header.type)];
        fread(temp, sizeof(mResTableHeader.header.type), 1, mFile);
        mResTableHeader.header.type = *((short*)temp);
        
        fread(temp, sizeof(mResTableHeader.header.headerSize), 1, mFile);
        mResTableHeader.header.headerSize = *((short*)temp);
        delete[] temp;
        
        temp = new(std::nothrow) char[sizeof(mResTableHeader.header.thunkSize)];
        fread(temp, sizeof(mResTableHeader.header.thunkSize), 1, mFile);
        mResTableHeader.header.thunkSize = *((int*)temp);
    
        fread(temp, sizeof(mResTableHeader.packageNum), 1, mFile);
        mResTableHeader.packageNum = *((int*)temp);
        delete[] temp;
        
        if (DBUG) mResTableHeader.toString();
        baseOffset += mResTableHeader.header.headerSize;
    }
    
    struct GlobalStringPool {
        Header header;
        uint32_t stringNum;
        uint32_t styleNum;
        uint32_t flag;
        uint32_t strOffset;
        uint32_t styleOffset;
        
        bool chars;
        // ...
        void toString() {
            chars = (flag == 1<<8);
            printf("GlobalStringPool { header:%s, stringNum:%d, styleNum:%d, "
                   "flag:%d(%s), strOffset:%d, styleOffset:%d }\n", header.toString().c_str(), stringNum,
                   styleNum, flag, chars ? "utf-8" : "utf-16", strOffset, styleOffset);
        }
    };
    
    GlobalStringPool mGlobalStringPool;
    
    void printfGlobalStringPool(FILE* mFile) {
        int fileOffset = baseOffset + mGlobalStringPool.strOffset;
        printf("\tGlobalStringPool Content >> offset :0x%08x\n", fileOffset);
        
        fseek(mFile, fileOffset, SEEK_SET);
        
        uint8_t c_len[2];
        sGlobalString = new string[mGlobalStringPool.stringNum];
        
        for (int index = 0; index < mGlobalStringPool.stringNum; index++) {
            fread(&c_len, 2, 1, mFile);
            if (mGlobalStringPool.chars) { // add 0x00 结尾
                uint8_t* mStr = new(nothrow) uint8_t[c_len[1] + 1];
                fread(mStr, c_len[1] + 1, 1, mFile);
                *(sGlobalString + index) = (const char*)mStr;
                delete [] mStr;
                if (GLOBAL_DBUG) printf("\t(index:%d, length:%d)\t\t %s\n", (index+1), c_len[1],
                                 (*(sGlobalString + index)).c_str());
            } else {
                uint16_t* mStr = new(nothrow) uint16_t[c_len[1] + 1];
                fread(mStr, c_len[1] + 1, 1, mFile);
                *(sGlobalString + index) = (const char*)mStr;
                delete [] mStr;
                if (GLOBAL_DBUG) printf("\t(index:%d, length:%d)\t\t %s\n", (index+1), c_len[1],
                                 (*(sGlobalString + index)).c_str());
            }
        }
        printf("\n");
    }
    
    void parseGlobalStringPool(FILE* mFile) {
        printf("GlobalStringPool >> offset 0x%08x\n", baseOffset);
        int offset = baseOffset;
        fseek(mFile, offset, SEEK_SET);
        
        char* temp = new(std::nothrow) char[sizeof(mGlobalStringPool.header.type)];
        fread(temp, sizeof(mGlobalStringPool.header.type), 1, mFile);
        mGlobalStringPool.header.type = *((short*) temp);
        delete [] temp;
        
        fread(temp, sizeof(mGlobalStringPool.header.headerSize), 1, mFile);
        mGlobalStringPool.header.headerSize = *((short*) temp);
        
        temp = new(std::nothrow) char[sizeof(mGlobalStringPool.header.thunkSize)];
        fread(temp, sizeof(mGlobalStringPool.header.thunkSize), 1, mFile);
        mGlobalStringPool.header.thunkSize = *((int*) temp);
        
        fread(temp, sizeof(mGlobalStringPool.stringNum), 1, mFile);
        mGlobalStringPool.stringNum = *((int*) temp);
        
        fread(temp, sizeof(mGlobalStringPool.styleNum), 1, mFile);
        mGlobalStringPool.styleNum = *((int*) temp);
        
        fread(temp, sizeof(mGlobalStringPool.flag), 1, mFile);
        mGlobalStringPool.flag = *((int*) temp);
        
        fread(temp, sizeof(mGlobalStringPool.strOffset), 1, mFile);
        mGlobalStringPool.strOffset = *((int*) temp);
        
        fread(temp, sizeof(mGlobalStringPool.styleOffset), 1, mFile);
        mGlobalStringPool.styleOffset = *((int*) temp);
        
        mGlobalStringPool.toString();
        
        //打印全局字符串池
        printfGlobalStringPool(mFile);
        
        baseOffset += mGlobalStringPool.header.thunkSize;
    }
    
    struct ResTable_package{
        Header header;
        
        uint32_t id;
        uint16_t name[128];  //256 + 32 = 288
        uint32_t typeStrings;
        uint32_t lastPublicType;
        uint32_t keyStrings;
        uint32_t lastPublicKey;
        uint32_t typeIdOffset;
        
        void toString() {
            printf("ResTable_package { header:%s, id:0x%02X, typeStrings:%d,"
                   " lastPublicType=%d, keyStrings:%d, lastPublicKey:%d, typeIdOffset:%d }\n",
                   header.toString().c_str(), id, typeStrings, lastPublicType, keyStrings, lastPublicKey,
                   typeIdOffset);
            showName();
        }
        
        void showName(){
            printf("\tPackageName { name:");
            for(int i = 0; i < 128; i++) {
                unsigned short* cs = name+i;
                printf("%s", (unsigned char*)cs);
            }
            printf(" }\n");
        }
    };
    
    ResTable_package mResTablePackage;
    
    void parseResTablePackage(FILE* mFile) {
        
        printf("ResTable_Package >> offset 0x%08x\n", baseOffset);
        fseek(mFile, baseOffset, SEEK_SET);
        
        char* tmp = new(std::nothrow) char[sizeof(mResTablePackage.header.type)];
        fread(tmp, sizeof(mResTablePackage.header.type), 1, mFile);
        mResTablePackage.header.type = *((uint16_t*)tmp);
        
        tmp = new(std::nothrow) char[sizeof(mResTablePackage.header.headerSize)];
        fread(tmp, sizeof(mResTablePackage.header.headerSize), 1, mFile);
        mResTablePackage.header.headerSize = *((uint16_t*)tmp);
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTablePackage.header.thunkSize)];
        fread(tmp, sizeof(mResTablePackage.header.thunkSize), 1, mFile);
        mResTablePackage.header.thunkSize = *((uint32_t*)tmp);
        
        fread(tmp, sizeof(mResTablePackage.id), 1, mFile);
        mResTablePackage.id = *((uint32_t*)tmp);
        
        fread(mResTablePackage.name, sizeof(uint16_t) * 128, 1, mFile);
        
        fread(tmp, sizeof(mResTablePackage.typeStrings), 1, mFile);
        mResTablePackage.typeStrings = *((uint32_t*)tmp);
    
        fread(tmp, sizeof(mResTablePackage.lastPublicType), 1, mFile);
        mResTablePackage.lastPublicType = *((uint32_t*)tmp);
        
        fread(tmp, sizeof(mResTablePackage.keyStrings), 1, mFile);
        mResTablePackage.keyStrings = *((uint32_t*)tmp);
        
        fread(tmp, sizeof(mResTablePackage.lastPublicKey), 1, mFile);
        mResTablePackage.lastPublicKey = *((uint32_t*)tmp);
        
        fread(tmp, sizeof(mResTablePackage.typeIdOffset), 1, mFile);
        mResTablePackage.typeIdOffset = *((uint32_t*)tmp);
        delete [] tmp;
        
        mResTablePackage.toString();
        
        typeStringPoolThunkOffset = baseOffset + mResTablePackage.typeStrings;
        printf("\ttypeStringPoolThunkOffset>>offset 0x%08x\n", typeStringPoolThunkOffset);
        keyStringPoolThunkOffset = baseOffset + mResTablePackage.keyStrings;
        printf("\tkeyStringPoolThunkOffset>>offset 0x%08x\n", keyStringPoolThunkOffset);
        printf("\n");
        
        baseOffset += mResTablePackage.header.headerSize;
    }
    
    struct ResTypeStringPool {
        Header header;
        
        uint32_t stringCount;
        uint32_t styleCount;
        uint32_t flags;
        uint32_t stringsStart;
        uint32_t stylesStart;
        
        void toString(){
            printf("ResTypeStringPool { header:%s, stringCount:%d,"
                   " styleCount:%d, flags:%d, stringsStart:%d, stylesStart:%d }\n", header.toString().c_str(), stringCount, styleCount, flags, stringsStart, stylesStart);
        }
    };
    
    ResTypeStringPool mResTypeStringPool;
    
    void printResTypeStringPool(FILE* mF) {
        int offset = typeStringPoolThunkOffset + mResTypeStringPool.stringsStart;
        printf("\tResTypeStringPool content >> offset 0x%08x.\n", offset);
    
        fseek(mF, offset, SEEK_SET);
        sTypeString = new string[mResTypeStringPool.stringCount];
        
        uint8_t c_len[2];
        for (int index = 0; index < mResTypeStringPool.stringCount; index++) {
            fread(&c_len, 2, 1, mF);
            //4个字符 需要读 (4+0x0000) * 2
            uint16_t* mStr = new(std::nothrow) uint16_t[c_len[0] + 1];
            fread(mStr, c_len[0]+1, sizeof(uint16_t), mF);
            
            uint8_t* cStr = new(std::nothrow) uint8_t[c_len[0] + 2];
            for (int i = 0; i < c_len[0] + 2; i++) {
                *(cStr+i) = *(uint8_t*)(mStr+i);
            }
            delete [] mStr;
            *(sTypeString + index) = (const char*)cStr;
            if (TYPE_DEBUG) printf("\t\tindex:%d %s\n", index + 1, (*(sTypeString + index)).c_str());
        }
        printf("\n");
    }
    
    void parseResTypeStringPool(FILE* mF) {
        printf("ResTypeStringPoolHeader >> offset 0x%08x.\n", typeStringPoolThunkOffset);
        fseek(mF, typeStringPoolThunkOffset, SEEK_SET);
        
        char* tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.header.type)];
        fread(tmp, sizeof(mResTypeStringPool.header.type), 1, mF);
        mResTypeStringPool.header.type = *(uint16_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.header.headerSize)];
        fread(tmp, sizeof(mResTypeStringPool.header.headerSize), 1, mF);
        mResTypeStringPool.header.headerSize = *(uint16_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.header.thunkSize)];
        fread(tmp, sizeof(mResTypeStringPool.header.thunkSize), 1, mF);
        mResTypeStringPool.header.thunkSize = *(uint32_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.stringCount)];
        fread(tmp, sizeof(mResTypeStringPool.stringCount), 1, mF);
        mResTypeStringPool.stringCount = *(uint32_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.styleCount)];
        fread(tmp, sizeof(mResTypeStringPool.styleCount), 1, mF);
        mResTypeStringPool.styleCount = *(uint32_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.flags)];
        fread(tmp, sizeof(mResTypeStringPool.flags), 1, mF);
        mResTypeStringPool.flags = *(uint32_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.stringsStart)];
        fread(tmp, sizeof(mResTypeStringPool.stringsStart), 1, mF);
        mResTypeStringPool.stringsStart = *(uint32_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTypeStringPool.stylesStart)];
        fread(tmp, sizeof(mResTypeStringPool.stylesStart), 1, mF);
        mResTypeStringPool.stylesStart = *(uint32_t*) tmp;
        delete [] tmp;
        
        mResTypeStringPool.toString();
        printResTypeStringPool(mF);
        
        baseOffset += mResTypeStringPool.header.thunkSize;
    }
    
    struct ResKeyStringPool {
        Header header;
        
        uint32_t stringCount;
        uint32_t styleCount;
        uint32_t flags;
        uint32_t stringsStart;
        uint32_t stylesStart;
        
        void toString(){
            printf("ResKeyStringPool { header:%s, stringCount:%d,"
                   " styleCount:%d, flags:%d, stringsStart:%d, stylesStart:%d }\n", header.toString().c_str(), stringCount, styleCount, flags, stringsStart, stylesStart);
        }
    };
    
    ResKeyStringPool mResKeyStringPool;
    
    void printResKeyStringPool(FILE* mF) {
        int offset = keyStringPoolThunkOffset + mResKeyStringPool.stringsStart;
        printf("\tResKeyStringPool content >> offset 0x%08x.\n", offset);
        
        bool chars = (mResKeyStringPool.flags == (1<<8));
        fseek(mF, offset, SEEK_SET);
        
        uint8_t c_len[2];
        sKeyString = new(nothrow) string[mResKeyStringPool.stringCount];
        
        for (int index = 0; index < mResKeyStringPool.stringCount; index++) {
            fread(&c_len, 2, 1, mF);
            if (chars) {
                uint8_t* mStr = new(std::nothrow) uint8_t[c_len[0] + 1];
                fread(mStr, c_len[0] + 1, 1, mF);
                *(sKeyString + index) = (const char*)mStr;
                delete[] mStr;
                
                if (KEY_DEBUG) {
                    printf("\t(index:%d, length:%d)\t\t %s\n", index+1, c_len[0], (*(sKeyString + index)).c_str());
                }
            } else {
                // nothing
            }
        }
        printf("\n");
    }
    
    void parseResKeyStringPool(FILE* mF) {
        
        printf("Start parse mResKeyStringPool >> offset : 0x%08x.\n", keyStringPoolThunkOffset);
        fseek(mF, keyStringPoolThunkOffset, SEEK_SET);
        
        char* tmp = new(std::nothrow) char[sizeof(mResKeyStringPool.header.type)];
        fread(tmp, sizeof(mResKeyStringPool.header.type), 1, mF);
        mResKeyStringPool.header.type = *(uint16_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.header.headerSize), 1, mF);
        mResKeyStringPool.header.headerSize = *(uint16_t*) tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResKeyStringPool.header.thunkSize)];
        fread(tmp, sizeof(mResKeyStringPool.header.thunkSize), 1, mF);
        mResKeyStringPool.header.thunkSize = *(uint32_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.stringCount), 1, mF);
        mResKeyStringPool.stringCount = *(uint32_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.styleCount), 1, mF);
        mResKeyStringPool.styleCount = *(uint32_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.flags), 1, mF);
        mResKeyStringPool.flags = *(uint32_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.stringsStart), 1, mF);
        mResKeyStringPool.stringsStart = *(uint32_t*) tmp;
        
        fread(tmp, sizeof(mResKeyStringPool.stylesStart), 1, mF);
        mResKeyStringPool.stylesStart = *(uint32_t*) tmp;
        delete [] tmp;
        
        mResKeyStringPool.toString();
        printResKeyStringPool(mF);
        
        baseOffset += mResKeyStringPool.header.thunkSize;
    }
    
    // ------
    
    struct ResTable_typeSpec
    {
        Header header;
        // The type identifier this chunk is holding.  Type IDs start
        // at 1 (corresponding to the value of the type bits in a
        // resource identifier).  0 is invalid.
        uint8_t id;
    
        // Must be 0.
        uint8_t res0;
        // Must be 0.
        uint16_t res1;
    
        // Number of uint32_t entry configuration masks that follow.
        uint32_t entryCount;
        enum {
            // Additional flag indicating an entry is public.
            SPEC_PUBLIC = 0x40000000
        };
        
        void toString(){
            printf("ResTable_typeSpec { header:%s, id:0x%02d, res0:%d, res1:%d, "
                   "entryCount:%d }\n", header.toString().c_str(), id, res0, res1, entryCount);
        }
    };
    
    ResTable_typeSpec mResTable_typeSpec;
    
    void parseResTable_typeSpec(FILE* mF, int offset) {
        
        printf("ResTable_typeSpec >> offset:0x%02x\n", offset);
        
        fseek(mF, offset, SEEK_SET);
        uint8_t* tmp = new(std::nothrow) uint8_t[sizeof(mResTable_typeSpec.header.type)];
        fread(tmp, sizeof(mResTable_typeSpec.header.type), 1, mF);
        mResTable_typeSpec.header.type = *(uint16_t*)tmp;
        
        fread(tmp, sizeof(mResTable_typeSpec.header.headerSize), 1, mF);
        mResTable_typeSpec.header.headerSize = *(uint16_t*)tmp;
        
        tmp = new(std::nothrow) uint8_t[sizeof(mResTable_typeSpec.header.thunkSize)];
        fread(tmp, sizeof(mResTable_typeSpec.header.thunkSize), 1, mF);
        mResTable_typeSpec.header.thunkSize = *(uint32_t*)tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) uint8_t[sizeof(mResTable_typeSpec.id)];
        fread(tmp, sizeof(mResTable_typeSpec.id), 1, mF);
        mResTable_typeSpec.id = *(uint8_t*)tmp;
        
        printf("mResTable_typeSpec>>typeId:%s.\n", (*(sTypeString + (mResTable_typeSpec.id - 1))).c_str());
        
        fread(tmp, sizeof(mResTable_typeSpec.res0), 1, mF);
        mResTable_typeSpec.res0 = *(uint8_t*)tmp;
        
        tmp = new(std::nothrow) uint8_t[sizeof(mResTable_typeSpec.res1)];
        fread(tmp, sizeof(mResTable_typeSpec.res1), 1, mF);
        mResTable_typeSpec.res1 = *(uint8_t*)tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) uint8_t[sizeof(mResTable_typeSpec.entryCount)];
        fread(tmp, sizeof(mResTable_typeSpec.entryCount), 1, mF);
        mResTable_typeSpec.entryCount = *(uint32_t*)tmp;
        delete [] tmp;
        
        mResTable_typeSpec.toString();
        
        printf("\tmResTable_typeSpec.CONIFIG_* >> offset 0x%08x\n", offset+ mResTable_typeSpec.header.headerSize);
        
        tmp = new(std::nothrow) uint8_t[4];
        printf("\t");
        for (int i = 1; i <= mResTable_typeSpec.entryCount; i++) {
            fread(tmp, 4, 1, mF);
            int specArr = *((uint32_t *)tmp);
            
            printf("%08X ", specArr);
            if (i % 8 == 0 && i != 0) {
                printf("\n\t");
            }
        }
        delete [] tmp;
        printf("\n\n");
        
        baseOffset += mResTable_typeSpec.header.thunkSize;
    }
    
    struct ResTable_type{
        Header header;
        
        uint8_t id;
        uint8_t res0;
        uint16_t res1;
        uint32_t entryCount;
        uint32_t entriesStart;
        
        //... 56
        
        void toString() {
            printf("ResTable_type { header:%s, id:0x%02x, res0:%d, res1:%d, entryCount:%d"
                   ", entriesStart:%d }\n", header.toString().c_str(), id, res0, res1, entryCount, entriesStart);
        }
    };
    
    ResTable_type mResTableType;
    
    char* getResId(int entryId){
        char* str = new char[11];
        sprintf(str, "0x%02x%02x%04x", mResTablePackage.id, mResTable_typeSpec.id, entryId);
        //return (mResTablePackage.id << 24) | ((mResTable_typeSpec.id)<<16) | (entryId & 0xFFFF);
        return str;
    }
    
    void parseResTable_type(FILE* mF, int offset) {
        
        printf("ResTable_type offset >> 0x%02x\n", offset);
        fseek(mF, offset, SEEK_SET);
        
        char* tmp = new(std::nothrow) char[sizeof(mResTableType.header.type)];
        fread(tmp, sizeof(mResTableType.header.type), 1, mF);
        mResTableType.header.type = *(uint16_t*)tmp;
        
        fread(tmp, sizeof(mResTableType.header.headerSize), 1, mF);
        mResTableType.header.headerSize = *(uint16_t*)tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTableType.header.thunkSize)];
        fread(tmp, sizeof(mResTableType.header.thunkSize), 1, mF);
        mResTableType.header.thunkSize = *(uint32_t*)tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTableType.id)];
        fread(tmp, sizeof(mResTableType.id), 1, mF);
        mResTableType.id = *(uint8_t*)tmp;
        
        fread(tmp, sizeof(mResTableType.res0), 1, mF);
        mResTableType.res0 = *(uint8_t*)tmp;
        delete[] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTableType.res1)];
        fread(tmp, sizeof(mResTableType.res1), 1, mF);
        mResTableType.res1 = *(uint16_t*)tmp;
        delete [] tmp;
        
        tmp = new(std::nothrow) char[sizeof(mResTableType.entryCount)];
        fread(tmp, sizeof(mResTableType.entryCount), 1, mF);
        mResTableType.entryCount = *(uint32_t*)tmp;
        
        fread(tmp, sizeof(mResTableType.entriesStart), 1, mF);
        mResTableType.entriesStart = *(uint32_t*)tmp;
        delete [] tmp;
        
        // -----------ResTable_Config  56
        tmp = new(std::nothrow) char[mResTableType.header.headerSize - 20];
        fread(tmp, mResTableType.header.headerSize - 20, 1, mF);
        /*
        uint32_t config_size = *((uint32_t*)tmp);
        uint32_t config_imsi = *((uint32_t*)(tmp + 4));
        uint32_t config_locale = *((uint32_t*)(tmp + 8));
        uint32_t config_screenType = *((uint32_t*)(tmp + 12));
        uint32_t config_input = *((uint32_t*)(tmp + 16));
        uint32_t config_screenSize = *((uint32_t*)(tmp + 20));
        uint32_t config_version = *((uint32_t*)(tmp + 24));
        uint32_t config_screenConfig = *((uint32_t*)(tmp + 28));
        uint32_t config_screenSizeDp = *((uint32_t*)(tmp + 32));
        char config_localeScript[4];
        memcmp(config_localeScript, tmp + 36, 4);
        char config_localeVariant[8];
        memcmp(config_localeVariant, tmp + 40, 8);
        uint32_t screenConfig2 = *((uint32_t*)(tmp + 48));
        */
        delete [] tmp;
        printf("Skip config ...");
        
        mResTableType.toString();
        
        printf("\t\tElement>> offset 0x%02x\n", offset + mResTableType.header.headerSize);
        fseek(mF , offset + mResTableType.header.headerSize, SEEK_SET);
        
        uint32_t* items = new(nothrow) uint32_t[mResTableType.entryCount];
        fread(items, mResTableType.entryCount, sizeof(uint32_t), mF);
        
        int hasNum = 0;
        printf("\t\tElement:\n\t");
        for (int i = 1; i <= mResTableType.entryCount; i++) {
            printf("%08X ", *(items + i - 1));
            if (i % 8 == 0 && i !=0) {
                printf("\n\t");
            }
            if (*(items + i - 1) != 0xFFFFFFFF) {
                hasNum ++;
            }
        }
            
        printf("\n\t\tSkip element... >> %d\n", hasNum);
        
        /*printf("Config: { size:%d, imsi:%d, locale:%d, screenType:%d, input:%d, screenSize:%d, version:%d"
               " screenConfig:%d, screenSizeDp:%d, localeScript:%s, localeVariant:%s, screenConfig2:%d }\n",
               config_size, config_imsi, config_locale, config_screenType, config_input, config_screenSize,
               config_version, config_screenConfig, config_screenSizeDp, config_localeScript,
               config_localeVariant, screenConfig2);*/
        
        printf("\t\tStart parse name/value ...\n");
        printf("\tEntry >> offset 0x%02x\n", offset + mResTableType.entriesStart);
        
        int offsetEntry = offset + mResTableType.entriesStart, bodySize = 0;
        fseek(mF, offsetEntry, SEEK_SET);
        
        for (int i = 0; i < mResTableType.entryCount; i++) {
            //offsetEntry += bodySize;
            if (*(items + i) == -1) {
                //printf("\t>>Skip %d->%d\n", i, *(items + i));
                continue;
            }
            
            fseek(mF, offsetEntry + *(items + i), SEEK_SET);
            printf("\tOffsetEntry >> 0x%08x >> ", offsetEntry);
            
            if (mResTableType.id == 0x05) {
                if (preBoolIdStart != 0){
                    preBoolIdStart++;
                    printf("  resId:0x%08x  ", (mResTablePackage.id << 24 | mResTableType.id << 16 | (preBoolIdStart & 0xFFFF)));
                } else {
                    printf("  resId:0x%08x  ", (mResTablePackage.id << 24 | mResTableType.id << 16 | (i & 0xFFFF)));
                }
            } else {
                printf("  resId:0x%08x  ", (mResTablePackage.id << 24 | mResTableType.id << 16 | (i & 0xFFFF)));
            }
            
            uint8_t* entry = new(nothrow) uint8_t[8];
            fread(entry, 8, sizeof(uint8_t), mF);
            
            uint16_t entrySize = *((uint16_t*) entry);
            uint16_t entryFlags = *((uint16_t*) (entry + sizeof(uint16_t)));
            uint32_t entryKey = *((uint32_t*) (entry + sizeof(uint16_t) * 2));
            delete[] entry;
            
            if ((entryFlags & 0x0001) == 1) { // name/vaule
                uint8_t* mapEntry = new(nothrow) uint8_t[sizeof(uint32_t)*2];
                fread(mapEntry, sizeof(uint32_t) * 2, 1, mF);
                
                uint32_t mapEntry_parent = *((uint32_t*)(mapEntry));
                uint32_t mapEntry_count = *((uint32_t*)(mapEntry + sizeof(uint32_t)));
                delete [] mapEntry;
                
                printf("\tResTable_map_entry >> (entrySize:%d, entryKey:%d::%s, mapEntry_parent:%d,"
                       " mapEntry_count:%d)\n",
                       entrySize, entryKey, (*(sKeyString+entryKey)).c_str(),
                       mapEntry_parent, mapEntry_count);
                
                for (int i = 0; i < mapEntry_count; i++ ) {
                    uint8_t* resValue = new(nothrow) uint8_t[sizeof(uint32_t)]; // ResTable_map
                    fread(resValue, sizeof(uint32_t), 1, mF);
                    uint32_t mapName = *((uint16_t*)(resValue));
                    delete [] resValue;
                    
                    resValue = new(nothrow) uint8_t[sizeof(uint16_t)]; //Res_Value
                    fread(resValue, sizeof(uint16_t), 1, mF);
                    uint16_t valueSize = *((uint16_t*)(resValue));
                    delete [] resValue;
                    
                    resValue = new(nothrow) uint8_t[sizeof(uint8_t)];
                    fread(resValue, sizeof(uint8_t), 1, mF);
                    uint16_t valueRes0 = *((uint8_t*)(resValue));
                    
                    resValue = new(nothrow) uint8_t[sizeof(uint8_t)];
                    fread(resValue, sizeof(uint8_t), 1, mF);
                    uint16_t valueDataType = *((uint8_t*)(resValue));
                    delete [] resValue;
                    
                    resValue = new(nothrow) uint8_t[sizeof(uint32_t)];
                    fread(resValue, sizeof(uint32_t), 1, mF);
                    uint32_t valueData = *((uint32_t*)(resValue));
                    delete [] resValue;
                    
                    printf("\tValueDataType>>%d mapName>>%d \n", valueDataType, mapName);
                    switch (valueDataType) {
                        case 0x00:
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:null, valueData:%d.\n", valueSize, valueRes0,
                                   valueData);
                            break;
                        case 0x01:// ref类型
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:ref, %s>>0x%08x>>%s.\n", valueSize, valueRes0,
                                   (*(sKeyString+entryKey)).c_str(),
                                   valueData, (valueData >> 24 == 0x7f) ? "@":"@android:"); // 因为从0开始算起
                            break;
                        case 0x02:// attr类型
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:ref, %s>>0x%08x>>%s.\n", valueSize, valueRes0,
                                   (*(sKeyString+entryKey)).c_str(),
                                   valueData, (valueData >> 24 == 0x7f) ? "@":"@android:");
                            break;
                        case 0x03:
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:string, data:%s.\n", valueSize, valueRes0,
                                   (*(sGlobalString+valueData+1)).c_str());
                            break;
                        case 0x05:
                            {//dimension
                                string dim[] = {"px", "dip", "sp", "pt", "in", "mm"};
                                printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                       "%s>>%d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                            }
                            break;
                        case 0x10:
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   " %s:%d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                            break;
                        case 0x11:
                            {
                                printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                       " valueDataType:bool, %s>>0x%08x.\n", valueSize, valueRes0,
                                       (*(sKeyString+entryKey)).c_str(), valueData);
                            }
                            break;
                        case 0x12:
                            {
                                bool res = (valueData != 0);
                                printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                       " valueDataType:bool, %s>>%s.\n", valueSize, valueRes0,
                                       (*(sKeyString+entryKey)).c_str(), res ? "true":"false");
                            }
                            break;
                        default:
                            break;
                    }
                }
                bodySize = entrySize + mapEntry_count * 12;
            } else {
                uint8_t* resValue = new(nothrow) uint8_t[sizeof(uint16_t)];
                fread(resValue, sizeof(uint16_t), 1, mF);
                uint16_t valueSize = *((uint16_t*)(resValue));
                delete [] resValue;
                
                resValue = new(nothrow) uint8_t[sizeof(uint8_t)];
                fread(resValue, sizeof(uint8_t), 1, mF);
                uint16_t valueRes0 = *((uint8_t*)(resValue));
                
                resValue = new(nothrow) uint8_t[sizeof(uint8_t)];
                fread(resValue, sizeof(uint8_t), 1, mF);
                short short_valueDataType = *((uint8_t*)(resValue));
                int valueDataType = short_valueDataType;
                delete [] resValue;
                
                resValue = new(nothrow) uint8_t[sizeof(uint32_t)];
                fread(resValue, sizeof(uint32_t), 1, mF);
                uint32_t valueData = *((uint32_t*)(resValue));
                delete [] resValue;
                
                printf("ValueDataType>>%d\n", valueDataType);
                switch (valueDataType) {
                    case 0x01:// 引用类型
                        printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                               " valueDataType:ref, %s>>0x%08x>>%s.\n", valueSize, valueRes0,
                               (*(sKeyString+entryKey)).c_str(),
                               valueData, (valueData >> 24 == 0x7f) ? "@":"@android:"); // 因为从0开始算起
                        break;
                    case 0x03:
                        printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                               " valueDataType:string, %s>>%s.\n", valueSize, valueRes0,
                               (*(sKeyString+entryKey)).c_str(),
                               (*(sGlobalString + valueData + 1)).c_str()); // 因为从0开始算起
                        break;
                    case 0x04: //float
                        {
                            string dim[] = {"px", "dip", "sp", "pt", "in", "mm"};
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   "%s >> float >> %d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                        }
                        break;
                    case 0x05:
                        {//dimension
                            string dim[] = {"px", "dip", "sp", "pt", "in", "mm"};
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   "%s>>%d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                        }
                        break;
                    case 0x06:{ // 复数
                            printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                                   "%s>>复数>>%d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                        }
                        break;
                    case 0x10:
                        printf("\t\t__(key::value) >> valueSize:%d, valueRes0:%d,"
                               "%s>>%d.\n", valueSize, valueRes0, (*(sKeyString + entryKey)).c_str(), valueData);
                        break;
                    case 0x11:
                        {
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                               " valueDataType:bool, %s>>0x%08x.\n", valueSize, valueRes0,
                               (*(sKeyString+entryKey)).c_str(), valueData);
                        }
                        break;
                    case 0x12:
                        {
                            bool res = (valueData != 0);
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:bool, %s>>%s.\n", valueSize, valueRes0,
                                   (*(sKeyString+entryKey)).c_str(), res ? "true":"false");
                        }
                        break;
                    case 0x1c:
                        {
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                               " valueDataType:#aarrggbb, %s>>#%08x.\n", valueSize, valueRes0,
                               (*(sKeyString+entryKey)).c_str(), valueData);
                        }
                        break;
                    case 0x1d:
                        {
                            printf("\t\t__Res_Value >> (key::value) >> valueSize:%d, valueRes0:%d,"
                                   " valueDataType:#rrggbb, %s>>#%08x.\n", valueSize, valueRes0,
                                   (*(sKeyString+entryKey)).c_str(), valueData);
                        }
                        break;
                    
                }
                bodySize = 8 + 8;
            }
        }
        
        //兼容
        if (mResTableType.id == 0x05) {
            preBoolIdStart = hasNum - 1;
        }
        
        offsetEntry += bodySize;
        printf("End Entry >> offset 0x%08x \n\n", offsetEntry);
        baseOffset += mResTableType.header.thunkSize;
    }
    
    int main(int argc, const char * argv[]) {
        FILE* mFile = fopen(RESOURCES_ARSC, "r");
        if (nullptr == mFile) {
            printf("Unable open %s", RESOURCES_ARSC);
            return 1;
        }
        
        printf("Start parse resources.arsc ...\n");
        parseResTableHeader(mFile);
        
        printf("Start parse globalStringPool ...\n");
        parseGlobalStringPool(mFile);
        
        printf("Start parse ResTable_Package ...\n");
        parseResTablePackage(mFile);
        
        printf("Start parse ResTypeStringPool ...\n");
        parseResTypeStringPool(mFile);
        
        printf("Start parse ResKeyStringPool ...\n");
        parseResKeyStringPool(mFile);
        
        specOffset = baseOffset;
        
        Header mSpecHeader;
        while (baseOffset < mResTableHeader.header.thunkSize) {
            printf(">> NewBaseOffset >> 0x%08x\n", baseOffset);
            
            fseek(mFile, baseOffset, SEEK_SET);
            char* header = new(nothrow) char[8];
            fread(header, 8, 1, mFile);
            
            mSpecHeader.type = *((uint16_t*) header);
            mSpecHeader.headerSize = *((uint16_t*) (header + 2));
            mSpecHeader.thunkSize = *((uint32_t*) (header + 4));
            delete [] header;
            
            //Spec
            if (mSpecHeader.type == 0x0202) {
                printf("Start parse ResTable_typeSpec ...\n");
                parseResTable_typeSpec(mFile, baseOffset);
            } else {
                printf("Start parse ResTable_type ...\n");
                parseResTable_type(mFile, baseOffset);
            }
        }
        
        fclose(mFile);
        return 0;
    }
    

    剩余的问题
    1、解析Color多个版本重名的时候 color-v23/会id会错乱
    2、float类型数据如何展示, 复数类型显示
    3、剩下几种展示尚未遇到。

    相关文章

      网友评论

          本文标题:2019-02-08 手动安装包解析resources.arsc

          本文链接:https://www.haomeiwen.com/subject/sknosqtx.html