学习一下Unidbg。这是基于Unicorn的,用于模拟Android系统环境的模拟器。
Android逆向-Unidbg
项目地址
环境搭建
从项目地址中下载最新的Release源码,解压到文件夹。
然后直接用IDEA信任并打开项目文件夹。
然后为了方便起见,首先在Settings里面设置一下Proxy。
如果之前已经安装了JDK1.8了,那么后面导入了现成的SDK后就可以直接用了。
但我把之前的这些环境全部卸载了,因此需要重新安装一份。可以在Oracle官网上查jdk1.8,然后再登陆账号下载,这样太麻烦了。推荐一种比较简单的方法:进入File->Project Structure
,第一眼看到SDK,进入设置,添加新的SDK,选择Download SDK
,然后选择version
是最下面的1.8的,至于是什么公司的似乎不是很重要(我现在用的似乎是Amazon Corretto
,反正也能正常运行)。下载好并使用这个SDK,即可使用整个项目了。
为了能够正常调试,还需要将相同jdk对应的jre路径给填上去。右上角Edit Configurations
,将此项目的Build and run
的java路径具体到jre文件夹上。
普歌:社区版本的debug测试–ERROR: transport library not found: dt_socket ERROR: JDWP - 掘金 (juejin.cn)
调试模式(还没试)
- CONSOLE
- GDB_SERVER
- ANDROID_SERVER_V7(IDA7.4)
Unidbg的用处
直接借用这位爷的话: unidbg 简介、基本使用、调用so中方法、unidbg-web_unicorn unidbg_擒贼先擒王的博客-CSDN博客
现在许多 app 把签名算法已经放到了 so 文件中,所以要想破解签名算法,必须能够破解 so 文件。但是 C++ 的逆向远比 Java 的逆向要难得多了,所以好多时候是没法破解的,那么这个时候还可以采用 hook 的方法,直接读取程序中算出来的签名,但是这样的话,需要实际运行这个应用,需要模拟器或者真机,效率又不是很高。unidbg 就是一个很巧妙地解决方案,他不需要直接运行 app,也无需逆向 so 文件,而是通过在 app 中找到对应的 JNI 接口,然后用 unicorn 引擎直接执行这个 so 文件,所以效率也比较高。
现在很多的 app 使用了so加密,可能你会直接破解 so 进行算法破解,但是也可以不用破解so,利用很多大佬写好的轮子即可 直接调用 so 中的函数方法。
Unidbg分析流程
以 Unidbg 为中心去做模拟执行/算法还原时,流程是这样的
- Frida 主动调用获取一份正确结果
- Unidbg写代码尝试运行→Unidbg给出报错→补环境
- 循环往复,最后得到和Frida主动调用一致的结果
以Unidbg为中心的逆向分析里,补环境是工作重心。(最讨厌补全环境了)
Unidbg补环境
直接引用 unidbg 简介、基本使用、调用so中方法、unidbg-web_unicorn unidbg_擒贼先擒王的博客-CSDN博客 :
Unidbg 中的补环境,大体上可以分成两类,运行环境缺失和上下文缺失:
- 上下文缺失则是由于样本在运行目标函数前对SO或目标函数做了一些初始化工作,Unidbg中对目标函数单独运行,自然就导致了上下文缺失。上下文缺失相较于运行环境缺失,是一种更加隐蔽的环境缺失。
- 运行环境缺失。最简单的例子就是目标函数中通过 JNI 调用到了某个自己的 JAVA 方法,Unidbg 会及时报错,给出堆栈以及这个 JAVA 方法的签名,需要我们补上对应的 JAVA 方法。
补 JAVA 环境是补运行环境中主要的一部分,但是,补 JAVA 环境并不是工作的全部。还有哪些环境需要补呢?
- 文件读写——对linux虚拟文件的读写,对ASSETS资源文件的读写、对app目录下文件的读取,对 Sharedpreference 的读取等等
- 系统调用具体实现——比如popen函数所涉及的系统调用等
- 系统库SO,Unidbg并没有,实际上也不可能模拟完整的 Android 系统 SO 环境,有的 SO 所依赖的 SO 比较多,很难调起来,所以 Unidbg 设计了 VirtualModule(虚拟SO模块),有时候我们需要和它打交道。
- 补不了,打 patch
Unidbg 在大多数情况下是好的方案
在补环境的过程中,对算法细节有了一定的理解,而且用 Unidbg 跑出结果后,分析和还原算法会更快,因为 Unidbg 的 code trace / hook / console debugger 相比较 IDA trace,Frida hook 更快、更稳定、更方便复现。而且环境完全是我们的,有绝对的掌控。
基本使用
把简单有效的代码块放在另一个Unidbg-CheatSheet博客上。
IDA动调(没解决)
IDA7.4版本太难找了
项目打包成Jar
我个人觉得没啥用处。
File —> Project Structure … 然后选择 Artifacts,点加号 Add —> jar —> From modules with dependencies… 然后如下配置, 别忘了勾上 Include tests
OK了,Build → Build Artifacts 编译成功之后就在 unidbg-0.9.0/out/artifacts/unidbg_parent_jar 目录下生成了一堆依赖jar包和unidbg-parent.jar 我们把要载入的 fenfei/libnative-lib.so 放到和 unidbg-parent.jar同级目录
Unidbg执行引擎(没解决)
Unidbg一共有4个backend:
- dynarmic(unidbg-dynarmic)
- hypervisor(unidbg-hypervisor)
- kvm(unidbg-kvm)
- unicorn2(unidbg-unicorn2)
一般情况下默认使用的是泛用性比较广的unicorn2
,不过执行效率一般。
dynarmic
: merryhime/dynarmic: An ARM dynamic recompiler. (github.com)
一种ARM指令的recompiler
(不知道是什么概念),反正可以算作一个执行效率更高的ARM指令翻译器。
项目Demo分析
anjuke.mobile.sign.SignUtil
这是一个签名函数。
此代码主要展现了对so函数主动调用的方法。
1 | package com.anjuke.mobile.sign; |
我原来还想对此so中另外一个导出的函数尝试进行自行hook,但是发现函数原型不太好确定,遂作罢。
bytedance.frameworks.core.encrypt
TTEncrypt
首先看一下类初始化函数:总体来说没有什么特别特殊的玩意。
1 | TTEncrypt(boolean logging) { |
然后看一下ttEncrypt
函数:
首先测试了一下获取符号,指针,字节流。
1 | Symbol sbox0 = module.findSymbolByName("sbox0"); // 在libttEncrypt.so模块中查找sbox0导出符号 |
然后后面测试了各种hook工具。
HookZz
首先是HookZz:
1 | IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz |
Dobby
然后是dobby:
1 | Dobby dobby = Dobby.getInstance(emulator); |
xHook
然后是xHook:
1 | IxHook xHook = XHookImpl.getInstance(emulator); // 加载xHook,支持Import hook,文档看https://github.com/iqiyi/xHook |
这三个Hook库的解释,单独放在另一个blog上。
TTEncryptWorker(多线程,没研究)
这似乎是用于多线程爆破的。
1 | package com.bytedance.frameworks.core.encrypt; |
其他例子
unidbg非反射调用demo(一)_unidbg demo_Codeooo的博客-CSDN博客
其他项目
ExAndroidNativeEmu
一个基于Python的安卓so模拟器。用Python补环境的时候会很麻烦,不过简单代码模拟的时候会方便一点。
1 | // 因为和angr环境冲突了所以创建个venv |
还是写了一个新的blog来记录。
参考教程
oasis
学习代码也被我放在了Unidbg项目里面
Android逆向-实战so分析-某洲_v3.5.8_unidbg学习_android逆向so分析_哔哩哩!的博客-CSDN博客
calculateS
SO逆向入门实战教程二:calculateS_nativenewcalculates 算法_白龙~的博客-CSDN博客
值得注意的一个点,博主在第一次尝试直接模拟执行calculateS
JNI函数的时候遇到Unidbg报错了,在0x2C8D处。
因为这个函数确确实实的使用了第二个class参数:
1 | jbyte *__fastcall sub_2C3C(JNIEnv *a1, jclass a2) |
然而偷懒,a2传的是Null。因此就触发了空指针解引用。
不过最后看Java层的话确实有点麻烦,所以除非考虑先用Frida去Hook,拿到具体的class,再到这里来做解析,否则就最好选择直接patch掉这一块代码。
right573
【精选】SO逆向入门实战教程三:V2-Sign_unidbg context_白龙~的博客-CSDN博客
这补环境就纯玄学
mfw_so
主要是分析SHA1算法魔改。
s
【精选】SO逆向入门实战教程六:s_undibg调用安卓_白龙~的博客-CSDN博客
增加了Java反射的方法,相比嗯加Jni方法可能会轻松点
不过补环境的时候还是很折磨
参考
Unidbg(一)环境安装及配置_unidbg环境配置_FalsePlus的博客-CSDN博客
Crack App | 初试 Unidbg 环境搭建-腾讯云开发者社区-腾讯云 (tencent.com)
unidbg 简介、基本使用、调用so中方法、unidbg-web_unicorn unidbg_擒贼先擒王的博客-CSDN博客
- 本文作者: Taardis
- 本文链接: https://taardisaa.github.io/2023/08/28/Android逆向-Unidbg/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!