首页
社区
课程
招聘
[原创]AndroidManifest 二进制解析笔记
发表于: 2024-1-18 18:56 13737

[原创]AndroidManifest 二进制解析笔记

2024-1-18 18:56
13737

自笔者开始学习Android逆向的第一天起就一直被一个问题所困扰,那就是 AndroidManifest 的编码总是会有问题,相信大家在使用 apktool 的时候如果直接 java -jar apktool.jar d HelloWorld.apk 那么在回编译的时候大概率会出现报错,这是因为 apktool 的资源的解析是有问题的,添加参数 -r 可以屏蔽资源的解析,但这样一来 AndroidManifest 就无法解析,而在逆向的过程中很常见的需求就是修改 AndroidManifest,例如修改启动类又或者添加debug标志,所以很容易想到的方法就是 apktool.jar 屏蔽资源解析,然后使用针对 AndroidManifest 修改的工具,这其中有许多大佬开源了自己的 AndroidManifest 修改工具,但在笔者的使用过程中总是会有这样那样的问题,正好最近有个需求是修改 AndroidManifest,所以在这里记录下 AndroidManifest.xml 二进制文件格式分析。

首先按照惯例先贴上这张神图,可以说总结的非常全面,但此图也有自己的问题,那就是难以让读者在心中对整个 AndroidManifest 格式有一个大概的雏形。

image-20240118115059789

在这张图中我们需要明白整个 AndroidManifest 格式分为六大区域,七种 Chunk 类型,依次分别为 AndroidManifestHead、StringChunk、ResourceChunk、StartNamespaceChunk、StartTagChunk&EndTagChunk、EndNameSpaceChunk,其中多数情况 ResourceChunk为空,不太需要处理。

image-20240118120250532

AndroidManifestHead 占据 AndroidManifest 的起始8个字节,magic 标志着这个文件是 AndroidManifest 格式,file_size 记录 AndroidManifest.xml 文件的大小,这种文件头可以说是异常简单了。

笔者在分析完 AndroidManifest 后总结出 StringChunk、ResourceChunk、StartNamespaceChunk、StartTagChunk、EndTagChunk、EndNameSpaceChunk 这六种块的前 8 个字节是一样的

由此我们可以先对 AndroidManifest 进行一个大致的遍历

输出的结果大致为这样,可以完美对应上方的结构图

StringChunk 的格式就略显复杂了,首先我们先看下 StringChunk 的头部,这部分共计 7 * 4 = 28 个字节的大小

StringChunk 的头部后面跟着的就是 StringOffsets,这部分区域是的大小为 scStringCount *4,其中每4个字节记录了对应 StringItem 在文件中的的偏移,这里画了一个图可以直观理解一下。

image-20240118150033561

根据上述的分析,故此我们可以定义如下两个类 StringItem、StringChunk

StartNamespaceChunk 中主要的字段为 sncPrefix,可以轻易解析通过 StringChunk 解析

和 StartNamespaceChunk 不能说一模一样,只能说完全相同

StartTagChunk 也是稍显复杂的一个结构,因为其中包含了另一个结构 AttributeChunk,这里同样给出一个关系结构图

image-20240118152802749

由此我们可以定义如下两个类 AttributeChunk、StartTagChunk

EndTagChunk 的结构就没 StartTagChunk 那么复杂了,可以说简单的很

自此我们在为借助其他第三方模块的完成了绝大部分 Chunk 的解析,AndroidManifest 也变得不再神秘,那么就简单的 show 一下吧

现在 AndroidManifest 已经可以任由我们搓扁揉圆了,重新组装 StringChunk 一下,就可以向其中添加任意的字符串

当 AndroidManifest 中已存在 ApplicationName 时直接修改其字符串偏移即可

AndroidManifest 的数据结构总体来讲不算过于复杂,和PE/ELF比算是小巫见大巫了,不过由于搞得不是很精细,后续还需要多做一些测试

Android逆向之旅—解析编译之后的AndroidManifest文件格式

AndroidManifest二进制文件格式分析

Android逆向笔记 —— AndroidManifest.xml 文件格式解析

