由于工作原因,需要直接扫描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、剩下几种展示尚未遇到。