本次研究基于安卓12
对于dex文件结构的的解析,我认为c或者c++语言是比较好的
推荐工具 c语言的编辑工具----我是用的 qt 简单方便
系统:windows 11
验证工具: 010 editor
文件头:header
索引区:stringids,typeids,protoids,fieldids,method_ids
数据区:classdefs,data,linkedata
了解结构体
头部结构体AI解读:
magic_[8]
:这是一个8字节的数组,用于存储文件的魔数(magic number)。魔数通常用于标识文件的类型或格式,确保读取文件的程序能够识别出这是一个它所能处理的文件。
checksum_
:这是一个32位的校验和,用于验证文件内容的完整性。在文件传输或存储过程中,如果文件内容被修改,这个校验和将不再匹配,从而可以检测到文件已被篡改。
signature_[20]
:这是一个20字节的签名数组,具体用途可能依赖于文件的实际使用场景。在某些情况下,它可能用于身份验证或完整性检查。
file_size_
:整个文件的大小(以字节为单位)。这个信息对于了解文件的整体大小很有帮助,尤其是在需要预先分配内存或进行文件操作时。
header_size_
:头部的大小(以字节为单位),或者是头部结束后,下一个部分的起始偏移量。这个信息对于解析文件的其他部分非常关键。
endian_tag_
:这个字段可能用于指示文件中数据的字节序(大端或小端)。这对于跨平台的数据交换和解析非常重要。
link_size_
和 link_off_
:这两个字段当前标记为未使用(unused),但在某些文件格式中,它们可能用于链接到文件的其他部分或提供额外的元数据。
map_off_
:映射列表的偏移量,从data_off_
开始计算。映射列表可能包含了文件中各个部分的详细描述或索引。
字符串ID、类型ID、原型ID、字段ID、方法ID和类定义的相关字段(如string_ids_size_
, string_ids_off_
, type_ids_size_
等):这些字段提供了关于文件中不同类型ID、字符串、类定义等信息的数量和偏移量。这对于解析文件内容和构建程序的内部表示非常重要。
data_size_
和 data_off_
:分别表示数据部分的大小和偏移量。数据部分可能包含了文件的主要执行内容或数据。
解析代码:
接下来解析字符串常量池
从头部获取 stringidsoff 与 size
即可解析 先看这个结构体吧:
这个结构体告诉你字符串的地址
老规矩先看结构体:
结构体指向的数据 是字符串常量池的索引
打印全部type的代码:
观摩结构体
解析protos
解析成员变量
上结构体
解析打印
结构体:
解析代码:
在我们重点关注class_data_off
指向的结构吧
先看看 class_data_off
指向的结构体吧
这里使用了uleb128的方式存储 那我们在使用结构体直接覆盖得到数据的方式就不在适用了,那这个结构体不导入进项目!
那自己设计一个函数 要求获取读取的数据值,还有在内存中的大小 就可以比较方便的读取了
有了这个工具就可以更好的解析了!
我们通过uleb128读取获取了
staticfieldssize; //静态成员变量的个数
instancefieldssize; //实例成员变量个数
directmethodssize; //直接函数个数
virtualmethodssize; // 虚函数个数
然后按顺序解析
field 与 method
这里的结构体也是uleb128
继续在原来的方法上解析
放解析代码:
这里我们就把方法的offcode找到了
接下来解析 code item
在insns_size后面就是数组 code
这个就是方法的代码所在 一串二进制 而已
到这里 我们就解析dex 解析的差不多了 其他的知识 遇到再补。
将基础篇的class类解析的代码改改:
把code的偏移 code的大小 code的数据 保存下来
checksum:文件校验码,使用alder32算法校验文件除去magic、checksum外余下的所有文件区域,用于检查文件错误。
signature:使用 SHA-1算法hash除去magic,checksum和signature外余下的所有文件区域 ,用于唯一识别本文件 。
顺序为 先signature 再checksum
SHA-1算法:
在函数抽取后 重新计算dex 的校验
使用编译好的架构
cmakelist
将下载好的jnilibs 与 头文件 复制到项目
现在的dobby好像没有这个文件了
链接:337K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6K9r3q4J5k6g2)9J5k6i4N6W2K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8W2W2$3e0e0t1&6j5W2y4A6 密码:calvin
这是我电脑还保存的
下面演示如何 hook 一个简单的函数
为啥我要介绍这个hook 原因嘛 不知道为什么 我用dobby hook libc 产生了闪退 。
而且 实践才发现 shadow hook 更简单
这个里给出使用演示:
自我感觉 shadowhook稳太多了。
第一步:
让我们的dex能被修改
第二部:
加载我们保存的code 并放在map中
第三步
hook 类被加载的方法 在这里还原类的所有方法
hook mmap 使加载的dex能被修改
我们先看看安卓源码的代码
这里我做了一个判断 如果hook的mmap失败 就不修改参数
这里我的知识点我放在 一代加固的帖子上
这里有一个坑 我发现源码里面的函数是这样的
如果按照源码的函数进行hook的话 会闪退
应该是这样的
再多加一个参数就行了
这个hook函数主要的工作就是
1.查找是否存在被抽空的 code off 在map里
2.申请写权限
3.拷贝还原 code
这里我们要明确一个需求 --- 我们要代码在执行前才被还原
那么 我们就在 类 在加载的时候 还原即可
先从findClass开始
pathList.findClass
element.findClass
dexFile.loadClassBinaryName
defineClassNative
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2024-7-10 20:25
被逆天而行编辑
,原因: