angr

First Post:

Last Update:

主要是记录一下这些脚本,真正理解暂时有点困难

附上大佬的教程:https://github.com/ZERO-A-ONE/AngrCTF_FITM

一.good:

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __cdecl main(int argc, const char **argv, const char **envp)
{
signed int i; // [esp+1Ch] [ebp-1Ch]
char s1[9]; // [esp+23h] [ebp-15h]
unsigned int v6; // [esp+2Ch] [ebp-Ch]

v6 = __readgsdword(0x14u);
printf("Enter the password: ");
__isoc99_scanf("%8s", s1);
for ( i = 0; i <= 7; ++i )
s1[i] = complex_function(s1[i], i);
if ( !strcmp(s1, "JACEJGCS") )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

使用Angr的步骤可以分为:

  • 创建 project
  • 设置 state
  • 新建符号量 : BVS (bitvector symbolic ) 或 BVV (bitvector value)
  • 把符号量设置到内存或者其他地方
  • 设置 Simulation Managers , 进行路径探索的对象
  • 运行,探索满足路径需要的值
  • 约束求解,获取执行结果

angr脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import angr
import sys
def Go():
path_to_binary = "./00_angr_find"
project = angr.Project(path_to_binary, auto_load_libs=False)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)

print_good_address = 0x8048678
simulation.explore(find=print_good_address)

if simulation.found:
solution_state = simulation.found[0]
solution = solution_state.posix.dumps(sys.stdin.fileno())
print("[+] Success! Solution is: {}".format(solution.decode("utf-8")))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
Go()

二.good_avoid

angr脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import angr
import sys
def Go():
path_to_binary = "./01_angr_avoid"
project = angr.Project(path_to_binary, auto_load_libs=False)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)

avoid_me_address = 0x080485A8
maybe_good_address = 0x080485E0

simulation.explore(find=maybe_good_address, avoid=avoid_me_address)

if simulation.found:
solution_state = simulation.found[0]
solution = solution_state.posix.dumps(sys.stdin.fileno())
print("[+] Success! Solution is: {}".format(solution.decode("utf-8")))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
Go()

这个我试着跑了一下,挺成功的

三.多个good或avoid

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int __cdecl main(int argc, const char **argv, const char **envp)
{
signed int i; // [esp+18h] [ebp-40h]
signed int j; // [esp+1Ch] [ebp-3Ch]
char s1[20]; // [esp+24h] [ebp-34h]
char s2[4]; // [esp+38h] [ebp-20h]
int v8; // [esp+3Ch] [ebp-1Ch]
unsigned int v9; // [esp+4Ch] [ebp-Ch]

v9 = __readgsdword(0x14u);
for ( i = 0; i <= 19; ++i )
s2[i] = 0;
*(_DWORD *)s2 = 1381128278;
v8 = 1381320010;
printf("Enter the password: ");
__isoc99_scanf("%8s", s1);
for ( j = 0; j <= 7; ++j )
s1[j] = complex_function(s1[j], j + 8);
if ( !strcmp(s1, s2) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}
1
2
3
4
5
6
7
8
9
int __cdecl complex_function(signed int a1, int a2)
{
if ( a1 <= 64 || a1 > 90 )
{
puts("Try again.");
exit(1);
}
return (31 * a2 + a1 - 65) % 26 + 65;
}

angr的exp

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
import angr
import sys
def Go():
path_to_binary = "./02_angr_find_condition"
project = angr.Project(path_to_binary, auto_load_libs=False)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
if b'Good Job.' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
if b'Try again.' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
solution_state = simulation.found[0]
solution = solution_state.posix.dumps(sys.stdin.fileno())
print("[+] Success! Solution is: {}".format(solution.decode("utf-8")))
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

引用了两个函数可以动态的获取地址,而不是之前“写死”

四.符号化寄存器

程序源码:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // eax
int v5; // edx
int v6; // ST1C_4
unsigned int v7; // ST14_4
unsigned int v9; // [esp+8h] [ebp-10h]
unsigned int v10; // [esp+Ch] [ebp-Ch]

printf("Enter the password: ");
v4 = get_user_input();
v6 = v5;
v7 = complex_function_1(v4);
v9 = complex_function_2(v3);
v10 = complex_function_3(v6);
if ( v7 || v9 || v10 )
puts("Try again.");
else
puts("Good Job.");
return 0;
}


