unidgb 经验
参数
context 如何构造
DvmObject<?> context = vm.resolveClass(“android/content/Context”).newObject(null);// context
字符串类型如何构造
list.add(vm.addLocalObject(context));
list.add(vm.addLocalObject(new StringObject(vm, “12345”)));
list.add(vm.addLocalObject(new StringObject(vm, “r0ysue”)));
除了基本类型,比如 int,long 等,其他的对象类型一律要手动 addLocalObject
Hash 算法
一个哈希算法,可以简单划分成填充和加密两部分
多次测试发现不论输入明文多长,都输出固定长度结果,所以疑似哈希算法。
输出恒为 40 位,疑似哈希算法中的 SHA1 算法。
输出恒为 32 位,疑似哈希算法中的 MD5 算法。
SHA1 算法的运算部分是由什么组成?SHA1 和 MD5 采用了相同的结构,每 512 比特分组需要一轮运算,我们的输入长度不超过一个分组的长度,所以只用考虑一轮运算。一轮运算是 80 步,每隔 20 步是一种模式。
MD5 特征
- 输出结果是 32 位。
- 有四个 IV,MD5 就有四个 IV
- 1.是 0x67452301 0xefcdab89 等四个魔术,但单靠这四个数证明不了是 MD5,也可能是别的哈希算法,除此之外,算法可能魔改常数。
- MD5 的 64 个 K,K1-K64 是 MD5 独特的标志,简单的魔改也不会改 K 值。(其实 K 表也可以随便改,但一般的开发人员也不懂 K 的意义,不敢乱改。)
1 | |
python MD5 源码
1 | |
SHA1 算法
Thumb 指令
ARM32 有 Thumb 和 ARM 两种指令模式,ida 查看到的地址是 thumb 模式
ida 里面查看的指令地址需要+1
unidgb 输出的地址不需要+1
何判断是 Thumb 还是 Arm 模式:
ARM 模式指令总是 4 字节长度,Thumb 指令长度多数为 2 字节,少部分指令是 4 字节。
Hook
Unidbg 内嵌了多种 Hook 工具,目前主要是四种
- Dobby
- HookZz
- xHook
- Whale
xHook 是爱奇艺开源的基于 PLT HOOK 的 Hook 框架,它无法 Hook 不在符号表里的函数,也不支持 inline hook,这在我们的逆向分析中是无法忍受的,所以在这里不去理会它。
Whale 在 Unidbg 的测试用例中只有对符号表函数的 Hook,没看到 Inline Hook 或者 非导出函数的 Hook,所以也不去考虑。
HookZz 是 Dobby 的前身,两者都可以 Hook 非导出表中的函数,即 IDA 中显示为 sub_xxx 的函数,也都可以进行 inline hook,所以二选一就行了。我喜欢 HookZz 这个名字,所以就 HookZz 了
1 | |
通常会有个参数是 buffer,在执行前 preCall 将其 push 保存,执行完毕 postCal 再 pop 取出
1 | |
1 | |
打 PATCH 一
地址:0x1E86
汇编:MOV R0,1
查看“mov r0,1”的机器码,使用ARMConvert 转换成 4FF00100
1 | |
打 PATCH 二
1 | |
打印地址所指向的内存
打印地址所指向的内存,其效果类似于 frida 中 hexdump。
1 | |
treemap 参数
1 | |
需要注意的是,代码中补齐了 treeMap 的继承关系:map→AbstractMap→TreeMap,这么做是必要的,否则在有些情况下会报错
补环境
如果缺失的环境比较多,来源于某个 java 类。
- 不继承自 AbstractJni
- vm.setJni(this);改成 vm.setDvmClassFactory(new ProxyClassFactory());
然后根据提示复制相关的类到指定位置
对象数组参数怎么构造

1 | |
补文件访问
方法 1

unidbg 对文件做了重定向,打印虚拟目录日志,把缺失的文件放入虚拟目录, 不存在的目录创建即可。
方法 2:
使用代码补
1 | |
JNItrace
jnitrace 可以跟踪所有的 jni 调用,特别适合 unidgb 补环境使用。因为 so 层会有很多通过 jni 来调用 java 层的方法。
1 | |
SO 依赖
报错
1 | |
解决方法:
1 | |
1 | |
注意:加顺序,依赖项必须较
- 先加载加载顺序,依赖项必须较加载顺序,依赖项必须较先加载
- 如果依赖库缺失环境报错,只要我们的目标 so 没用用到该函数,可以不用管。用到了就必须要补。
第二种 unidgb 提供了案例参考:
IO 重定向 、系统调用、文件访问(星球样本 1)
报错:
1 | |
openat 的系统调用 ,打开 proc/9720/status 文件
proc 文件系统由内核提供,系统中正在运行的每个进程都有对应的一个目录在 proc 下,其以进程的 PID 号为目录名,这个目录是读取进程信息的接口。 所以说“proc/9720/status”,就是读取 9720 这个进程的相关信息
在 Android 系统中,cmdline 里是应用的进程名,而 Status,则包含的信息非常多:可执行文件名、当前 状态、PID 和 PPID、实际及有效的 UID 和 GID、内存使用情况、以及其他。
可以用 adb shell 进入文件目录验证: cat status
利用 unidgb IO 重定向,补文件访问
1 | |
1 | |
补 Application
1 | |
继承关系
android/content/Context → android/content/ContextWrapper→android/app/Application
returnvm.resolveClass(“android/app/returnvm.resolveClass(“android/app/Application”).newObject(signature);Application”).newObject(signature);
为什么要补继承关系?
1 | |
1 | |
设置日志为 debug
1 | |