转载

利用符号执行去除控制流平坦化

这样可以模糊基本块之间的前后关系,增加程序分析的难度,同时这个流程也很像VM的执行流程。更多控制流平坦化的细节可以看 Obfuscating C++ programs via control flow flattening ,本文以 Obfuscator-LLVM

的控制流平坦化为例。 

1.2 符号执行

符号执行 是一种重要的形式化方法和软件分析技术,通过使用符号执行技术,将程序中变量的值表示为符号值和常量组成的计算表达式,符号是指取值集合的记号,程序计算的输出被表示为输入符号值的函数,其在软件测试和程序验证中发挥着重要作用,并可以应用于程序漏洞的检测。

符号执行的发展是从静态符号执行到动态符号执行到 选择性符号执行 ,动态符号执行会以具体数值作为输入来模拟执行程序,是 混合执行 (concolic execution)的典型代表,有很高的精确度,目前较新的符号执行工具有 Triton 和 angr ,本文是以angr为例。 

2. 分析

首先写一个简单的示例程序

利用符号执行去除控制流平坦化

编译

利用符号执行去除控制流平坦化

用IDA查看未经过控制流平坦化的控制流程图(CFG) 

利用符号执行去除控制流平坦化

添加控制流平坦化

利用符号执行去除控制流平坦化

可以看到控制流平坦化后的CFG非常漂亮 

利用符号执行去除控制流平坦化

通过分析可以发现原始的执行逻辑只在真实块(自己想的名称...)以及序言和retn块中,其中会产生分支的真实块中主要是通过CMOV指令来控制跳转到哪一个分支,因此只要确定这些块的前后关系就可以恢复出原始的CFG,这个思路主要是参考 Deobfuscation: recovering an OLLVM-protected program 。 

3. 实现

3.1 获取真实块、序言、retn块和无用块

由于angr的CFG跟IDA的有点不同,因此本文使用 BARF 来获取,后来问了Fish Wang可以用 angr-management 下的to_supergraph来获取。 主要思路: 

1. 函数的开始地址为序言的地址

2. 序言的后继为主分发器

3. 后继为主分发器的块为预处理器

4. 后继为预处理器的块为真实块

5. 无后继的块为retn块

6. 剩下的为无用块

主要代码:

利用符号执行去除控制流平坦化


3.2 确定真实块、序言和retn块的前后关系

这个步骤主要是使用符号执行,为了方便,这里把真实块、序言和retn块统称为真实块,符号执行从每个真实块的起始地址开始,直到执行到下一个真实块。如果遇到分支,就改变判断值执行两次来获取分支的地址,这里用angr的inspect在遇到类型为ITE的IR表达式时,改变临时变量的值来实现,例如下面这个块

利用符号执行去除控制流平坦化

使用statement before类型的inspect 

利用符号执行去除控制流平坦化


修改临时变量28为false或true再执行就可以得到分支的地址 

利用符号执行去除控制流平坦化

如果遇到call指令,使用hook的方式直接返回 

利用符号执行去除控制流平坦化

主要代码:

利用符号执行去除控制流平坦化

3.3 Patch二进制程序 


首先把无用块都改成nop指令

利用符号执行去除控制流平坦化

然后针对没有产生分支的真实块把最后一条指令改成jmp指令跳转到下一真实块

利用符号执行去除控制流平坦化

针对产生分支的真实块把CMOV指令改成相应的条件跳转指令跳向符合条件的分支,例如CMOVZ 改成JZ ,再在这条之后添加JMP 指令跳向另一分支

利用符号执行去除控制流平坦化

上述就是去除控制流平坦化的总体实现思路。 

4. 演示

去除指定函数的控制流平坦化

利用符号执行去除控制流平坦化

用IDA查看恢复后的CFG

利用符号执行去除控制流平坦化

可以看到CFG跟原来的大致一样,然后反编译恢复出原始代码 

利用符号执行去除控制流平坦化

5. 总结

本文主要针对x86架构下Obfuscator-LLVM的控制流平坦化,但最重要的是去除控制流平坦化过程中的思路,同时当函数比较复杂时可能速度会有点慢。有时间会以此为基础尝试分析伪造控制流、指令替换和VM等软件保护手段,另外符号执行也可以应用于漏洞挖掘领域,例如借助符号执行生成覆盖率更高的Fuzzing测试集以及求解达到漏洞点的路径等。本文相关的脚本deflat请移步到TSRC实验室下载。

由于小弟刚学习符号执行,可能有理解错误的地方,欢迎研究符号执行或者认为有更好思路的师傅们批评指正。最后,感谢angr主要开发者Fish Wang在这期间的耐心帮助。 

6. 参考

1. Obfuscating C++ programs via control flow flattening

2. https://github.com/obfuscator-llvm/obfuscator/tree/llvm-3.6.1

3. Symbolic Execution and Program Testing

4. Selective Symbolic Execution

5. CUTE: A Concolic Unit Testing Engine for C

6. https://github.com/JonathanSalwan/Triton

7. https://github.com/angr/angr

8. http://blog.quarkslab.com/deobfuscation-recovering-an-ollvm-protected-program.html

9. https://github.com/programa-stic/barf-project

10. https://github.com/angr/angr-management

原文  https://security.tencent.com/index.php/blog/msg/112
正文到此结束
Loading...