int get_user_input()
{
int v1; // [esp+0h] [ebp-18h]
int v2; // [esp+4h] [ebp-14h]
int v3; // [esp+8h] [ebp-10h]
unsigned int v4; // [esp+Ch] [ebp-Ch]

v4 = __readgsdword(0x14u);
__isoc99_scanf("%x %x %x", &v1, &v2, &v3);
return v1;
}

angr的exp:

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
import angr
import sys
import claripy
def Go():
path_to_binary = "./03_angr_symbolic_registers"
project = angr.Project(path_to_binary, auto_load_libs=False)
start_address = 0x08048980 #跳过get_user_input(),直接修改三个寄存器数据
initial_state = project.factory.blank_state(addr=start_address)

passwd_size_in_bits = 32
passwd0 = claripy.BVS('passwd0', passwd_size_in_bits)
passwd1 = claripy.BVS('passwd1', passwd_size_in_bits)
passwd2 = claripy.BVS('passwd2', passwd_size_in_bits)

initial_state.regs.eax = passwd0
initial_state.regs.ebx = passwd1
initial_state.regs.edx = passwd2

simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
if b'Good Job.\n' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
if b'Try again.\n' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
for i in simulation.found:
solution_state = i
solution0 = format(solution_state.solver.eval(passwd0), 'x')
solution1 = format(solution_state.solver.eval(passwd1), 'x')
solution2 = format(solution_state.solver.eval(passwd2), 'x')
solution = solution0 + " " + solution1 + " " + solution2
print("[+] Success! Solution is: {}".format(solution))
# print(simgr.found[0].posix.dumps(0))
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

五.符号化栈

应用情况就是函数在输入传参的时候是在栈上进行的

如图:img

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __cdecl main(int argc, const char **argv, const char **envp)
{
printf("Enter the password: ");
handle_user();
return 0;
}

int handle_user()
{
int result; // eax
int v1; // [esp+8h] [ebp-10h]
int v2; // [esp+Ch] [ebp-Ch]

__isoc99_scanf("%u %u", &v2, &v1);
v2 = complex_function0(v2);
v1 = complex_function1(v1);
if ( v2 == 1999643857 && v1 == -1136455217 )
result = puts("Good Job.");
else
result = puts("Try again.");
return result;
}

angr的exp:

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
51
import angr
import sys
import claripy
def Go():
path_to_binary = "./04_angr_symbolic_stack"
project = angr.Project(path_to_binary, auto_load_libs=False)
start_address = 0x8048697#还是跳过输入,直接从栈上符号化输入的参数
initial_state = project.factory.blank_state(addr=start_address)

initial_state.regs.ebp = initial_state.regs.esp#初始化,是esp和ebp相同

passwd_size_in_bits = 32
passwd0 = claripy.BVS('passwd0', passwd_size_in_bits)
passwd1 = claripy.BVS('passwd1', passwd_size_in_bits)

padding_length_in_bytes = 0x8#先抬高栈,以便在将符号值压入堆栈之前提供填充,但是栈是从高地址到低地址增长的,所以我们真正需要的是ESP - 0x8
initial_state.regs.esp -= padding_length_in_bytes

initial_state.stack_push(passwd0)
initial_state.stack_push(passwd1)

simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(1)
if b'Good Job.\n' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(1)
if b'Try again.\n' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
for i in simulation.found:
solution_state = i
solution0 = (solution_state.solver.eval(passwd0))
solution1 = (solution_state.solver.eval(passwd1))
print("[+] Success! Solution is: {0} {1}".format(solution0, solution1))
#print(solution0, solution1)
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

六.符号化内存

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+Ch] [ebp-Ch]