struct sAndroidManifestHead {
    int magic;      // 标志着这个文件是 AndroidManifest 格式
    int file_size;  // 记录 AndroidManifest.xml  文件的大小
};
struct sAndroidManifestHead {
    int magic;      // 标志着这个文件是 AndroidManifest 格式
    int file_size;  // 记录 AndroidManifest.xml  文件的大小
};
class Chunk {
public:
    struct sChunk {
        int cSignature;         // 块类型标识
                                // cSignature = 0x001c0001  stringChunk
                                // cSignature = 0x00080180  resourceChunk
                                // cSignature = 0x00100100  startNameSpaceChunk
                                // cSignature = 0x00100102  startTagChunk
                                // cSignature = 0x00100103  endTagChunk
                                // cSignature = 0x00100101  EndNameSpaceChunk
        int cSize;              // 块的大小
    };
 
    char* addr;
    int cSignature;
    int cSize;
    std::string type;
 
    Chunk(char* chunk_addr) {
        addr = chunk_addr;
        sChunk* mChunk = (sChunk*)chunk_addr;
 
        if (mChunk->cSignature == 0x001c0001) {
            type = "StringChunk";
        }
        else if (mChunk->cSignature == 0x00080180) {
            type = "ResourceChunk";
        }
        else if (mChunk->cSignature == 0x00100100) {
            type = "StartNameSpaceChunk";
        }
        else if (mChunk->cSignature == 0x00100102) {
            type = "StartTagChunk";
        }
        else if (mChunk->cSignature == 0x00100103) {
            type = "EndTagChunk";
        }
        else if (mChunk->cSignature == 0x00100101) {
            type = "EndNameSpaceChunk";
        }
        else {
            type = "Unknown";
        }
        cSize = mChunk->cSize;
    };
 
    Chunk* NextChunk() {
        return new Chunk((addr + cSize));
    }
};
class Chunk {
public:
    struct sChunk {
        int cSignature;         // 块类型标识
                                // cSignature = 0x001c0001  stringChunk
                                // cSignature = 0x00080180  resourceChunk
                                // cSignature = 0x00100100  startNameSpaceChunk
                                // cSignature = 0x00100102  startTagChunk
                                // cSignature = 0x00100103  endTagChunk
                                // cSignature = 0x00100101  EndNameSpaceChunk
        int cSize;              // 块的大小
    };
 
    char* addr;
    int cSignature;
    int cSize;
    std::string type;
 
    Chunk(char* chunk_addr) {
        addr = chunk_addr;
        sChunk* mChunk = (sChunk*)chunk_addr;
 
        if (mChunk->cSignature == 0x001c0001) {
            type = "StringChunk";
        }
        else if (mChunk->cSignature == 0x00080180) {
            type = "ResourceChunk";
        }
        else if (mChunk->cSignature == 0x00100100) {
            type = "StartNameSpaceChunk";
        }
        else if (mChunk->cSignature == 0x00100102) {
            type = "StartTagChunk";
        }
        else if (mChunk->cSignature == 0x00100103) {
            type = "EndTagChunk";
        }
        else if (mChunk->cSignature == 0x00100101) {
            type = "EndNameSpaceChunk";
        }
        else {
            type = "Unknown";
        }
        cSize = mChunk->cSize;
    };
 
    Chunk* NextChunk() {
        return new Chunk((addr + cSize));
    }
};
int main() {
    const char* AndroidManifestPath = "C:\\Users\\lxz\\source\\repos\\AndroidManifestEditor\\AndroidManifest.xml";
    char* mAndroidManifestData = read_file(AndroidManifestPath);
    sAndroidManifestHead* mAndroidManifestHead = (sAndroidManifestHead*)mAndroidManifestData;
 
    std::vector<Chunk*> chunkList;
 
    Chunk* chunk = new Chunk(((char*)mAndroidManifestHead + sizeof(sAndroidManifestHead)));
    while (chunk->type != "Unknown") {
        chunkList.push_back(chunk);
        chunk = chunk->NextChunk();
    }
 
    for (Chunk* chunk : chunkList) {
        printf("%s\n\n", chunk->type.c_str());
        delete chunk;
    }
    chunkList.clear();
}
int main() {
    const char* AndroidManifestPath = "C:\\Users\\lxz\\source\\repos\\AndroidManifestEditor\\AndroidManifest.xml";
    char* mAndroidManifestData = read_file(AndroidManifestPath);
    sAndroidManifestHead* mAndroidManifestHead = (sAndroidManifestHead*)mAndroidManifestData;
 
    std::vector<Chunk*> chunkList;
 
    Chunk* chunk = new Chunk(((char*)mAndroidManifestHead + sizeof(sAndroidManifestHead)));
    while (chunk->type != "Unknown") {
        chunkList.push_back(chunk);
        chunk = chunk->NextChunk();
    }
 
    for (Chunk* chunk : chunkList) {
        printf("%s\n\n", chunk->type.c_str());
        delete chunk;
    }
    chunkList.clear();
}
stringChunk
 
