Processing math: 0%

obfuscation && deobfuscation(1)

之前只会用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

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

image-20200613002226907

图2 加入虚假控制流之前的控制流图
![image-20200613002256501](https://ycdxsb-1257345996.cos.ap-beijing.myqcloud.com/blog/2020-07-11-133339.jpg)
图3 加入虚假控制流后的控制流图

控制流平坦化#

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

image-20200613204052796

image-20200613204052796

图4 控制流平坦化前
![image-20200613204121588](https://ycdxsb-1257345996.cos.ap-beijing.myqcloud.com/blog/2020-07-11-133354.jpg)
图5控制流平坦化后
注意:这里的基本块号其实标错了,但不影响简单的理解主分发器和基本块的关系

这里也给出论文里对函数f的控制流平坦化示例:

image-20200613204513328

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

image-20200613210045156

控制流平坦化编译#

1
/build/bin/clang check_passwd.c -o check_passwd_flat -mllvm-fla

emmmm,太大了,还是用腾讯的图好了

image-20200613210742907

image-20200613210742907

参考资料#

评论

Powered By Valine
v1.4.14