memset(user_input, 0, 0x21u);
printf("Enter the password: ");
__isoc99_scanf("%8s %8s %8s %8s", user_input, &unk_A1BA1C8, &unk_A1BA1D0, &unk_A1BA1D8);
for ( i = 0; i <= 31; ++i )
*(_BYTE *)(i + 0xA1BA1C0) = complex_function(*(char *)(i + 0xA1BA1C0), i);// user_input = 0xA1BA1C0
if ( !strncmp(user_input, "NJPURZPCDYEAXCSJZJMPSOMBFDDLHBVN", 0x20u) )// 用来比较s1和s2字符串的前n个字符
puts("Good Job.");
else
puts("Try again.");
return 0;
}

user_input()所处的地址:

img

字符串分别位于以下地址[0xA1BA1C0, 0xA1BA1C8, 0xA1BA1D0, 0xA1BA1D8]

angr的exp:

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
51
52
53
54
55
56
57
import angr
import sys
import claripy
def Go():
path_to_binary = "./05_angr_symbolic_memory"
project = angr.Project(path_to_binary, auto_load_libs=False)
start_address = 0x8048601#跳过输入,直接去内存里符号化四个字符串
initial_state = project.factory.blank_state(addr=start_address)

passwd_size_in_bits = 64
passwd0 = claripy.BVS('passwd0', passwd_size_in_bits)
passwd1 = claripy.BVS('passwd1', passwd_size_in_bits)
passwd2 = claripy.BVS('passwd2', passwd_size_in_bits)
passwd3 = claripy.BVS('passwd3', passwd_size_in_bits)

passwd0_address = 0xA1BA1C0
#passwd1_address = 0xA1BA1C8
#passwd2_address = 0xA1BA1D0
#passwd3_address = 0xA1BA1D8
initial_state.memory.store(passwd0_address, passwd0)
initial_state.memory.store(passwd0_address + 0x8, passwd1)
initial_state.memory.store(passwd0_address + 0x10, passwd2)
initial_state.memory.store(passwd0_address + 0x18, passwd3)

simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(1)
if b'Good Job.\n' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(1)
if b'Try again.\n' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
for i in simulation.found:
solution_state = i
solution0 = solution_state.solver.eval(passwd0,cast_to=bytes)
solution1 = solution_state.solver.eval(passwd1,cast_to=bytes)
solution2 = solution_state.solver.eval(passwd2,cast_to=bytes)
solution3 = solution_state.solver.eval(passwd3,cast_to=bytes)
solution = solution0 + b" " + solution1 + b" " + solution2 + b" " + solution3
print("[+] Success! Solution is: {}".format(solution.decode("utf-8")))
#print(solution0, solution1, solution2, solution3)
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

七.符号化动态内存

程序源码:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // ebx
char *v4; // ebx
int v6; // [esp-10h] [ebp-1Ch]
signed int i; // [esp+0h] [ebp-Ch]

buffer0 = (char *)malloc(9u);
buffer1 = (char *)malloc(9u);
memset(buffer0, 0, 9u);
memset(buffer1, 0, 9u);
printf("Enter the password: ");
__isoc99_scanf("%8s %8s", buffer0, buffer1, v6);
for ( i = 0; i <= 7; ++i )
{
v3 = &buffer0[i];
*v3 = complex_function(buffer0[i], i);
v4 = &buffer1[i];
*v4 = complex_function(buffer1[i], i + 32);
}
if ( !strncmp(buffer0, "UODXLZBI", 8u) && !strncmp(buffer1, "UAORRAYF", 8u) )
puts("Good Job.");
else
puts("Try again.");
free(buffer0);
free(buffer1);
return 0;
}

angr的exp:

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
51
52
53
54
55
import angr
import sys
import claripy
def Go():
path_to_binary = "./06_angr_symbolic_dynamic_memory"
project = angr.Project(path_to_binary, auto_load_libs=False)
start_address = 0x8048699 #跳过malloc和scanf
initial_state = project.factory.blank_state(addr=start_address)