resourceChunk
 
startNameSpaceChunk
 
startTagChunk
 
startTagChunk
 
endTagChunk
 
startTagChunk
 
......
 
endTagChunk
 
endTagChunk
 
EndNameSpaceChunk
stringChunk
 
resourceChunk
 
startNameSpaceChunk
 
startTagChunk
 
startTagChunk
 
endTagChunk
 
startTagChunk
 
......
 
endTagChunk
 
endTagChunk
 
EndNameSpaceChunk
struct sStringChunk {
    int scSignature;        // 块类型标识
    int scSize;             // 块大小
    int scStringCount;      // 字符串数量
    int scStyleCount;       // 未知
    int scUNKNOWN;          // 未知
    int scStringPoolOffset; // 字符串集合的偏移
    int scStylePoolOffset;  // 未知
};
struct sStringChunk {
    int scSignature;        // 块类型标识
    int scSize;             // 块大小
    int scStringCount;      // 字符串数量
    int scStyleCount;       // 未知
    int scUNKNOWN;          // 未知
    int scStringPoolOffset; // 字符串集合的偏移
    int scStylePoolOffset;  // 未知
};
class StringItem {
public:
    std::wstring wstr;
    char* raw;
    int size;
    StringItem(char* addr) {
        size = 2 + (*(wchar_t*)addr) * 2 + 2;
        wstr = std::wstring((wchar_t*)(addr + 2));
        raw = addr;
    }
    StringItem(std::wstring v_wstr) {
        wstr = v_wstr;
        size = 2 + wstr.length() * 2 + 2;
        raw = (char*)malloc(size);
        memset(raw, 0, size);
        *(int*)raw = wstr.length();
        memcpy(raw + 2, wstr.c_str(), wstr.length() * 2);
    }
};
 
class StringChunk {
public:
    struct sStringChunk {
        int scSignature;        // 块类型标识
        int scSize;             // 块大小
        int scStringCount;      // 字符串数量
        int scStyleCount;       // 未知
        int scUNKNOWN;          // 未知
        int scStringPoolOffset; // 字符串集合的偏移
        int scStylePoolOffset;  // 未知
    };
 
    char* addr;
    int scSignature;
    int scSize;
    int scStringCount; 
    int scStyleCount;
    int scUNKNOWN;
    int scStringPoolOffset;
    int scStylePoolOffset;
    int* scStringOffsets;
 
    std::vector<int> StringOffset_list;
    std::vector<StringItem*> StringItem_list;
 
    StringChunk(char* chunk_addr) {
        addr = chunk_addr;
         
        scSignature = ((sStringChunk*)chunk_addr)->scSignature;
        scSize = ((sStringChunk*)chunk_addr)->scSize;
        scStringCount = ((sStringChunk*)chunk_addr)->scStringCount;
        scStyleCount = ((sStringChunk*)chunk_addr)->scStyleCount;
        scUNKNOWN = ((sStringChunk*)chunk_addr)->scUNKNOWN;
        scStringPoolOffset = ((sStringChunk*)chunk_addr)->scStringPoolOffset;
        scStylePoolOffset = ((sStringChunk*)chunk_addr)->scStylePoolOffset;
 
        scStringOffsets = (int*)(chunk_addr + sizeof(sStringChunk));
        for (int i = 0; i < scStringCount; i++) {
            StringOffset_list.push_back(*(scStringOffsets + i));
            StringItem_list.push_back(new StringItem(addr + scStringPoolOffset + *(scStringOffsets + i)));
        }
    };
 
