OLLVM静态还原-0

反混淆的主流程

在接下来的好几个章节中,我们将讨论如何静态对抗Flat控制流混淆技术,包括从较为初级的裸状态变量的Flat混淆到一些对于状态变量保护后的flat混淆。

首先,对于Flat混淆技术的对抗核心的问题是攻击状态变量来还原控制流,会包含以下这些流程:

  1. 定位状态变量

  2. 定位分发块/真实块等

  3. 还原状态变量在真实块的值,确认真实的控制流

  4. 使用上面的信息,最终还原控制流结构

但是,在当前的对抗环境下,每一步有很多的困难,尤其是各种增强或者变种后的Flat技术,这些技术会想办法来保护混淆状态变量,比如:

  1. 状态变量特殊化,不再是一个局部变量,甚至是多重状态变量

  2. 控制流插入状态变量的计算后比较逻辑,不直接比较大数

  3. 虚假控制流干扰对于分支逻辑的判断

  4. 状态变量混合执行流程

  5. 混合其它的混淆方案

使用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