1.DexHeader结构体占用0x70字节,源码位置 dalvik\libdex\DexFile.h文件中269/*

270 * Direct-mapped "header_item" struct.

271 */

272struct DexHeader {

273    u1  magic[8];           /* dex版本标示 */

274    u4  checksum;           /* adler32检验 */

275    u1  signature[kSHA1DigestLen]; /* SHA-1哈希值 */

276    u4  fileSize;           /* 整个文件的大小 */

277    u4  headerSize;         /* DexHeader结构大小 */

278    u4  endianTag;        /* 字节序标记 */

279    u4  linkSize;         /* 链接段大小 */

280    u4  linkOff;          /* 链接段偏移 */

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的文件偏移 */

294    u4  dataSize;         /* 数据段大小 */

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文件解析的更多相关文章

  1. DEX文件解析---1、dex文件头解析

    DEX文件解析---1.dex文件头解析 一.dex文件     dex文件是Android平台上可执行文件的一种文件类型.它的文件格式可以下面这张图概括:     dex文件头一般固定为0x70个字 ...

  2. class文件与dex文件解析

    关于Android的热修复与插件化技术在如今基本上已经成为了“时髦技术”的标配了,或者说用来进行“炫技”的一种方式,毕境如今Android已经发展得非常之成熟了,基本上APP用的到东东都差不多,除了业 ...

  3. DEX文件解析--7、类及其类数据解析(完结篇)

    一.前言    前置技能链接:       DEX文件解析---1.dex文件头解析       DEX文件解析---2.Dex文件checksum(校验和)解析       DEX文件解析--3.d ...

  4. DEX文件解析--3、dex文件字符串解析

    一.前言    前两篇文章链接:     1.DEX文件头解析     2.DEX文件校验和解析    PS:前几天检查文件夹的时候发现DEX文件解析还只写了开头,正好找点事情来做,就去接着解析DEX ...

  5. DEX文件解析--4、dex类的类型解析

    一.前言   前几篇系列文章链接:     DEX文件解析---1.dex文件头解析     DEX文件解析---2.Dex文件checksum(校验和)解析     DEX文件解析--3.dex文件 ...

  6. DEX文件解析--5、dex方法原型解析

    一.前言    前几篇文章链接:     DEX文件解析---1.dex文件头解析     DEX文件解析---2.Dex文件checksum(校验和)解析     DEX文件解析--3.dex文件字 ...

  7. DEX文件解析--6、dex文件字段和方法定义解析

    一.前言    前几篇文章链接:       DEX文件解析---1.dex文件头解析       DEX文件解析---2.Dex文件checksum(校验和)解析       DEX文件解析--3. ...

  8. DEX文件解析---2、Dex文件checksum(校验和)解析

    一.checksum介绍     checksum(校验和)是DEX位于文件头部的一个信息,用来判断DEX文件是否损坏或者被篡改,它位于头部的0x08偏移地址处,占用4个字节,采用小端序存储.     ...

  9. Android Dex文件格式解析

    Dex文件是Android虚拟机下的可执行文件,包含了应用程序所用到所有操作指令和运行时数据.在程序编译过程中,java源文件先被编译成class文件,然后通过dx工具将多个class文件整合为一个d ...

随机推荐

  1. Python面向对象 | 类方法 classmethod

      类方法:必须通过类的调用,而且此方法的意义:就是对类里面的变量或者方法进行修改添加. 例一个商店,店庆全场八折,代码怎么写呢? class Goods: __discount = 0.8 # 折扣 ...

  2. Pandas | 05 基本功能

    到目前为止,我们了解了三种Pandas数据结构以及如何创建它们.接下来将主要关注数据帧(DataFrame)对象,因为它在实时数据处理中非常重要,并且还讨论其他数据结构. 一.系列基本功能 编号 属性 ...

  3. Ubuntu安装笔记

    Ubuntu安装笔记 前言 先后在台式电脑&奇葩的SurfaceLaptop上装了Ubuntu18.04LTS 收获了去多经验,浪费了去多时间 为了让下次更加的方便, 写一篇博客记录一下 安装 ...

  4. 常见网页编辑器(富文本,Markdown,代码编辑等)

    编辑器:网页不常用的功能,但却又是不可少的功能,如果要造个编辑器轮子,它可以把人玩死!!前端几大禁忌就有富文本, 为什么都说富文本编辑器是天坑? 下面记录一下常见的一些编辑器,该文随时更新: 富文本编 ...

  5. web服务本质

    目录 django 框架引入: web框架本质 HTTP协议 多功能web服务 封装,分发处理 django 框架引入: web框架本质 web框架本质: 软件开发架构: c / s ; b/ s - ...

  6. prometheus自定义监控指标——实战

    上一节介绍了pushgateway的作用.优劣以及部署使用,本机通过几个实例来重温一下自定义监控指标是如何使用的. 一.监控容器启动时间(shell) 使用prometheus已经两个月了,但从未找到 ...

  7. ASP.NET Core使用Docker-Compose实现多容器应用部署

    一.需求背景 人生苦短,我用.NET Core!前面的<ASP.NET Core使用Docker进行容器化托管和部署>基础课程我们学习了如何使用Docker来部署搭建ASP.NET Cor ...

  8. Remote Desktop突然不能用了 “This could be due to CredSSP encryption oracle remediation”

    一段时间没有用RDP去连远程的Windows主机,某一天突然发现用不了了. 错误信息如下: An authentication error has occurred. The function req ...

  9. [Atcoder ARC103D]Robot Arms

    题目大意:平面上有$n$个点,要求你构造$m$条边(满足$m\leqslant40$),使得可以从原点到达给定的$n$个点(边必须平行于坐标轴).并要求输出每一条边的方向,每条边必须都使用,无解输出$ ...

  10. golang学习笔记--函数和方法

    在go中,函数类型是一等类型,这意味着可以吧函数当做一个值来传递和使用. func divide(dividend int,divisor int)(int,error){ //省略部分代码 } 参数 ...