5.1 dex文件解析
1.DexHeader结构体占用0x70字节,源码位置 dalvik\libdex\DexFile.h文件中269/*
270 * Direct-mapped "header_item" struct.
271 */
273 u1 magic[8]; /* dex版本标示 */
274 u4 checksum; /* adler32检验 */
275 u1 signature[kSHA1DigestLen]; /* SHA-1哈希值 */
276 u4 fileSize; /* 整个文件的大小 */
277 u4 headerSize; /* DexHeader结构大小 */
281 u4 mapOff; /* DexMapList文件偏移 */
282 u4 stringIdsSize; /* DexStringId的个数 */
283 u4 stringIdsOff; /* DesStringId的文件偏移 */
284 u4 typeIdsSize; /* DexTypeId的个数 */
285 u4 typeIdsOff; /* DexTypeId的文件偏移 */
286 u4 protoIdsSize; /* DexProtoId的个数 */
287 u4 protoIdsOff; /* DexProtoId的文件偏移 */
288 u4 fieldIdsSize; /* DexFileldId的个数 */
289 u4 fieldIdsOff; /* DexFileldId的文件偏移 */
290 u4 methodIdsSize; /* DexMethodId的个数 */
291 u4 methodIdsOff; /* DexMethodId的文件偏移 */
292 u4 classDefsSize; /* DexClassDefs的个数 */
293 u4 classDefsOff; /* DexClassDefs的文件偏移 */
295 u4 dataOff; /* 数据段的文件偏移 */
296};
补充:
magic:目前固定值dex035 “64 65 78 0A 30 33 35 00”
checksum:dex文件校验和,判断dex文件的完整性和是否被修改
signature:识别最佳化之前的dex文件
fileSize:整个dex文件大小
headerSize:DexHeader结构体本身的大小,目前固定为0x70
endianTag:指定dex运行环境的CPU字节序,预设值ENDIAN_CONSTANT 0x12345678 默认采用Little-Endian字节序列
linkSize和linkOff:指定链接段的大小与文件偏移,大部分情况下默认值0

将实例文件Hello.dex使用010editor打开

查看源码
255struct DexMapList {
256 u4 size; /* DexMapItem的个数 */
257 DexMapItem list[1]; /* DexMapItem结构 */
258};
根据mapOff指向DexMapList的数据结构:
245struct DexMapItem {
246 u2 type; /* kDexType开头类型 */
247 u2 unused; /* 未使用,用于字节对齐 */
248 u4 size; /* 指定类型的个数 */
249 u4 offset; /* 指定类型数据的文件偏移,起始位置 */
250};

跳转到DexMapList结构

在DexHeader部分

2.分析StringIdItem结构体中的字段
源码:
263struct DexStringId {
264 u4 stringDataOff; /* 字符串数据偏移 */
265};
通过stringDataOff找到stringdata字符串的保存位置

Data区存放的字符串并非是ASCII字符串而是由MUTF-8编码表示的Modified UTF-8
特点:
1. MUTF-8使用1~3字节编码长度
2. 大于16位的Unicode编码U+10000~U+10ffff使用3字节编码
3. U+0000采用2字节编码
4. 以null作为字符串结尾
分析DexTypeIds结构体:

地址跳转Ctril+G B0

DexTypeId对应DexHeader中的typeIdsSzie与typeIdsOff
270struct DexTypeId {
271 u4 descriptorIdx; /* 指向DexStringId列表索引 */
272};
3.分析DexTypeProtoIdItem

295struct DexProtoId {
296 u4 shortyIdx; /* 指向DexStringId列表的索引 */
297 u4 returnTypeIdx; /* 指向DexTypeId列表的索引 */
298 u4 parametersOff; /* 指向DexTypeList的偏移 */
299};
补充:
shortyIdx是方法声明字符串
returnTypeIdx是方法返回类型字符串
DexTypeList存放了方法的参数列表
4.DexTypeList的偏移地址


DexTypeList结构声明:325struct DexTypeList {
326 u4 size; /* DexTypeItem的个数 */
327 DexTypeItem list[1]; /* DexTypeItem结构 */
328};
318struct DexTypeItem {
319 u2 typeIdx; /* 指向DexTypeId列表的索引 */
320};
方法声明由返回类型和参数列表组成,并且返回类型位于参数列表的前面
5.分析TypeFieldIdItem

根据偏移

