Unidbg-HookZz
Android逆向-Unidbg-Hook工具
简介
【转载】unidbg hook 使用大全 - qinless
Unidbg 在Android 上支持的Hook,可以分为两大类
- Unidbg 内置的第三方Hook框架,包括xHook/Whale/HookZz
- Unicorn Hook 以及 Unidbg基于它封装的Console Debugger
第一类是Unidbg支持并内置的第三方Hook框架,有Dobby(前身HookZz)/Whale这样的Inline Hook框架,也有xHook这样的PLT Hook 框架。有小伙伴可能困惑Unidbg是否能支持Frida?我个人观点是目前阶段不现实,Frida比Dobby或者xHook都复杂的多,Unidbg目前还跑不通,除此之外,Dobby + Whale + xHook 也绝对够用了,没有非Frida不可的需求。
第二类是当Unidbg的底层引擎选择为Unicorn时(默认引擎),Unicorn自带的Hook功能。Unicorn提供了各种级别和粒度的Hook,内存Hook/指令/基本块 Hook/异常Hook 等等,十分强大和好用,而且Unidbg基于它封装了更便于使用的Console Debugger。
该怎么选择Hook方案?这得看使用Unidbg的目的。如果项目用于模拟执行,那么建议使用 Console Debugger 做快速分析,排查错误,跑通代码后用第三方Hook框架做持久化,为什么?这得从Unidbg支持的汇编执行引擎说起。Unidbg支持多种底层引擎,最早也是默认的引擎是Unicorn,从名字也能看出,Unidbg和Unicorn有很大关系。但后续Unidbg又支持了数个引擎,任何提高程序复杂度的行为,肯定都为了解决某个痛点。
hypervisor 引擎可以在搭载了 Apple Silicon 芯片的设备上模拟执行;
KVM 引擎可以在树莓派上模拟执行;
Dynarmic 引擎是为了更快的模拟执行;
Unicorn 是最强大最完善的模拟执行引擎,但它相比Dynarmic太慢了,同场景下,Dynarmic比Unicorn模拟执行快数倍甚至十数倍。如果使用Unidbg是为了实现生产环境下的模拟执行,速度最重要,那么Dynarmic + unidbg-boot-server 这个高并发server服务器,是完美之选。一般实操中,先使用 Unicorn 引擎跑通模拟执行代码,切换成Dynarmic无误后,直接上生产环境。
切换执行引擎
Dynarmic
1 | private static AndroidEmulator createARMEmulator() { |
Unicorn2
默认情况下自动使用
1 | private static AndroidEmulator createARMEmulator() { |
Unicorn2的执行速度比Dynarmic应该有慢几十倍。Dynarmic跑一个爆破结果5s能结束,Unicorn2跑了252s多没反应。
Hook的选择
Ⅰ 以模拟执行为目的
使用第三方Hook方案,arm32下HookZz的支持较好,arm64下Dobby的支持较好,HookZz/Dobby Hook不成功时,如果函数是导出函数,使用xHook,否则使用 Whale。
Ⅱ 以算法还原为目的
使用Console Debugger 和 Unicorn Hook,并建议不优先使用第三方Hook方案。
HookZz(wrap,instrument方法)
HookZz主项目已经完全被Dobby替代了,但是在Unidbg里面,移植还不完善,有一些功能还只有HookZz能用。
HookZz的项目地址:https://github.com/jmpews/HookZz
但是现在似乎已经停更了,被Dobby替代了。
下面是一个例子:
1 | IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz |
因为HookZz和后续的Dobby很相似,因此先解释一下。首先用wrap
方法hook了一个有符号的ss_encrypt
函数;然后又通过instrument
方法指定hook一个地址上的指令。
被Hook的这个函数是这样的:
1 | ss_encrypt(vars0, len, &key, key_len, vars0) |
hook的时候只关注了第二个和第三个参数,也就是与key数组有关系的。然后最后在postCall
又检查了一下返回值是否正常。
最后instrument的一个指令似乎是位于0xF5C的:
1 | SUB.W SP, SP, R3 |
这里的instrument就是简单的监视了一下R3寄存器和R10寄存器的值。
Dobby(replace方法)
jmpews/Dobby: a lightweight, multi-platform, multi-architecture hook framework. (github.com)
1 | Dobby dobby = Dobby.getInstance(emulator); |
根据测试,native函数是被正常执行了。
1 | int __fastcall ss_encrypted_size(int a1) |
传入的a1
是16,在postCall
的时候打印出执行结果是22。
hook代码中:
1 | HookStatus.RET(emulator, originFunction); |
的第二个参数指定的是pc寄存器的值,因此这里写入了originFunction
,因而会返回到原函数恢复执行。
修改寄存器的值(没研究)
xHook(支持PLT Hook)
https://github.com/iqiyi/xHook
1 | IxHook xHook = XHookImpl.getInstance(emulator); // 加载xHook,支持Import hook,文档看https://github.com/iqiyi/xHook |
这个Hook库可以用于把导入的函数给hook了。
Whale(没搞)
Unicorn Hook
这就是不是用第三方库,直接用Unicorn底层暴露的Hook函数来使用。
优势:
- HookZz或者xHook等方案,都可以基于其Hook实现原理进行检测,但Unicorn 原生Hook不容易被检测。
- Unicorn Hook 没有局限,其他方案局限性较大。比如Inline Hook方案不能Hook短函数,或者两个相邻的地址;PLT Hook 不能 Hook Sub_xxx 子函数。
- 第三方 inline Hook 框架和原生 Hook 方案同时使用时会摩擦出BUG的火花,事实上,单使用Unicorn的某些Hook功能都有BUG。所以说,统一用原生Hook会少一些BUG,少一些麻烦。
参考
【转载】unidbg hook 使用大全 - qinless
- 本文作者: Taardis
- 本文链接: https://taardisaa.github.io/2023/09/04/Android逆向-Unidbg-Hook工具/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!