zoukankan      html  css  js  c++  java
  • 5.1 dex文件解析

    1.DexHeader结构体占用0x70字节,源码位置 dalviklibdexDexFile.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结构声明:
    325
    struct 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列表

     
     

     

  • 相关阅读:
    Linux系统教程:设置GRUB菜单密码
    vimdiff的常用命令
    Zero-Copy实现原理
    解决业务代码里的分布式事务一致性问题
    用好这6个APP,学英语SO EASY!
    线程池调优
    理解select,poll,epoll实现分析
    时序图
    性能监控-TP理解
    sshd_config OpenSSH SSH 进程配置文件配置说明
  • 原文地址:https://www.cnblogs.com/heixiang/p/10966006.html
Copyright © 2011-2022 走看看