277struct DexFieldId {
278 u2 classIdx; /* 类的声明,指向DexTypeId列表索引 */
279 u2 typeIdx; /* 声明类型,指向DexProtoId列表索引 */
280 u4 nameIdx; /* 方法名,指向DexStringId列表索引 */
281};
DexFieldId结构中的数据全部是索引值,指明字段所在的类,字段的类型,字段名
6.分析DexTypeMethodIdItem

根据偏移

286struct DexMethodId {
287 u2 classIdx; /* 类的声明,指向DexTypeId列表索引 */
288 u2 protoIdx; /* 声明类型,指向DexProtoId列表索引 */
289 u4 nameIdx; /* 方法名,指向DexStringId列表索引 */
290};
7.分析TypeClassDefItem

根据偏移

304struct DexClassDef {
305 u4 classIdx; /*类的类型,指向DexTypeId列表的索引 */
306 u4 accessFlags; /* 访问标示,以ACC_开头的一个枚举值*/
307 u4 superclassIdx; /* 父类类型,指向DexTypeId列表的索引 */
308 u4 interfacesOff; /* 接口,指向DexTypeList的偏移 */
309 u4 sourceFileIdx; /*源文件名,指向DexStringId列表的索引结构*/
310 u4 annotationsOff; /* 注解,指向DexAnnotationDirectoryItem结构*/
311 u4 classDataOff; /* 指向DexClassData结构的偏移 */
312 u4 staticValuesOff; /* 指向DexEncodedArray结构的偏移 */
313};
根据classDataOff偏移

classDataOff指向的DexClassData结构声明 在DexClass.h文件中
51struct DexClassData {
52 DexClassDataHeader header; /* 指定字段与方法的个数 */
53 DexField* staticFields; /* 静态字段,DexField结构 */
54 DexField* instanceFields; /* 实例字段,DexField结构 */
55 DexMethod* directMethods; /* 直接方法,DexMethod结构 */
56 DexMethod* virtualMethods; /* 虚方法,DexMethond结构 */
57};

根据DexClassData分析DexClassDataHeader结构
28struct DexClassDataHeader {
29 u4 staticFieldsSize; /* 静态字段个数 */
30 u4 instanceFieldsSize; /* 实例字段个数 */
31 u4 directMethodsSize; /* 直接方法 */
32 u4 virtualMethodsSize; /* 虚方法 */
33};
DexField结构描述了字段的类型与访问标志
36struct DexField {
37 u4 fieldIdx; /* 指向DexFieldId的索引 */
38 u4 accessFlags; /* 访问标志 */
39};
DexMethod描述方法的原型,名称,访问标志和代码数据块
42struct DexMethod {
43 u4 methodIdx; /* 指向DexMethodId的索引 */
44 u4 accessFlags; /* 访问标志 */
45 u4 codeOff; /* 指向DexCode结构的偏移 */
46};
根据codeOff偏移定位

DexCode在DexFile.h文件中
337struct DexCode {
338 u2 registersSize; /* 使用寄存器的数量 */
339 u2 insSize; /* 参数的个数 */
340 u2 outsSize; /* 调用其它方法时使用的寄存器个数 */
341 u2 triesSize; /* Try/Catch个数 */
342 u4 debugInfoOff; /* 指向调试信息的偏移 */
343 u4 insnsSize; /* 指令集个数,以2字节为单位 */
344 u2 insns[1]; /* 指令集 */
345 /* 2字节空间用于结构对齐 */
346 /* try_item[triesSize] DexTry结构 */
347 /* Try/Catch中handler的个数 */
348 /* catch_handler_item[handlersSize],DexCatchHandler结构 */
349};
至此Dex文件分析完毕
附录StringId表,DexTypeld表,DexProtoId表
DexStringId结构体

DexTypeId列表

DexProtoId列表

