-
-
[原创]静态InlineHook的脚本实现
-
发表于:
2021-9-30 18:42
30678
-
Use lief, keystone and capstone to manually inline hook elf(libil2cpp.so) file
前文说到使用基于LIEF的InlineHook实现 ,在这里我们再借助 keystone 和 capstone 来完善一下这个想法,解决一些比较枯燥且容易出错的事,比如 地址偏移的计算,指令备份还原 ...
- 合并编译出的so中的指定节到我们待修改的so(MergeUtils中recordSymbols屏蔽掉合并后函数地址的变化)
- UnityJumper.addHook 后当前pc已经reset在待写代码的位置,写完代码调用 UnityJumper.endHook
- addHook中也支持查看hook位置的Regs值(printRegs=True),具体实现是读取进入hook代码前对所有用户态寄存器保存在堆栈的值,如果后续修改参数(setArg/getArg)记得保存好FP
- Hook InitArray 的第一个函数(Unity是hook il2cpp_init),在此处获取基址,并将GOT_TABLE中的每一项加上这个基址重新写回
- LDR 指令修复,其他PC相关指令后续再说 TODO .....
- 封装一些常用的函数 android_log_print mprotect callFunction Unity.JNI(解决多参数问题,仅支持int,bool)
小提示
- ins.addGOT() 和 ins.addPtr() :
- addGOT 添加到 GOT_TABLE 启动时候会加基地址,用作blx Rx
- addPtr 添加到 GLOBAL_TABLE ,仅用作存储,但是在 recordSymbol中也会用到addPtr,此处的调用会调用 addGOT
- ins.addBP() 添加一个死循环,IDA调式BUG的时候使用 (或者ins.resetPC(0x12345678) 后使用)
记录下用到的五个起始位置

- GLOBAL_TABLE 用于存放我们需要初始化的一些值,可以理解我们自己写代码的.data
- STR_TABLE 字符串后期使用可能会比较常用,所以我就单独列出来了一个字符串表
- GOT_TABLE 初始化时会将该表每一项都给他加上一个soAddr(libil2cpp.so的基地址),用作后续可能的blx Rx
- trampolines 跳板代码存放位置(1.环境的保存 2.跳转到textCodes 3.textCodes返回时跳转回原代码)
- textCodes 真实执行的代码位置 (hook代码存放位置)
原来的样子
这里在+-32MB范围内建议直接用bl会比较简洁一些
脚本中提供了三种方式的 hook:ldr(3)/b(1)/bl(1)

hook之后使用三条指令跳转到 trampolines

进入到trampolines
做一次中转,保存上下文同时跳转到hook代码

进入到textCodes
真实的hook代码位置,使用的每一个小功能代码连续且独立成块,用一条b跳过相对寻址占用的位置

GLOBAL_TABLE

STR_TABLE

(目前有一个已知的问题是对CallStaticVoidMethod参数的构建,具体JValueArray的内存实现大概是猜对了,基本数据类型是没啥问题,主要是引用数据类型不能正确读取)
具体实现如下:

[注意]看雪招聘,专注安全领域的专业人才平台!
最后于 2021-10-27 14:33
被唱过阡陌编辑
,原因: