Dex文件格式

Dex文件格式

Google虽然借鉴了Java的上层设计,但是虚拟机使用的是自己设计的Dalvik,Dalvik虚拟机读取、解释的文件是DEX文件。虽然在Android 4.0开始,开始引入类似C#的二次编译技术(Android自称ART),Android 5.0已经完全放弃Dalvik虚拟机(所以源码里已经没有Dalvik设计文档了),但是,二次编译技术是安装apk时候的事,我们用Java语言所写的代码,还是要经过.java->.class->.dex->.apk的过程,认识Dex文件格式,还是有助于反汇编成Smali语言,有助于逆向。

dex生成流程

以下Makefile脚本展示了dex文件生成流程:

MODULE_NAME := Hello
START_CLASS := Hellk
DX := ${SDK_PATH}\sdk\build-tools\19.1.0\dx.bat
INSTALL_PATH := /data/local/tmp
 
#用dalvikvm虚拟机解释运行dex文件,需要指定启动类
run:
    adb push ${MODULE_NAME}.dex ${INSTALL_PATH}
    adb shell dalvikvm -cp ${INSTALL_PATH}/${MODULE_NAME}.dex ${START_CLASS}
 
dx: ${MODULE_NAME}.dex ${MODULE_NAME}.class
 
#通过.class生成dx
${MODULE_NAME}.dex: ${MODULE_NAME}.class
    ${DX} --dex --output=${MODULE_NAME}.dex ${MODULE_NAME}.class
     
javac: ${MODULE_NAME}.class
 
#dx所支持的.class版本一般不是最新的
${MODULE_NAME}.class:
    javac -source 1.6 -target 1.6 ${MODULE_NAME}.java

学习Dex文件的工具

推荐使用010 Editor软件,它自带模板插件功能,并且已经有他人制作好的针对Dex文件的模版。可以高亮显示各字段,解析各字段,还附带各字段的注释。对照着Dalvik自带的文档看十六进制,事半功倍

Dex文件组成

按顺序解析dex文件,有以下几个部分:

  1. struct header_item dex_header
  2. struct string_id_list dex_string_ids
  3. struct type_id_list dex_type_ids
  4. struct proto_id_list dex_proto_ids
  5. struct field_id_list dex_field_ids
  6. struct method_id_list dex_method_ids
  7. struct class_def_item_list dex_class_defs
  8. struct map_list_type dex_map_list

其中两头两尾的header_itemmap_list是两张“总表”,包含着其它的表的偏移信息等,两者信息有重叠(冗余)。

各个表的功能及要求:

  1. string_id_item[]: 文件中要用到的所有字符串,按UTF-16编码有序排列
  2. type_id_item[]: 文件中要用到的所有类型信息,但里面并不直接记录着字符串,而是string_id_item[]中的数组下标,且按string_id_item中的数组下标有序排列
  3. proto_id_item[]: 文件中要用到的所有方法原型,相当于所有函数指针的类型信息,也是有序排列的,主序是返回类型,次序是参数类型
  4. field_id_item[]: 文件中要用到的所有成员(含静态与普通),按类的类型、成员名、成员类型优先级递减有序排列。
  5. method_id_item[]: 文件中要用到的所有方法(含静态与普通), 按类的类型、方法名、方法原型优先级递减有序排列。
  6. class_def_item[]: 类的信息在此表中,从此表中,可以解析出内部类、静态与普通成员/方法、Dalvik字符码的位置等与类有关的具体信息,都在此表中

文件头中的校验

在文件头中,以下几项比较关键,影响到dex文件能否被dalvikvm正常执行:

  1. uint checksum: 文件0x8偏移处,通过alder32算法,针对文件0xC至文件尾得到的的校验值。
  2. SHA1 signature[20]: 文件0xC偏移处,通过SHA1算法,镇上 对文件0x20至文件尾得到的HASH值。
  3. uint file_size: 文件0x20偏移处,记录文件长度

对Dex文件进行修改后,要依次更新file_size, signature[20], checksum三个字段,Dex才能正常运行。

dex的一些加固思路

大小尾标签

在header_item中有一个uint endian_tag字段,记录了常量0x12345678,dalvikvm在运行Dex文件时,会通过检查这个字段,来决定是以小尾还是大尾方式来解释dex文件(中的相关变量)。由于ARM与x86芯片都是小尾方式,现有的反汇编引擎都不会考虑这个字段(默认小尾),因此,若我们人为修改这个字段为大尾,并将dex文件中相关数据都反过来,可以对抗当前的各种反汇编引擎。

字符串混淆

因为dex文件的信息都很集中,所以将string_id_item[]中的字符串替换为无意义的字符串,整个文件中相关要用到的地方也同步更新了,可用此来混淆。有时候防守方做得太恶心了(如两个函数名:”oooo0o”与”o0oooo”),可以用比较弱的混淆器对抗下(abc一类的名称比数圈圈好)。

实践方案

以上的实验还只是针对dex的标识符的加固,不涉及代码。实际操作中,可以:

  1. 得到正常的dex
  2. 修改dex中的各表项,使阅读困难
  3. 用baksmali,反汇编成smali语法
  4. 针对smali文件,进行代码混淆
  5. 重新编译smali文件,得到加固后的dex文件

不过,不管怎样混淆,dalvikvm毕竟是开源的,dex文件的强度都比较弱。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DEX文件格式是Android中的一种可执行文件格式,全称为Dalvik Executable Format。DEX文件主要用于存储和执行Android应用程序的字节码。 DEX文件的结构由标头区域、字符串表、类型表、字段表、方法表、类定义和数据区组成。 标头区域是DEX文件的开始部分,包含了一些元数据信息,例如魔数、版本号、校验和等。字符串表用于存储DEX文件中使用的字符串常量,例如类名、方法名、变量名等。类型表用于存储类的完整类型信息,包括类名、父类名、接口等。字段表和方法表分别用于存储类中的字段和方法的详细信息,例如访问权限、名称、类型等。 类定义部分是DEX文件的核心,用于存储所有类的定义信息。每个类都有一个类定义项,包含了该类的访问标志、类名、父类名、实现的接口、字段和方法等详细信息。 数据区是DEX文件的最后部分,用于存储类及其相关信息的具体数据。数据区包括常量池、方法体、注解和调试信息等。常量池存储了类中使用的常量,例如字符串、数字、类引用等。方法体包含了方法的字节码指令和异常处理表。注解用于存储类、字段和方法的元数据信息。调试信息用于存储调试器需要的信息,例如行号映射表和本地变量表等。 总之,DEX文件格式是一种用于存储和执行Android应用程序字节码的文件格式,通过包含标头区域、字符串表、类型表、字段表、方法表、类定义和数据区等部分,有效地组织和管理类及其相关信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值