之前只会用deflat.py,最近正好学了angr,而且看了下代码也只有三百行不到,所以打算对应着康康原理和代码
第一部分简单讲一下工具使用和obfuscation原理
obfuscator
是论文《Obfuscator-LLVM — Software Protection for the Masses》的研究成果
安装
1 2 3 4 5 6
| git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git cd obfuscator mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF .. make
|
指令替换
指令替换是将简单的运算替换为较为复杂的运算

image-20200613001154466
图1 指令替换表目前支持将加法、减法、与、或、异或替换成等价的相对复杂的运算表达
使用时通过加入参数-mllvm -sub
使用,并可以通过-mllvm -sub_loop=num
指定替换的次数为num
次,例如-mllvm -sub_loop=3
虚假控制流
虚假控制流是在原来的控制流图上,通过加入条件跳转语句跳转到一个原来的基本块或者是一个虚假的基本块,并最终跳转回条件跳转语句,引入循环结构,改变控制流图。
使用时通过加入参数-mllvm -bcf
使用,也可以同上一样设置混淆次数-mllvm -bcf_loop=num
文中使用的是论文团队之前的工作Bogus Control Flow Insertion
,
举例:
1 2 3 4 5 6
| void f(int x){ int i; for(i=0;i<x;i++){ printf("%d",i); } }
|
对于上面的函数f,展开前和展开后的结果分别如图2,图3所示

image-20200613002226907
图2 加入虚假控制流之前的控制流图
图3 加入虚假控制流后的控制流图控制流平坦化
我们知道一个函数内存在自己的控制流和基本块,控制流平坦化,就是使用一个主分发块,通过条件控制分别进入不同的基本块,然后再回到主分发块,虽然逻辑和原来的程序相同,但分析起来更加复杂,类似于虚拟机,这里用腾讯博客中的图看起来条理比较清晰

image-20200613204052796
图4 控制流平坦化前
图5控制流平坦化后注意:这里的基本块号其实标错了,但不影响简单的理解主分发器和基本块的关系
这里也给出论文里对函数f的控制流平坦化示例:

image-20200613204513328
图6 函数f控制流平坦化结果在工具使用时,加入参数
-mllvm -fla进行对控制流的平坦化处理,也可以加入
-mllvm -split激活基本块细分,
-mllvm -split_num=num将基本块分为
num份
示例 check_password
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <stdio.h> #include <stdlib.h> #include <string.h>
int check_password(char *passwd) { int i, sum = 0; for (i = 0; ; i++) { if (!passwd[i]) { break; } sum += passwd[i]; } if (i == 4) { if (sum == 0x1a1 && passwd[3] > 'c' && passwd[3] < 'e' && passwd[0] == 'b') { if ((passwd[3] ^ 0xd) == passwd[1]) { return 1; } puts("Orz..."); } } else { puts("len error"); } return 0; }
int main(int argc, char **argv) { if (argc != 2) { puts("error"); return 1; } if (check_password(argv[1])) { puts("Congratulation!"); } else { puts("error"); } return 0; }
|
正常编译
1
| gcc check_passwd.c -o check_passwd
|

image-20200613210045156
控制流平坦化编译
1
| /build/bin/clang check_passwd.c -o check_passwd_flat -mllvm-fla
|
emmmm,太大了,还是用腾讯的图好了

image-20200613210742907
参考资料