1. 背景
1.1 控制流平坦化

经过控制流平坦化后的执行流程就如下图

这样可以模糊基本块之间的前后关系,增加程序分析的难度,同时这个流程也很像VM的执行流程。更多控制流平坦化的细节可以看Obfuscating C++ programs via control flow flattening,本文以Obfuscator-LLVM的控制流平坦化为例。
1.2 符号执行
符号执行的发展是从静态符号执行到动态符号执行到选择性符号执行,动态符号执行会以具体数值作为输入来模拟执行程序,是混合执行(concolic execution)的典型代表,有很高的精确度,目前较新的符号执行工具有Triton和angr,本文是以angr为例。
2. 分析

编译


添加控制流平坦化


3. 实现
3.1 获取真实块、序言、retn块和无用块
2. 序言的后继为主分发器
3. 后继为主分发器的块为预处理器
4. 后继为预处理器的块为真实块
5. 无后继的块为retn块
6. 剩下的为无用块

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

使用statement before类型的inspect


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

主要代码:

3.3 Patch二进制程序
首先把无用块都改成nop指令

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

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

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

用IDA查看恢复后的CFG

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

5. 总结
6. 参考
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
评论留言
25