前言

ctf中像ollvm混淆过的,或者其他混淆器混淆过的,还有虚拟机的等等逆向题都可以用angr约束求解从而省去分析的时间。

正文

下面就自己写的一个小例子,来看看怎么用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

//austctf{ollvm_obfuscation_is_never_a_problem}
int main(int argc,char** argv,char** envp){
//char input[45];
if(argc<2){puts("./a.out flag");return 0;}
char* input=argv[1];
int arr1[]={0x0ceb6941,0x341a8af6,0x23a54c79,0x025c5e8c,0x105dd6ae,0x09175709,0x02672ca5,0x36b42f99,0x3d5cd4b0,0x02d0971c,0x29870f1d,0x08fd9db7,0x10c84055,0x2d52a527,0x1f0cca9c,0x1c43ff49,0x2b40f1d4,0x33011ef0,0x3ff17b24,0x20f4f0e2,0x09cf127a,0x08140c75,0x2f27c415,0x121de529,0x01c0ec22,0x0535697d,0x3bbed813,0x1d4405d9,0x3a65211a,0x359bfa89,0x39988a59,0x14a6c133,0x277ad110,0x3169cf4b,0x212d5172,0x352fdf53,0x1bdc1cda,0x26bc3f7f,0x3d9ed50e,0x23a93535,0x3a51bfe0,0x2a1a1297,0x1c1510e3,0x03134abc,0x2e09c0ad};
int arr2[]={0x0ceb6920,0x341a8a83,0x23a54c0a,0x025c5ef8,0x105dd6cd,0x0917577d,0x02672cc3,0x36b42fe2,0x3d5cd4df,0x02d09770,0x29870f71,0x08fd9dc1,0x10c84038,0x2d52a578,0x1f0ccaf3,0x1c43ff2b,0x2b40f1b2,0x33011e85,0x3ff17b57,0x20f4f081,0x09cf121b,0x08140c01,0x2f27c47c,0x121de546,0x01c0ec4c,0x05356922,0x3bbed87a,0x1d4405aa,0x3a652145,0x359bfae7,0x39988a3c,0x14a6c145,0x277ad175,0x3169cf39,0x212d512d,0x352fdf32,0x1bdc1c85,0x26bc3f0f,0x3d9ed57c,0x23a9355a,0x3a51bf82,0x2a1a12fb,0x1c151086,0x03134ad1,0x2e09c0d0};
for(int i=0;i<45;i++){
if(input[i]!=(char)(arr1[i]^arr2[i])){
puts("不对再猜猜");
return 0;
}
}
puts("哦豁,流批啊兄dei");
return 0;
}

经过ollvm混淆过后ida中控制流程图和伪c代码如下


c代码很可怕,但是用angr求解的话只需要一个简单脚本,只需要2分钟,当然也需要我们找到两个关键的地方,即提示正确和错误的分支

1
2
3
4
5
6
7
8
import angr
import claripy
proj = angr.Project("./a.out") #创建工程
argv1 = claripy.BVS('argv1',50*8) #这里约束字符串的长度50个字符*8个比特
state = proj.factory.entry_state(args=['./a.out',argv1]) #入口点处状态
simgr = proj.factory.simgr(state) #初始化进程模拟器
simgr.explore(find=0x401516,avoid=0x401183) #find是要查找的路径,avoid是要避免的路径
print(simgr.found[0].solver.eval(argv1)) #找到的路径对应的解

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ubuntu@VM-0-5-ubuntu:~/angrtest$ python3 main.py
WARNING | 2019-05-15 00:02:55,653 | angr.state_plugins.symbolic_memory | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2019-05-15 00:02:55,654 | angr.state_plugins.symbolic_memory | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2019-05-15 00:02:55,654 | angr.state_plugins.symbolic_memory | 1) setting a value to the initial state
WARNING | 2019-05-15 00:02:55,654 | angr.state_plugins.symbolic_memory | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2019-05-15 00:02:55,654 | angr.state_plugins.symbolic_memory | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY_REGISTERS}, to suppress these messages.
WARNING | 2019-05-15 00:02:55,654 | angr.state_plugins.symbolic_memory | Filling register r15 with 8 unconstrained bytes referenced from 0x401860 (__libc_csu_init+0x0 in a.out (0x401860))
WARNING | 2019-05-15 00:02:55,657 | angr.state_plugins.symbolic_memory | Filling register r14 with 8 unconstrained bytes referenced from 0x401862 (__libc_csu_init+0x2 in a.out (0x401862))
WARNING | 2019-05-15 00:02:55,660 | angr.state_plugins.symbolic_memory | Filling register r13 with 8 unconstrained bytes referenced from 0x401867 (__libc_csu_init+0x7 in a.out (0x401867))
WARNING | 2019-05-15 00:02:55,662 | angr.state_plugins.symbolic_memory | Filling register r12 with 8 unconstrained bytes referenced from 0x401869 (__libc_csu_init+0x9 in a.out (0x401869))
WARNING | 2019-05-15 00:02:55,667 | angr.state_plugins.symbolic_memory | Filling register rbx with 8 unconstrained bytes referenced from 0x40187a (__libc_csu_init+0x1a in a.out (0x40187a))
WARNING | 2019-05-15 00:02:55,734 | angr.state_plugins.symbolic_memory | Filling register cc_ndep with 8 unconstrained bytes referenced from 0x4005c1 (register_tm_clones+0x21 in a.out (0x4005c1))
983058422689711008096173569442318819174690826169295271715143449687565245228593338661636664402647006866087328351617286144
ubuntu@VM-0-5-ubuntu:~/angrtest$ python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import binascii
>>> binascii.a2b_hex(hex(983058422689711008096173569442318819174690826169295271715143449687565245228593338661636664402647006866087328351617286144)[2:])
b'austctf{ollvm_obfuscation_is_never_a_problem}\x00\x00\x00\x00\x00'
>>>

这里我们只是约束了字符串的长度,对字符集没有进行约束,约束了字符集以后会运行更快,这样这道题目的工作就简化到了找到要避免的路径和要寻找的分支上面