这是一篇漫谈Unidbg的文章,我对Unidbg的使用和理解都还很浅,日后会更新或修改看法,欢迎大佬指点,也期待同侪讨论。
我们常规使用Frida + IDA的动静态分析中,工作可能是这样的
找线索→Frida Hook验证→验证成功继续下一步/验证失败继续找线索
而以Unidbg为中心去做模拟执行/算法还原时,工作是这样的
可以发现,在以Frida为中心的逆向分析中,写hook代码是工作重心,而以Unidbg为中心的逆向分析里,补环境是工作重心。
一言以蔽之,补环境。
Unidbg中的补环境,大体上可以分成两类,运行环境缺失和上下文缺失,上下文缺失则是由于样本在运行目标函数前对SO或目标函数做了一些初始化工作,Unidbg中对目标函数单独运行,自然就导致了上下文缺失。
运行环境缺失很好理解,最简单的例子就是目标函数中通过JNI调用到了某个自己的JAVA方法,Unidbg会及时报错,给出堆栈以及这个JAVA方法的签名,需要我们补上对应的JAVA方法,前五篇文章所涉及的都是这种情况。需要注意,补JAVA环境是补运行环境中主要的一部分,后续会有好几篇文章强化如何补JAVA环境,几个非常棒的实例。但是,补JAVA环境并不是工作的全部。还有哪些环境需要补呢?
运行环境缺失的问题是摆在明面上的,根据报错一步步补就行,只要补对了、补全了就没问题。
样本在运行目标函数前对SO或目标函数做了一些初始化工作,不论这些初始化工作是什么形式,它们所作的事就是修改了目标SO的代码/数据,如果我们在Unidbg中只对目标函数单独模拟,结果一定是出问题(因为相当于我们用了错误的SO嘛)。
这类环境缺失我们称之为上下文缺失,上下文缺失相较于运行环境缺失,是一种更加隐蔽的环境缺失。它常常难倒Unidbg的使用者,我们后续也会用数个实例来讲解上下文缺失的系统化处理办法。
从二、三我们可以意识到,样本的环境缺失越严重,Unidbg的性价比越低。打个比方,在native中和1000个JAVA方法交互,每次调用目标函数访问其中的50个,可想而知是很大的工作量。又或者初始化SO的函数非常多且非常隐蔽,难以发觉。。。你只知道自己的垃圾代码报错了,但永远不知道哪个地方没做到位。我个人认为这也是反Unidbg很有效的一个办法。
在补环境的过程中,对算法细节有了一定的理解,而且用Unidbg跑出结果后,分析和还原算法会更快,因为 Unidbg 的 code trace / hook / console debugger 相比较 IDA trace,Frida hook 更快、更稳定、更方便复现。而且环境完全是我们的,有绝对的掌控。
有的朋友,使用 rpc 遇到了风控或者未知错误,就想知道Unidbg是否可以避免这些问题——当然不行啦,本质都是黑盒调用,谁也不比谁更管用。
Unidbg并不是过往某个工具的替代品,而是IDA、Frida以及其工具套件的互补品。它和过去的工具结合在一起1+1>2,我们会在后面的例子里阐述这一点。欢迎大佬指点。