    std::wstring get_string(int id) {
        return (wchar_t*)(addr + scStringPoolOffset + *(scStringOffsets + id) + 2);
    }
 
    void show_all_string() {
        for(int i = 0; i < scStringCount; i++) {
            printf("%S \n", get_string(i).c_str());
        }
    }
};
class StringItem {
public:
    std::wstring wstr;
    char* raw;
    int size;
    StringItem(char* addr) {
        size = 2 + (*(wchar_t*)addr) * 2 + 2;
        wstr = std::wstring((wchar_t*)(addr + 2));
        raw = addr;
    }
    StringItem(std::wstring v_wstr) {
        wstr = v_wstr;
        size = 2 + wstr.length() * 2 + 2;
        raw = (char*)malloc(size);
        memset(raw, 0, size);
        *(int*)raw = wstr.length();
        memcpy(raw + 2, wstr.c_str(), wstr.length() * 2);
    }
};
 
class StringChunk {
public:
    struct sStringChunk {
        int scSignature;        // 块类型标识
        int scSize;             // 块大小
        int scStringCount;      // 字符串数量
        int scStyleCount;       // 未知
        int scUNKNOWN;          // 未知
        int scStringPoolOffset; // 字符串集合的偏移
        int scStylePoolOffset;  // 未知
    };
 
    char* addr;
    int scSignature;
    int scSize;
    int scStringCount; 
    int scStyleCount;
    int scUNKNOWN;
    int scStringPoolOffset;
    int scStylePoolOffset;
    int* scStringOffsets;
 
    std::vector<int> StringOffset_list;
    std::vector<StringItem*> StringItem_list;
 
    StringChunk(char* chunk_addr) {
        addr = chunk_addr;
         
        scSignature = ((sStringChunk*)chunk_addr)->scSignature;
        scSize = ((sStringChunk*)chunk_addr)->scSize;
        scStringCount = ((sStringChunk*)chunk_addr)->scStringCount;
        scStyleCount = ((sStringChunk*)chunk_addr)->scStyleCount;
        scUNKNOWN = ((sStringChunk*)chunk_addr)->scUNKNOWN;
        scStringPoolOffset = ((sStringChunk*)chunk_addr)->scStringPoolOffset;
        scStylePoolOffset = ((sStringChunk*)chunk_addr)->scStylePoolOffset;
 
        scStringOffsets = (int*)(chunk_addr + sizeof(sStringChunk));
        for (int i = 0; i < scStringCount; i++) {
            StringOffset_list.push_back(*(scStringOffsets + i));
            StringItem_list.push_back(new StringItem(addr + scStringPoolOffset + *(scStringOffsets + i)));
        }
    };
 
    std::wstring get_string(int id) {
        return (wchar_t*)(addr + scStringPoolOffset + *(scStringOffsets + id) + 2);
    }
 
    void show_all_string() {
        for(int i = 0; i < scStringCount; i++) {
            printf("%S \n", get_string(i).c_str());
        }
    }
};
class StartNamespaceChunk {
public:
    struct sStartNamespaceChunk {
        int scSignature;    // 块类型标识
        int scSize;         // 块大小
        int sncLineNumber;  // 该属性在明文中的行数
        int sncUNKNOWN;     // 未知
        int sncPrefix;      // 字符串索引
        int sncUri;         // 字符串 Uri 索引
    };
 
    char* addr;
    int scSignature;
    int scSize;
    int sncLineNumber;
    int sncUNKNOWN;
    int sncPrefix;
    int sncUri;
 
    StringChunk*& mStringChunk;
 
    StartNamespaceChunk(char* chunk_addr, StringChunk** vStringChunk):mStringChunk(*vStringChunk) {
        addr = chunk_addr;
        scSignature = ((sStartNamespaceChunk*)addr)->scSignature;
        scSize = ((sStartNamespaceChunk*)addr)->scSize;
        sncLineNumber = ((sStartNamespaceChunk*)addr)->sncLineNumber;
        sncUNKNOWN = ((sStartNamespaceChunk*)addr)->sncUNKNOWN;
        sncPrefix = ((sStartNamespaceChunk*)addr)->sncPrefix;
        sncUri = ((sStartNamespaceChunk*)addr)->sncUri;
    };
 
