Dex 檔案格式詳解
阿新 • • 發佈:2019-01-30
/* * 解析 Dex 檔案 */ #include "dex.h" #include <sstream> #include <string> #include <iostream> void DexFile::parseAllClass() { for (u4 i = 0; i < dexHeader->classDefsSize; ++i) { std::cout << parseClassDef(i) << std::endl; std::cout << std::endl; } } DexFile::DexFile(char* file) { // dex 頭 dexHeader = reinterpret_cast<PDexHeader>(file); if (dexHeader == nullptr) { return; } else { // 字串 if (dexHeader->stringIdsOff != 0) { stringIds = reinterpret_cast<PDexStringId>((dexHeader->stringIdsOff) + reinterpret_cast<char*>(dexHeader)); } else { stringIds = nullptr; } // 型別 if (dexHeader->typedeIdsOff == 0) { typeIds = nullptr; } else { typeIds = reinterpret_cast<PDexTypeId>((dexHeader->typedeIdsOff) + reinterpret_cast<char*>(dexHeader)); } // 宣告 if (dexHeader->protoIdsOff == 0) { protoIds = nullptr; } else { protoIds = reinterpret_cast<PDexProtoId>((dexHeader->protoIdsOff) + reinterpret_cast<char*>(dexHeader)); } // 欄位 if (dexHeader->fieldIdsOff == 0) { fieldIds = nullptr; } else { fieldIds = reinterpret_cast<PDexFieldId>((dexHeader->fieldIdsOff) + reinterpret_cast<char*>(dexHeader)); } // 方法 if (dexHeader->methodIdsOff == 0) { methodIds = nullptr; } else { methodIds = reinterpret_cast<PDexMethodId>((dexHeader->methodIdsOff) + reinterpret_cast<char*>(dexHeader)); } // 類 if (dexHeader->classDefsOff == 0) { classDefs = nullptr; } else { classDefs = reinterpret_cast<PDexClassDef>((dexHeader->classDefsOff) + reinterpret_cast<char*>(dexHeader)); } // 資料 if (dexHeader->dataOff == 0) { data = nullptr; } else { data = reinterpret_cast<PDexData>((dexHeader->dataOff) + reinterpret_cast<char*>(dexHeader)); } // 靜態連結資料區 if (dexHeader->linkOff == 0) { linkData = nullptr; } else { linkData = reinterpret_cast<PDexLink>((dexHeader->linkOff) + reinterpret_cast<char*>(dexHeader)); } } return; } /* * 根據索引獲取字串 * DexStringId 結構體 * typedef struct _DexStringId * { * u4 stringDataOff; // 指向 MUTF-8 字串的偏移 * }DexStringId, *PDexStringId; */ std::string DexFile::parseStringId(u4 index) { return std::string(MUTF8ToASCII(reinterpret_cast<char *>(stringIds[index].stringDataOff + reinterpret_cast<char*>(dexHeader)))); } /* * 根據索引獲取型別 * DexTypeId 結構體 * typedef struct _DexTypeId * { * u4 descriptorIdx; // 指向 DexStringId 列表的索引 * }DexTypeId, *PDexTypeId; */ std::string DexFile::parseTypeId(u4 index) { return parseStringId(typeIds[index].descriptorIdx); } /* * 根據索引解析方法宣告 * DexProtoId 結構體 * typedef struct _DexProtoId * { * u4 shortyIdx; // 方法宣告字串,指向 DexStringId 列表的索引,方法宣告 = 返回型別+引數列表 * u4 returnTypeIdx; // 方法返回型別字串,指向 DexStringId 列表的索引 * u4 parametersOff; // 方法的引數列表,指向 DexTypeList 結構的偏移 * }DexProtoId, *PDexProtoId; */ std::string DexFile::parseProtoId(u4 index) { // 方法宣告 = 返回型別+引數列表 std::string funcString = parseStringId(protoIds[index].shortyIdx); // 引數 if (protoIds[index].parametersOff != 0) { funcString.append(parseDataTypeList(reinterpret_cast<PDexTypeList>((protoIds[index].parametersOff) + reinterpret_cast<char*>(dexHeader)))); } // 返回值 funcString.append(parseTypeId(protoIds[index].returnTypeIdx)); return funcString; } /* * 根據索引解析欄位 * DexFieldId 結構體 * typedef struct _DexFieldId * { * u2 classIdx; // 類的型別,指向 DexTypeId 列表的索引 * u2 typeIdx; // 欄位的型別,指向 DexTypeId 列表的索引 * u4 nameIdx; // 欄位名,指向 DexStringId 列表的索引 * }DexFieldId, *PDexFieldId; */ std::string DexFile::parseFieldId(u4 index) { std::string fieldString = parseTypeId(fieldIds[index].classIdx); fieldString.append(parseTypeId(fieldIds[index].typeIdx)); fieldString.append(parseStringId(fieldIds[index].nameIdx)); return fieldString; } /* * 根據索引解析方法 * DexMethodId 結構體 * typedef struct _DexMethodId * { * u2 classIdx; // 類的型別,指向 DexTypeId 列表的索引 * u2 protoIdx; // 宣告的型別,指向 DexProtoId 列表的索引 * u4 nameIdx; // 方法名,指向 DexStringId 列表的索引 * }DexMethodId, *PDexMethodId; */ std::string DexFile::parseMethodId(u4 index) { std::string methodString = parseTypeId(methodIds[index].classIdx); methodString.append(parseProtoId(methodIds[index].protoIdx)); methodString.append(parseStringId(methodIds[index].nameIdx)); return methodString; } /* * 根據索引解析類 * DexClassDef 結構 * typedef struct _DexClassDef * { * u4 classIdx; // 類的型別,指向 DexTypeId 列表的索引 * u4 accessFlags; // 類的訪問標誌 * u4 superclassIdx; // 父類型別索引值,指向 DexTypeId 列表的索引,如果沒有父類? * u4 interfacesOff; // 介面,如果有指向 DexTypeList 結構,否則為0 * u4 sourceFileIdx; // 原始檔名,指向 DexStringId 列表的索引 * u4 annotationsOff; // 註解,指向 DexAnnotationsDirectoryItem,或者為0 * u4 classDataOff; // 指向 DexClassData 結構的偏移,類的資料部分 * u4 staticValuesOff; // 指向 DexEncodeArray 結構的偏移,記錄了類中的靜態資料 */ std::string DexFile::parseClassDef(u4 index) { std::string classString = "類型別:"; // 類型別 classString.append(parseTypeId(classDefs[index].classIdx)); // 類的訪問標誌 // 父類 classString.append("\n父類:"); classString.append(parseTypeId(classDefs[index].superclassIdx)); // 介面 if (classDefs[index].interfacesOff != 0) { classString.append("\n介面:"); classString.append(parseDataTypeList(reinterpret_cast<PDexTypeList>((classDefs[index].interfacesOff) + reinterpret_cast<char*>(dexHeader)))); } // 原始檔名 classString.append("\n原始檔名:"); classString.append(parseStringId(classDefs[index].sourceFileIdx)); // 註解 // 暫時不處理 // 類的資料 if (classDefs[index].classDataOff != 0) { classString.append(parseClassData(reinterpret_cast<PDexClassData>((classDefs[index].classDataOff) + reinterpret_cast<char*>(dexHeader)))); } // 類的靜態資料 if (classDefs[index].staticValuesOff != 0) { // do something } return classString; } /* * DexClassData 結構體 * typedef struct _DexClassData * { * DexClassDataHeader header; // 指定欄位與方法的個數 * DexField* staticFields; // 靜態欄位 * DexField* instanceFields; // 例項欄位 * DexMethod* directMethods; // 直接方法 * DexMethod* virtualMethods; // 虛方法 * }DexClassData, *PDexClassData; * * DexClassDataHeader 結構體 * typedef struct _DexClassDataHeader * { * uleb128 staticFieldsSize; // 靜態欄位個數 * uleb128 instanceFieldsSize; // 例項欄位個數 * uleb128 directMethodsSize; // 直接方法個數 * uleb128 virtualMethodsSize; // 虛方法個數 * }DexClassDataHeader, *PDexClassDataHeader; */ std::string DexFile::parseClassData(PDexClassData classData) { u1* ptr = reinterpret_cast<u1*>(classData); std::string str = ""; u4 staticFieldsSize = uleb128ToInt(&ptr); u4 instanceFieldsSize = uleb128ToInt(&ptr); u4 directMethodsSize = uleb128ToInt(&ptr); u4 virtualMethodsSize = uleb128ToInt(&ptr); // 靜態欄位 if (staticFieldsSize != 0) { str.append("\n靜態欄位個數:"); str.append(IntToString(staticFieldsSize)); // 解析 DexField for (u4 i = 0; i < staticFieldsSize; ++i) { str.append("\n靜態欄位:"); str.append(parseFieldId(uleb128ToInt(&ptr))); str.append("\n訪問標誌:"); str.append(IntToString(uleb128ToInt(&ptr))); } } // 例項欄位 if (instanceFieldsSize != 0) { str.append("\n例項欄位個數:"); str.append(IntToString(instanceFieldsSize)); // 解析 DexField for (u4 i = 0; i < instanceFieldsSize; ++i) { str.append("\n例項欄位:"); str.append(parseFieldId(uleb128ToInt(&ptr))); str.append("\n訪問標誌"); str.append(IntToString(uleb128ToInt(&ptr))); } } // 直接方法 if (directMethodsSize != 0) { str.append("\n直接方法個數:"); str.append(IntToString(directMethodsSize)); // 解析 DexMethod for (u4 i = 0; i < directMethodsSize; ++i) { str.append("\n直接方法:"); str.append(parseMethodId(uleb128ToInt(&ptr))); str.append("\n訪問標誌:"); str.append(IntToString(uleb128ToInt(&ptr))); str.append("\nDexCode的偏移:"); str.append(IntToString(uleb128ToInt(&ptr))); } } // 虛方法 if (virtualMethodsSize != 0) { str.append("\n虛方法個數:"); str.append(IntToString(virtualMethodsSize)); // 解析 DexMethod for (u4 i = 0; i < virtualMethodsSize; ++i) { str.append("\n虛方法:"); str.append(parseMethodId(uleb128ToInt(&ptr))); str.append("\n訪問標誌:"); str.append(IntToString(uleb128ToInt(&ptr))); str.append("\nDexCode的偏移:"); str.append(IntToString(uleb128ToInt(&ptr))); } } return str; } /************************************************ * DexTypeList 結構體 * typedef struct _DexTypeList * { * u4 size; // 接下來 DexTypeItem 的個數 * PDexTypeItem list; // DexTypeItem 結構 * }DexTypeList, *PDexTypeList; * * DexTypeItem 結構體 * typedef struct _DexTypeItem * { * u2 typeIdx; // 指向 DexTypeId 列表的索引 * }DexTypeItem, *PDexTypeItem; ************************************************/ std::string DexFile::parseDataTypeList(PDexTypeList typeList) { std::string str = ""; PDexTypeItem ptr = reinterpret_cast<PDexTypeItem>((reinterpret_cast<char*>(typeList)) + sizeof(u4)); for (u4 i = 0; i < typeList->size; ++i) { str.append(parseTypeId(ptr[i].typeIdx)); } return str; } int DexFile::uleb128ToInt(u1** pStream) { u1* ptr = *pStream; int result = *(ptr++); if (result > 0x7f) { int cur = *(ptr++); result = (result & 0x7f) | ((cur & 0x7f) << 7); if (cur > 0x7f) { cur = *(ptr++); result |= (cur & 0x7f) << 14; if (cur > 0x7f) { cur = *(ptr++); result |= (cur & 0x7f) << 21; if (cur > 0x7f) { /* * Note: We don't check to see if cur is out of * range here, meaning we tolerate garbage in the * high four-order bits. */ cur = *(ptr++); result |= cur << 28; } } } } *pStream = ptr; return result; } int DexFile::sleb128ToInt(u1** pStream) { u1* ptr = *pStream; int result = *(ptr++); if (result <= 0x7f) { result = (result << 25) >> 25; } else { int cur = *(ptr++); result = (result & 0x7f) | ((cur & 0x7f) << 7); if (cur <= 0x7f) { result = (result << 18) >> 18; } else { cur = *(ptr++); result |= (cur & 0x7f) << 14; if (cur <= 0x7f) { result = (result << 11) >> 11; } else { cur = *(ptr++); result |= (cur & 0x7f) << 21; if (cur <= 0x7f) { result = (result << 4) >> 4; } else { /* * Note: We don't check to see if cur is out of * range here, meaning we tolerate garbage in the * high four-order bits. */ cur = *(ptr++); result |= cur << 28; } } } } *pStream = ptr; return result; } std::string DexFile::IntToString(int num) { std::stringstream strStream; std::string str; strStream << num; strStream >> str; return str; }