passwd_size_in_bits = 64
passwd0 = claripy.BVS('passwd0', passwd_size_in_bits)
passwd1 = claripy.BVS('passwd1', passwd_size_in_bits)

fake_heap_address0 = 0xffffc93c#假地址
pointer_to_malloc_memory_address0 = 0xabcc8a4#malloc的buffer0地址
fake_heap_address1 = 0xffffc94c#假地址
pointer_to_malloc_memory_address1 = 0xabcc8ac#malloc的buffer1地址
initial_state.memory.store(pointer_to_malloc_memory_address0, fake_heap_address0, endness=project.arch.memory_endness)
initial_state.memory.store(pointer_to_malloc_memory_address1, fake_heap_address1, endness=project.arch.memory_endness)

#这里总的逻辑是这样的,之前是buffer指向的是malloc分配好的内存地址,string存在这里。现在是buffer指向的是我们伪造的地址,符号位向量存在这里

initial_state.memory.store(fake_heap_address0, passwd0)
initial_state.memory.store(fake_heap_address1, passwd1)

simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(1)
if b'Good Job.\n' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(1)
if b'Try again.\n' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
for i in simulation.found:
solution_state = i
solution0 = solution_state.solver.eval(passwd0, cast_to=bytes)
solution1 = solution_state.solver.eval(passwd1, cast_to=bytes)
print("[+] Success! Solution is: {0} {1}".format(solution0.decode('utf-8'), solution1.decode('utf-8')))
#print(solution0, solution1)
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

八.符号化文件内容

程序源码:

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
51
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int i; // [esp+Ch] [ebp-Ch]

memset(buffer, 0, 0x40u);
printf("Enter the password: ");
__isoc99_scanf("%64s", buffer);
ignore_me((int)buffer, 0x40u);
memset(buffer, 0, 0x40u);
fp = fopen("OJKSQYDP.txt", "rb");
fread(buffer, 1u, 0x40u, fp);
fclose(fp);
unlink("OJKSQYDP.txt");
for ( i = 0; i <= 7; ++i )
*(_BYTE *)(i + 0x804A0A0) = complex_function(*(char *)(i + 0x804A0A0), i);
if ( strncmp(buffer, "AQWLCTXB", 9u) )
{
puts("Try again.");
exit(1);
}
puts("Good Job.");
exit(0);
}


unsigned int __cdecl ignore_me(int a1, size_t n)
{
void *v2; // esp
int v4; // [esp+0h] [ebp-28h]
void *ptr; // [esp+Ch] [ebp-1Ch]
size_t v6; // [esp+10h] [ebp-18h]
void *s; // [esp+14h] [ebp-14h]
FILE *stream; // [esp+18h] [ebp-10h]
unsigned int v9; // [esp+1Ch] [ebp-Ch]

ptr = (void *)a1;
v9 = __readgsdword(0x14u);
v6 = n - 1;
v2 = alloca(16 * ((n + 15) / 0x10));
s = &v4;
memset(&v4, 0, n);
unlink("OJKSQYDP.txt");
stream = fopen("OJKSQYDP.txt", "a+b");
fwrite(ptr, 1u, n, stream);
fseek(stream, 0, 0);
__isoc99_fscanf(stream, "%64s", s);
fseek(stream, 0, 0);
fwrite(s, 1u, n, stream);
fclose(stream);
return __readgsdword(0x14u) ^ v9;
}

angr的exp:

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
import angr
import sys
import claripy
def Go():
path_to_binary = "./07_angr_symbolic_file"
project = angr.Project(path_to_binary, auto_load_libs=False)
start_address = 0x80488EA
initial_state = project.factory.blank_state(addr=start_address)

filename = 'OJKSQYDP.txt'
symbolic_file_size_bytes = 64
passwd0 = claripy.BVS('password', symbolic_file_size_bytes * 8)
passwd_file = angr.storage.SimFile(filename, content=passwd0, size=symbolic_file_size_bytes)

initial_state.fs.insert(filename, passwd_file)

