OLLVM混淆
OLLVM混淆
LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。
个人感觉OLLVM混淆大都是while true的嵌套,而OLLVM的破解一般都用angr
虚假控制流 (Bogus control flow)
在讲虚假控制流之前,我们看看别的,利用不透明谓词混淆代码的原理是什么?
不透明谓词是指一个表达式,他的值在执行到某处时,对程序员而言必然是已知的,但是由于某种原因,编译器或者说静态分析器无法推断出这个值,只能在运行时确定。
不透明谓词的设计必须满足俩条件
1,对于混淆器也就是开发者,它的值在执行到某阶段总是确定的。
2,对于分析器,也就是攻击者,只有执行到某阶段才能确切的知道它的值。
条件一和条件二完美符合,那么这个不透明谓词就算是一个高质量的设计。
原理其实挺简单,但是要设计出简单高效高质量的不透明谓词,是比较难的。
在将代码转换成汇编和机器码之前,编译器中的一种代码表示形式,可以简单的理解为具有跨平台性和其他特性的汇编,正确解释请看编译原理或了解一下LLVM和OLLVM。
虚假控制流的流程表示
用 OLLVM 项目中的注释部分就可以清晰表示出什么是虚假控制流。可以看到,相对于原程序中的单个代码块,混淆后的程序中加入了一个由不透明谓词组成的条件语句,由于混淆器知道他的值,所以可以保证被混淆程序的正确性,执行被混淆程序原本的代码,而编译器和反编译器都无法对这个表达式进行求值,只能保留此谓词,达到干扰静态分析的目的。
简单来说,通过大量的if和while语句来混淆反编译器,只有混淆器知道正确的路
Before : |
怎么实现混淆
在其他项目中
在 OLLVM 中,使用了 y > 10 || x * (x + 1) % 2 == 0
这个不透明谓词,学过数学的都知道,x * (x + 1) % 2 == 0
是个永真式。也就是说,混淆器已经知道了 y > 10 || x * (x + 1) % 2 == 0
这个式子的值,所以可以将其放在条件语句中,控制代码的走向;而编译器和反编译器都认为这个表达式需要进行运行后才能求值,会保留这段代码,进而干扰到反编译器。
在HikariObfuscator这个项目中使用 IRBuilder 生成一箩筐的整数运算,由于 LLVM 的 IRBuilder 会折叠常量,混淆器就能知道了之前生成的一箩筐的整数运算的最终结果,而编译器和反编译器都不知道生成的表达式的值,所以就获得了一个崭新的不透明谓词。
当然,上面的两个混淆都有较为简单的破解方法,就是将不透明谓词中的变量修改成常量,并且设置一个初始值,这时候 Hex-rays 等反编译器会对不透明谓词进行求值,如果不透明谓词的结果可知,那么这个表达式将会被优化。
具体实现混淆
有时间实操一下
去OLLVM
使用deflat.py反混淆
使用方法: python deflat.py -f path/to/binary –addr hexaddress
path/to/binary填文件,hexaddress填函数入口地址。
python deflat.py -f /home/phantomor/Desktop/EasyRe –addr 0x400A0D
[安洵杯 2019]game
打开一看是个Sudoku题,
点开函数一看
使用上述工具对主要函数去混淆check1、check3
size_t __fastcall check1(char *a1) |
int __fastcall check3(char *a1) |
最后把Sudoku做好 |
脚本
int main() |