的控制流平坦化为例。
符号执行的发展是从静态符号执行到动态符号执行到 选择性符号执行 ,动态符号执行会以具体数值作为输入来模拟执行程序,是 混合执行 (concolic execution)的典型代表,有很高的精确度,目前较新的符号执行工具有 Triton 和 angr ,本文是以angr为例。
首先写一个简单的示例程序
编译
添加控制流平坦化
1. 函数的开始地址为序言的地址
2. 序言的后继为主分发器
3. 后继为主分发器的块为预处理器
4. 后继为预处理器的块为真实块
5. 无后继的块为retn块
6. 剩下的为无用块
主要代码:
这个步骤主要是使用符号执行,为了方便,这里把真实块、序言和retn块统称为真实块,符号执行从每个真实块的起始地址开始,直到执行到下一个真实块。如果遇到分支,就改变判断值执行两次来获取分支的地址,这里用angr的inspect在遇到类型为ITE的IR表达式时,改变临时变量的值来实现,例如下面这个块
使用statement before类型的inspect
修改临时变量28为false或true再执行就可以得到分支的地址
如果遇到call指令,使用hook的方式直接返回
主要代码:
3.3 Patch二进制程序
首先把无用块都改成nop指令
然后针对没有产生分支的真实块把最后一条指令改成jmp指令跳转到下一真实块
针对产生分支的真实块把CMOV指令改成相应的条件跳转指令跳向符合条件的分支,例如CMOVZ 改成JZ ,再在这条之后添加JMP 指令跳向另一分支
上述就是去除控制流平坦化的总体实现思路。
去除指定函数的控制流平坦化
用IDA查看恢复后的CFG
可以看到CFG跟原来的大致一样,然后反编译恢复出原始代码
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