全解析框架和信息篡改
引
用 python 一步步解剖 dex 文件(一)
用 python 一步步解剖 dex 文件(二)
前两篇主要在已有的项目 dexparser 基础上, 做的研究和补充; 但是想对 dex 做修改的话, 这个就不够了
所以我自己做了一个解析框架, 这个框架将 dex 分解为层级对象, 并且可以将层级对象重新还原回 dex 格式中
框架代码地址: https://github.com/callmejacob/dexfactory
android dex 文件格式:
https://source.android.com/devices/tech/dalvik/dex-format#encoding
android 源码中对 dex 格式的解析和校验:
http://androidxref.com/8.0.0_r4/xref/dalvik/libdex/
框架结构
dex 文件可以看成是一个 section 的列表, 每个 section 里包含一个 item 列表, 而每个 item 中又可能嵌套某个数据结构 data
其中, section 列表的信息 (类型, 子项数目, 文件偏移量) 最终会记录在叫 MAP_LIST 的 section 段中
基于此, 首先抽象出一个字节数组对象类(BytesObject), 它包含一个字节数组和解码编码的方法, 解码用于从该字节数组中获取一个对象信息, 编码用于将对象信息重新压缩回字节数组中
上面提到的 data 使用 BaseData 抽象, item 使用 BaseItem 抽象, section 使用 BaseSection 抽象
继承关系如下:
基类图
每个 section 都是有类型的:(按官方文档, 这里缺失一些类型, 需要继续补充)
类型定义
基于抽象基类和类型, 我们定义基于 BaseItem 的各个类型的子类, 并做 item 类的映射表:
item 类映射表
并且定义基于 BaseSection 的各个类型的子类, 并做 section 类的映射表:
section 类映射表
为了能够跨越 section 获取信息, 定义一个上下文的类 Context, 它包含了 section 的映射表:
Context 类
最后定义一个 Dex 文件的信息类 DexInfo, 它负责打开 dex 文件, 解码, 编码, 保存, 打印等等
DexInfo
最主要的流程还是解码和编码的过程:
解码过程
编码过程
这里面的难点主要是文件偏移量和排序问题
dex 的数据结构中, 很多是直接用文件偏移量表示的, 可是该文件偏移量对应的项信息发生了更改(特别是文件偏移量需要调整的时候), 就会出现混乱; 还有 android 的 libdex 在解析 dex 时会做很多顺序的校验, 比如 string_ids 列表的数字必须从低到高等
为此, 我做了两重映射: off <> id <> item
其中 off 是指文件偏移量, id 是指对应的子项在 section 中的索引编号, 而 item 就是对应的子项
在解码过程中, 从 Dex 里解析到的是 off, 然后使用 [ off ---> id ] 转换, 再做 [ id ---> item ] 转换, 这样子项 item 里的信息, 就包含了其它 section 中相应的 id 和 item 信息
在编码过程中, 因为 section 里的子项列表可能做了调整, 所以先做 [ item ---> id ] 转换 (同时按照新的 id 进行排序), 再做[ id ---> off ] 转换, 这样最后的偏移量就是准确的偏移量了
测试程序和字符串修改
Demo
其中修改函数如下:
修改字符串
运行结果:
result
使用 dexdump 可以立即检测下新的 dex 文件是否有问题:
dexdump classes_new.dex
如果发现错误信息, 可以到 android 源码中的 dalvik/libdex 中, 找寻相应的提示来定位问题
最后, 将新的 dex 文件替换掉原有 apk 中的 dex 文件, 重新用 zip 压缩为 apk, 并重新签名
这里提供一个 mac 上的签名工具:
地址: 链接: https://pan.baidu.com/s/1kXiUgFt 密码: xy6j
使用: signapk.sh xxx.apk xxx_signed.apk
需要完善的地方
1. 类型不完全
2. 排序功能不完全
3. 字节码反编译框架
4. 数据使用需要优化
待续
来源: http://www.jianshu.com/p/93ed7ae06994