【Android SDK程序逆向分析与破解系列】之二:Android可执行程序DEX分析(一)
2015-05-06 14:32
465 查看
作者:郭嘉
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWells
【Android SDK程序逆向分析与破解系列】之二:Android可执行程序DEX分析(一)
【Android SDK程序逆向分析与破解系列】之三:Android可执行程序DEX分析(二)
首先上一张图展示Android平台DEX文件的大体结构。
u1~u8:表示1~8字节的无符号数。
sleb128、uled128和uled128pl:DEX文件特有的LEB128数据类型。每个LEB128由1~5个字节组成,所有的字节组合在一起表示一个32位的数据。
LEB128数据类型如下表所示:
每个字节只有7位有效位,如果第一个字节的最高位为1,则表明LEB128需要用到第2个字节,如果第2个字节最高位为1,则表明LEB128需要用到第3个字节,依次类推,知道最后的字节最高位为0.LEB128最多只会使用5个字节,如果读取5个字节后下一个字节的最高位仍为1,则表明该DEX文件无效,Dalvik虚拟机在验证DEX会失败返回。
Android系统源码中读取无符号LEB128的实现如下所示:
源码位置:dalvik\libdex\Leb128.h
Android系统源码中读取有符号LEB128的实现如下所示(有符号与无符号的计算方法是一样的,只是对有符号的LEB128最后一个字节的最高有效位进行了符号扩展):
源码位置:dalvik\libdex\Leb128.h
- dex header:DEX文件头,指定了dex文件的一些属性,并记录了其他6部分在DEX文件中的物理偏移。
- string_ids
- type_ids
- proto_ids
- field_ids
- method_ids
- class_def
- data:真实的数据存放区。
- link_data:静态链接数据区。
Android源码中DexFile结构体的定义如下所示:
DexFile结构为DEX文件被映射到内存中结构,保存各个结构的指针,还包括了DexOptHeader与DexFile尾部附加的数据。
源码位置:dalvik\libdex\DexFile.h
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWells
【Android SDK程序逆向分析与破解系列】章节索引
【Android SDK程序逆向分析与破解系列】之一:Android安装程序APK分析【Android SDK程序逆向分析与破解系列】之二:Android可执行程序DEX分析(一)
【Android SDK程序逆向分析与破解系列】之三:Android可执行程序DEX分析(二)
首先上一张图展示Android平台DEX文件的大体结构。
一 DEX文件数据结构
DEX使用的数据类型如下表所示:u1~u8:表示1~8字节的无符号数。
sleb128、uled128和uled128pl:DEX文件特有的LEB128数据类型。每个LEB128由1~5个字节组成,所有的字节组合在一起表示一个32位的数据。
LEB128数据类型如下表所示:
每个字节只有7位有效位,如果第一个字节的最高位为1,则表明LEB128需要用到第2个字节,如果第2个字节最高位为1,则表明LEB128需要用到第3个字节,依次类推,知道最后的字节最高位为0.LEB128最多只会使用5个字节,如果读取5个字节后下一个字节的最高位仍为1,则表明该DEX文件无效,Dalvik虚拟机在验证DEX会失败返回。
Android系统源码中读取无符号LEB128的实现如下所示:
源码位置:dalvik\libdex\Leb128.h
/* * Reads an unsigned LEB128 value, updating the given pointer to point * just past the end of the read value. This function tolerates * non-zero high-order bits in the fifth encoded byte. */ DEX_INLINE int readUnsignedLeb128(const u1** pStream) { const u1* ptr = *pStream; int result = *(ptr++); if (result > 0x7f) { //大于0x77f表示第1个字节最高位为1 int cur = *(ptr++); //第2个字节 result = (result & 0x7f) | ((cur & 0x7f) << 7);//前2个字节组合 if (cur > 0x7f) { //大于0x77f表示第2个字节最高位为1 cur = *(ptr++); //第3个字节 result |= (cur & 0x7f) << 14; //前3个字节的组合 if (cur > 0x7f) { cur = *(ptr++); //第4个字节 result |= (cur & 0x7f) << 21;//前4个字节的组合 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++); //第5个字节 result |= cur << 28; //前5个字节的组合 } } } } *pStream = ptr; return result; }
Android系统源码中读取有符号LEB128的实现如下所示(有符号与无符号的计算方法是一样的,只是对有符号的LEB128最后一个字节的最高有效位进行了符号扩展):
源码位置:dalvik\libdex\Leb128.h
/* * Reads a signed LEB128 value, updating the given pointer to point * just past the end of the read value. This function tolerates * non-zero high-order bits in the fifth encoded byte. */ DEX_INLINE int readSignedLeb128(const u1** pStream) { const 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; }
二 DEX文件整体结构
DEX文件由多个结构体组合而成,具体结构如下图所示:- dex header:DEX文件头,指定了dex文件的一些属性,并记录了其他6部分在DEX文件中的物理偏移。
- string_ids
- type_ids
- proto_ids
- field_ids
- method_ids
- class_def
- data:真实的数据存放区。
- link_data:静态链接数据区。
Android源码中DexFile结构体的定义如下所示:
DexFile结构为DEX文件被映射到内存中结构,保存各个结构的指针,还包括了DexOptHeader与DexFile尾部附加的数据。
源码位置:dalvik\libdex\DexFile.h
/* * Structure representing a DEX file. * * Code should regard DexFile as opaque, using the API calls provided here * to access specific structures. */ struct DexFile { /* directly-mapped "opt" header */ const DexOptHeader* pOptHeader; /* pointers to directly-mapped structs and arrays in base DEX */ const DexHeader* pHeader; const DexStringId* pStringIds; const DexTypeId* pTypeIds; const DexFieldId* pFieldIds; const DexMethodId* pMethodIds; const DexProtoId* pProtoIds; const DexClassDef* pClassDefs; const DexLink* pLinkData; /* * These are mapped out of the "auxillary" section, and may not be * included in the file. */ const DexClassLookup* pClassLookup; const void* pRegisterMapPool; // RegisterMapClassPool /* points to start of DEX file data */ const u1* baseAddr; /* track memory overhead for auxillary structures */ int overhead; /* additional app-specific data structures associated with the DEX */ //void* auxData; };
相关文章推荐
- 【Android SDK程序逆向分析与破解系列】之三:Android可执行程序DEX分析(二)
- 【Android SDK程序逆向分析与破解系列】之四:Android可执行程序ODEX分析
- 【Android SDK程序逆向分析与破解系列】之一:Android安装程序APK分析
- 【Android SDK程序逆向分析与破解系列】之五:Android APK的静态分析
- 【基于Android的ARM汇编语言系列】之二:C/C++程序生成ARM汇编程序的过程分析
- Android软件安全与逆向分析——Dalvik是如何执行程序的
- 自用Android程序破解,逆向分析工具集
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- 手把手教你逆向分析 Android 程序
- 逆向分析 Android 程序- 内存内存
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- Android安卓破解之逆向分析SO常用的IDA分析技巧
- Android OTA升级原理和流程分析(八)---升级程序update_binary的执行过程
- 手把手教你逆向分析 Android 程序
- Android安全:如何逆向分析Android程序
- Android逆向实例笔记—破解第一个Android程序_crackme02
- Android逆向实例笔记—续力破解三个Android程序
- Android系统Recovery工作原理之使用update.zip升级过程分析(八)---升级程序update_binary的执行过程
- Android系统Recovery工作原理之使用update.zip升级过程分析(八)---升级程序update_binary的执行过程