OLLVM静态还原-0
反混淆的主流程
在接下来的好几个章节中,我们将讨论如何静态对抗Flat控制流混淆技术,包括从较为初级的裸状态变量的Flat混淆到一些对于状态变量保护后的flat混淆。
首先,对于Flat混淆技术的对抗核心的问题是攻击状态变量来还原控制流,会包含以下这些流程:
定位状态变量
定位分发块/真实块等
还原状态变量在真实块的值,确认真实的控制流
使用上面的信息,最终还原控制流结构
但是,在当前的对抗环境下,每一步有很多的困难,尤其是各种增强或者变种后的Flat技术,这些技术会想办法来保护混淆状态变量,比如:
状态变量特殊化,不再是一个局部变量,甚至是多重状态变量
控制流插入状态变量的计算后比较逻辑,不直接比较大数
虚假控制流干扰对于分支逻辑的判断
状态变量混合执行流程
混合其它的混淆方案
使用IDA Pro和他的中间语言micorocode作为的还原的工具,选择IDA的原因是这个工作很方便,大家都会用;
虽然他的micorocode相关的资料比较匮乏,但是现有的开源资料已经足够完成后面的工作了。
样例二进制(借用一下OBPO):
熟悉IDA-micorocode
安装lucid插件:
首先需要清楚IDA实现F5中的几个优化过程:
MMAT_ZERO
microcode does not exist
MMAT_GENERATED
generated microcode
MMAT_PREOPTIMIZED
preoptimized pass is complete
MMAT_LOCOPT
local optimization of each basic block is complete.
control flow graph is ready too.
MMAT_CALLS
detected call arguments. see also hxe_calls_done
MMAT_GLBOPT1
performed the first pass of global optimization
MMAT_GLBOPT2
most global optimization passes are done
MMAT_GLBOPT3
completed all global optimization. microcode is fixed now.
MMAT_LVARS
allocated local variables
在这个系列中,我们尽可能的在更高层的中间语言执行优化,也就是说尽可能在IDA的其它优化之后执行优化。这么做的原因是,借用IDA的常量传播等优化功能,可以省去很多复杂的跨basic-block的分析工作。
插件优化层次的选择
越是往后,IDA本身的优化越多。
插件的优化所在的层次和插件本身的功能和需求有关。例如,这一次我实现的是一个以攻击状态变量为主的OLLVM还原插件,那么可以列出以下这些要求:
需要有清晰的状态变量+用常量给状态变量赋值+状态变量比较常量
状态变量的个数,尽可能收敛
通过对中间语言的查看,上面的需求至少是要在MMAT_CALLS及以上实现。
说明:比如汇编里面有这样的代码
在MMAT_LOCOPT优化层,中间语言长这样,和汇编的意思差不多:

但是MMAT_CALLS 优化层,由于执行了常量传播+替换,w11和w12直接被替换成了常量,因此就可以直接看出来是状态变量的比较操作了。

所以这个反混淆优化的层次,最少要在MMAT_CALLS之上实现,
基础样例的反混淆流程
识别状态变量:
状态变量区分基本块:
识别分发块 -> 真是块 状态变量的入度:
找到真实块中状态变量的赋值点:
在中间语言还原控制流:
识别状态变量
使用一种较为朴素的方案:
遍历所有的中间语言,查找最多的用于比较固定值后跳转的变量,代码如下:
可以直接在IDA的File -> Script Command 复制黏贴并执行这部分代码,然后在sub_172BC函数按下F5就能在console中看到输出结果了。
因此,w8.4 w9.1 w10.4 这三个变量的使用此时明显超过了正常的情况,很有可能是状态变量。
可以在lucid的输出结果中与汇编进行对比。
Last updated