    std::wstring get_string() {
        return mStringChunk->get_string(sncPrefix);
    }
};
class StartNamespaceChunk {
public:
    struct sStartNamespaceChunk {
        int scSignature;    // 块类型标识
        int scSize;         // 块大小
        int sncLineNumber;  // 该属性在明文中的行数
        int sncUNKNOWN;     // 未知
        int sncPrefix;      // 字符串索引
        int sncUri;         // 字符串 Uri 索引
    };
 
    char* addr;
    int scSignature;
    int scSize;
    int sncLineNumber;
    int sncUNKNOWN;
    int sncPrefix;
    int sncUri;
 
    StringChunk*& mStringChunk;
 
    StartNamespaceChunk(char* chunk_addr, StringChunk** vStringChunk):mStringChunk(*vStringChunk) {
        addr = chunk_addr;
        scSignature = ((sStartNamespaceChunk*)addr)->scSignature;
        scSize = ((sStartNamespaceChunk*)addr)->scSize;
        sncLineNumber = ((sStartNamespaceChunk*)addr)->sncLineNumber;
        sncUNKNOWN = ((sStartNamespaceChunk*)addr)->sncUNKNOWN;
        sncPrefix = ((sStartNamespaceChunk*)addr)->sncPrefix;
        sncUri = ((sStartNamespaceChunk*)addr)->sncUri;
    };
 
    std::wstring get_string() {
        return mStringChunk->get_string(sncPrefix);
    }
};
class EndNameSpaceChunk {
public:
    struct sEndTagChunk {
        int encSignature;
        int encSize;
        int encLineNumber;
        int encUNKNOWN;
        int encPrefix;
        int encUri;
    };
 
    char* addr;
    int encSignature;
    int encSize;
    int encLineNumber;
    int encUNKNOWN;
    int encPrefix;
    int encUri;
 
    StringChunk*& mStringChunk;
 
    EndNameSpaceChunk(char* chunk_addr, StringChunk** vStringChunk): mStringChunk(*vStringChunk) {
        addr = chunk_addr;
        encSignature = ((sEndTagChunk*)addr)->encSignature;
        encSize = ((sEndTagChunk*)addr)->encSize;
        encLineNumber = ((sEndTagChunk*)addr)->encLineNumber;
        encUNKNOWN = ((sEndTagChunk*)addr)->encUNKNOWN;
        encPrefix = ((sEndTagChunk*)addr)->encPrefix;
        encUri = ((sEndTagChunk*)addr)->encUri;
    };
 
    std::wstring get_string() {
        return mStringChunk->get_string(encPrefix);
    }
};
class EndNameSpaceChunk {
public:
    struct sEndTagChunk {
        int encSignature;
        int encSize;
        int encLineNumber;
        int encUNKNOWN;
        int encPrefix;
        int encUri;
    };
 
    char* addr;
    int encSignature;
    int encSize;
    int encLineNumber;
    int encUNKNOWN;
    int encPrefix;
    int encUri;
 
    StringChunk*& mStringChunk;
 
    EndNameSpaceChunk(char* chunk_addr, StringChunk** vStringChunk): mStringChunk(*vStringChunk) {
        addr = chunk_addr;
        encSignature = ((sEndTagChunk*)addr)->encSignature;
        encSize = ((sEndTagChunk*)addr)->encSize;
        encLineNumber = ((sEndTagChunk*)addr)->encLineNumber;
        encUNKNOWN = ((sEndTagChunk*)addr)->encUNKNOWN;
        encPrefix = ((sEndTagChunk*)addr)->encPrefix;
        encUri = ((sEndTagChunk*)addr)->encUri;
    };
 
    std::wstring get_string() {
        return mStringChunk->get_string(encPrefix);
    }
};
class AttributeChunk {
public:
    struct sAttributeChunk {
        int acNamespaceUri; // 命名空间 Uri 索引
        int acName;         // 属性名称(key)的索引
        int acValueStr;     // 属性内容(value)的索引(当前类型为字符串时使用该属性)
        int acType;         // 属性内容(value)的类型(String、Int、Bool ...)
        int acData;         // 属性内容(value)的索引
    };
 