5.1 dex文件解析的更多相关文章
- DEX文件解析---1、dex文件头解析
DEX文件解析---1.dex文件头解析 一.dex文件 dex文件是Android平台上可执行文件的一种文件类型.它的文件格式可以下面这张图概括: dex文件头一般固定为0x70个字 ...
- class文件与dex文件解析
关于Android的热修复与插件化技术在如今基本上已经成为了“时髦技术”的标配了,或者说用来进行“炫技”的一种方式,毕境如今Android已经发展得非常之成熟了,基本上APP用的到东东都差不多,除了业 ...
- DEX文件解析--7、类及其类数据解析(完结篇)
一.前言 前置技能链接: DEX文件解析---1.dex文件头解析 DEX文件解析---2.Dex文件checksum(校验和)解析 DEX文件解析--3.d ...
- DEX文件解析--3、dex文件字符串解析
一.前言 前两篇文章链接: 1.DEX文件头解析 2.DEX文件校验和解析 PS:前几天检查文件夹的时候发现DEX文件解析还只写了开头,正好找点事情来做,就去接着解析DEX ...
- DEX文件解析--4、dex类的类型解析
一.前言 前几篇系列文章链接: DEX文件解析---1.dex文件头解析 DEX文件解析---2.Dex文件checksum(校验和)解析 DEX文件解析--3.dex文件 ...
- DEX文件解析--5、dex方法原型解析
一.前言 前几篇文章链接: DEX文件解析---1.dex文件头解析 DEX文件解析---2.Dex文件checksum(校验和)解析 DEX文件解析--3.dex文件字 ...
- DEX文件解析--6、dex文件字段和方法定义解析
一.前言 前几篇文章链接: DEX文件解析---1.dex文件头解析 DEX文件解析---2.Dex文件checksum(校验和)解析 DEX文件解析--3. ...
- DEX文件解析---2、Dex文件checksum(校验和)解析
一.checksum介绍 checksum(校验和)是DEX位于文件头部的一个信息,用来判断DEX文件是否损坏或者被篡改,它位于头部的0x08偏移地址处,占用4个字节,采用小端序存储. ...
- Android Dex文件格式解析
Dex文件是Android虚拟机下的可执行文件,包含了应用程序所用到所有操作指令和运行时数据.在程序编译过程中,java源文件先被编译成class文件,然后通过dx工具将多个class文件整合为一个d ...
随机推荐
- ToDoList--HttpMediaTypeNotSupportedException
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-url ...
- [Python] Python 获取中文的首字母 和 全部拼音首字母
Python 获取中文的首字母 和 全部拼音首字母 代码如下: import pinyin def getStrAllAplha(str): return pinyin.get_initial(str ...
- 洛谷P3063 [USACO12DEC]牛奶的路由Milk Routing
链接 其实在博客园里写题解都挺应付的都是在洛谷写了之后 挑一部分粘过来 在洛谷写的也都是废话,是为了凑篇幅 主要就是代码 大体思路就一提 这题贪心不行废话 跑m遍SPFA更新最小值 注意数组记得清空 ...
- CF1174E Ehab and the Expected GCD Problem(DP,数论)
题目大意:对于一个序列,定义它的价值是它的所有前缀的 $\gcd$ 中互不相同的数的个数.给定整数 $n$,问在 $1$ 到 $n$ 的排列中,有多少个排列的价值达到最大值.答案对 $10^9+7$ ...
- 一元n次方程为什么至多有n个实根
任意一个n次多项式都可以分解成n个一次多项式的乘积.例如,对于三次多项式来说,那就可以分成三个一次式的乘积,也就是说,三次方程最多有三个根. 需要注意的是,最少的话可能一个实根都没有,如\(f(x)= ...
- haproxy 配置文件详解 之 global
配置示例: global log 127.0.0.1 local0 info maxconn user nobody group nobody daemon nbproc pidfile /usr/l ...
- App3种开发方式的优劣分析:原生、混合和H5
App混合开发(英文名:Hybrid App),是指在开发一款App产品的时候为了提高效率.节省成本即利用了原生的开发技术还应用了HTML5开发技术,是原生和HTML5技术的混合应用.目前App的开发 ...
- ORM之Entity Framework(EF)
ORM之Entity Framework(EF) 一.下载安装: nuget 搜索Entity Framework安装 EntityFramework.Extension是个扩展库根据需要安装 二.使 ...
- SVN与GIT工具使用对比
版本工具 差异 svn git 系统特点 1.集中式版本控制系统(文档管理很方便) 2.企业内部并行集中开发 3.windows系统上开发推荐使用 4.克隆一个拥有将近一万个提交(commit),五个 ...
- IO流一些问题的总结
字节流的继承体系 字符流的继承体系 字符编码是什么?常见的字符编码表有哪些? 字符编码(英语:Character encoding)也称字集码,是把字符集中的字符编码为指定集合中某一对象,以便文本在计 ...