simulation = project.factory.simgr(initial_state)

def is_successful(state):
stdout_output = state.posix.dumps(1)
if b'Good Job.\n' in stdout_output:
return True
else:
return False

def should_abort(state):
stdout_output = state.posix.dumps(1)
if b'Try again.\n' in stdout_output:
return True
else:
return False

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
for i in simulation.found:
solution_state = i
solution0 = solution_state.solver.eval(passwd0, cast_to=bytes)
print("[+] Success! Solution is: {0}".format(solution0.decode('utf-8')))
#print(solution0)
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()

九.路径爆炸

程序源码:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
signed int i; // [esp+Ch] [ebp-Ch]

password = 1146115393;
dword_804A044 = 1380994638;
dword_804A048 = 1381647695;
dword_804A04C = 1112233802;
memset(&buffer, 0, 0x11u);
printf("Enter the password: ");
__isoc99_scanf("%16s", &buffer);
for ( i = 0; i <= 15; ++i )
*(_BYTE *)(i + 0x804A050) = complex_function(*(char *)(i + 0x804A050), 15 - i);
if ( check_equals_AUPDNNPROEZRJWKB(&buffer, 16) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

_BOOL4 __cdecl check_equals_AUPDNNPROEZRJWKB(int a1, unsigned int a2)
{
int v3; // [esp+8h] [ebp-8h]
unsigned int i; // [esp+Ch] [ebp-4h]

v3 = 0;
for ( i = 0; i < a2; ++i )
{
if ( *(_BYTE *)(i + a1) == *(_BYTE *)(i + 0x804A040) )
++v3;
}
return v3 == a2;
}

所谓符号执行就是把程序中的变量符号化去模拟程序运行,搜集路径约束条件并使用约束求解器对其进行求解后得到结果。当一个程序存在循环结构时,即使逻辑十分简单也可能会产生规模十分巨大的执行路径。在符号执行的过程中,每个分支点都会产生两个实例,当程序中存在循环结构展开时,可能会导致程序分支路径数呈指数级增长,即路径爆炸问题。故我们需要提供更多的约束条件控制路径爆照问题

angr的exp:

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
import angr
import sys
import claripy
def Go():
path_to_binary = "./08_angr_constraints"
project = angr.Project(path_to_binary, auto_load_libs=False)

start_address = 0x8048625
buff_addr = 0x0804A050
address_to_check_constraint = 0x08048565

initial_state = project.factory.blank_state(addr=start_address)

char_size_in_bits = 8
passwd_len = 16
passwd0 = claripy.BVS('passwd0', char_size_in_bits*passwd_len)
initial_state.memory.store(buff_addr, passwd0)

simulation = project.factory.simgr(initial_state)
simulation.explore(find=address_to_check_constraint)

if simulation.found:
solution_state = simulation.found[0]
constrained_parameter_address = buff_addr
constrained_parameter_size_bytes = 16
constrained_parameter_bitvector = solution_state.memory.load(
constrained_parameter_address,
constrained_parameter_size_bytes
)
constrained_parameter_desired_value = 'AUPDNNPROEZRJWKB'
solution_state.solver.add(constrained_parameter_bitvector == constrained_parameter_desired_value)
solution0 = solution_state.solver.eval(passwd0,cast_to=bytes)
print("[+] Success! Solution is: {0}".format(solution0))
else:
raise Exception('Could not find the solution')

if __name__ == "__main__":
Go()
  • 用户输入的字符串存储在buffer,buffer的地址为:0x804A050
  • 比较函数check_equals_AUPDNNPROEZRJWKB的地址为:0x08048565
  • 其实只要当程序运行到地址0x08048565时,处于buffer地址内的字符串等于AUPDNNPROEZRJWKB即可
  • 添加上述约束条件即可一步得出结果,而不用进入比较函数逐一字符比较而产生路径爆炸问题

十.angr hook

主要就是学习使用angr的hook技术解决路径爆炸问题,与我们之前利用的约束条件不同,hook技术则更为强大