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

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

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

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

#include 
#include 

#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文件)