    int acNamespaceUri;
    int acName;        
    int acValueStr;    
    int acType;        
    int acData;        
 
    char* addr;
    StringChunk*& mStringChunk;
    StartNamespaceChunk*& mStartNamespaceChunk;
 
    AttributeChunk(char* chunk_addr, StringChunk** vStringChunk, StartNamespaceChunk** vStartNamespaceChunk):mStringChunk(*vStringChunk), mStartNamespaceChunk(*vStartNamespaceChunk) {
        addr = chunk_addr;
        acNamespaceUri = ((sAttributeChunk*)addr)->acNamespaceUri;
        acName = ((sAttributeChunk*)addr)->acName;
        acValueStr = ((sAttributeChunk*)addr)->acValueStr;
        acType = ((sAttributeChunk*)addr)->acType;
        acData = ((sAttributeChunk*)addr)->acData;
    }
 
    std::wstring get_srting() {
        std::wstring resData = L"";
        // 当 acNamespaceUri 为 -1 时,命名空间为空
        if (acNamespaceUri != -1 && acNamespaceUri == mStartNamespaceChunk->sncUri) {
            resData = mStartNamespaceChunk->get_string() + L":";
        }
 
        // 属性名称
        resData += mStringChunk->get_string(acName);
        resData += L"=";
 
        // 属性值的数据类型
        if ((acType >> 24) == 0x10) {
            // 整数
            resData += L"\"";
            resData += std::to_wstring(acData);
            resData += L"\"";
        }
        else if ((acType >> 24) == 0x3) {
            // 字符串
            resData += L"\"";
            resData += mStringChunk->get_string(acValueStr);
            resData += L"\"";
        }
        else if ((acType >> 24) == 0x12) {
            // 布尔值
            if (acData == -1) {
                resData += L"\"true\"";
            }
            else if (acData == 0) {
                resData += L"\"false\"";
            }
        }
        else if ((acType >> 24) == 0x1) {
            // 资源ID
            std::wstringstream wss;
            wss << std::hex << acData;
            std::wstring hexString = wss.str();
            resData += L"\"@";
            resData += std::wstring(wss.str());
            resData += L"\"";
        }
        else {
            // 未识别格式
            std::wstringstream wss;
            wss << std::hex << acData;
            std::wstring hexString = wss.str();
            resData += L"\"[Error]";
            resData += std::wstring(wss.str());
            resData += L"\"";
        }
        return resData;
    }
 
    void change_value(int value) {
        ((sAttributeChunk*)addr)->acValueStr = value;
        acValueStr = value;
    }
};
 
 
class StartTagChunk {
public:
    struct sStartTagChunk {
        int stcSignature;       // 块类型标识      
        int stcSize;            // 块大小
        int stcLineNumber;      // 该属性在明文中的行数
        int stcUNKNOWN;         // 未知
        int stcNamespaceUri;    // 字符串 Uri 索引
        int stcName;            // Tag 名称字符串索引
        int stcFlags;           // 未知
        int stcAttributeCount;  // AttributeChunk 的数量
        int stcClassAttribute;  // 未知
    };
 
    char* addr;
    int stcSignature;
    int stcSize;
    int stcLineNumber;
    int stcUNKNOWN;
    int stcNamespaceUri;
    int stcName;
    int stcFlags;
    int stcAttributeCount;
    int stcClassAttribute;
 
    EndTagChunk* mEndTagChunk;
    StringChunk*& mStringChunk;
    StartNamespaceChunk*& mStartNamespaceChunk;
    std::vector<AttributeChunk*> mAttributeChunkList;
 
    StartTagChunk(char* chunk_addr, StringChunk** vStringChunk, StartNamespaceChunk** vStartNamespaceChunk)
        : mStringChunk(*vStringChunk), mStartNamespaceChunk(*vStartNamespaceChunk){
        addr = chunk_addr;
        stcSignature = ((sStartTagChunk*)addr)->stcSignature;
        stcSize = ((sStartTagChunk*)addr)->stcSize;
        stcLineNumber = ((sStartTagChunk*)addr)->stcLineNumber;
        stcUNKNOWN = ((sStartTagChunk*)addr)->stcUNKNOWN;
        stcName = ((sStartTagChunk*)addr)->stcName;
        stcFlags = ((sStartTagChunk*)addr)->stcFlags;
        stcAttributeCount = ((sStartTagChunk*)addr)->stcAttributeCount;
        stcClassAttribute = ((sStartTagChunk*)addr)->stcClassAttribute;
 
        for (int i = 0; i < stcAttributeCount; i++) {
            AttributeChunk* mAttributeChunk =
                new AttributeChunk(addr + sizeof(sStartTagChunk) + 20 * i, &mStringChunk, &mStartNamespaceChunk);
            mAttributeChunkList.push_back(mAttributeChunk);
        }
    };
 
    std::wstring get_string() {
        std::wstring resData = L"";
        for (int i = 0; i < mAttributeChunkList.size(); i++) {
            resData += mAttributeChunkList[i]->get_srting();
            resData += L"\n";
        }
        return resData;
    }
};
class AttributeChunk {
public:
    struct sAttributeChunk {
        int acNamespaceUri; // 命名空间 Uri 索引
        int acName;         // 属性名称(key)的索引
        int acValueStr;     // 属性内容(value)的索引(当前类型为字符串时使用该属性)
        int acType;         // 属性内容(value)的类型(String、Int、Bool ...)
        int acData;         // 属性内容(value)的索引
    };
 
    int acNamespaceUri;
    int acName;        
    int acValueStr;    
    int acType;        
    int acData;        
 
    char* addr;
    StringChunk*& mStringChunk;
    StartNamespaceChunk*& mStartNamespaceChunk;
 
    AttributeChunk(char* chunk_addr, StringChunk** vStringChunk, StartNamespaceChunk** vStartNamespaceChunk):mStringChunk(*vStringChunk), mStartNamespaceChunk(*vStartNamespaceChunk) {
        addr = chunk_addr;
        acNamespaceUri = ((sAttributeChunk*)addr)->acNamespaceUri;
        acName = ((sAttributeChunk*)addr)->acName;
        acValueStr = ((sAttributeChunk*)addr)->acValueStr;
        acType = ((sAttributeChunk*)addr)->acType;
        acData = ((sAttributeChunk*)addr)->acData;
    }
 
    std::wstring get_srting() {
        std::wstring resData = L"";
        // 当 acNamespaceUri 为 -1 时,命名空间为空
        if (acNamespaceUri != -1 && acNamespaceUri == mStartNamespaceChunk->sncUri) {
            resData = mStartNamespaceChunk->get_string() + L":";
        }
 
        // 属性名称
        resData += mStringChunk->get_string(acName);
        resData += L"=";
 
        // 属性值的数据类型
        if ((acType >> 24) == 0x10) {
            // 整数
            resData += L"\"";
            resData += std::to_wstring(acData);
            resData += L"\"";
        }
        else if ((acType >> 24) == 0x3) {
            // 字符串
            resData += L"\"";

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-1-18 22:07 被简单的简单编辑 ,原因:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 2428
活跃值: (10698)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
太细了
2024-1-19 10:34
0
雪    币: 3525
活跃值: (31011)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2024-1-19 11:19
1
雪    币: 6501
活跃值: (4912)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
你瞒我瞒 太细了
因为我真的在试图教会你 
2024-1-19 11:20
0
雪    币: 1110
活跃值: (3364)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
看得出来这是逆向出来,没有细看 AOSP 的相关源码,有一些情况没有覆盖到,还有改进空间。
2024-1-19 12:14
0
雪    币: 2428
活跃值: (10698)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
简单的简单 因为我真的在试图教会你 [em_51]
现在有部分app试图在破坏某个部分但是不影响app安装,影响文件的解析来规避上架检测,或者让反编译工具反编译失效
2024-1-23 09:21
0
雪    币: 203
活跃值: (1204)
能力值: ( LV9,RANK:195 )
在线值:
发帖
回帖
粉丝
7
你瞒我瞒 现在有部分app试图在破坏某个部分但是不影响app安装,影响文件的解析来规避上架检测,或者让反编译工具反编译失效[em_2]
现在的APP为了切支付也是煞费苦心
2024-1-24 10:51
0
游客
登录 | 注册 方可回帖
返回
//