angr学习笔记

参考链接:https://blog.csdn.net/A951860555/article/details/119102789

题目链接:https://github.com/jakespringer/angr_ctf

angr安装:https://www.anquanke.com/post/id/212816


 angr是一个二进制分析平台,目的是找程序路径。本学习笔记通过做题(angr_findangr_avoidangr_find_condition)来学习angr。

0x00 angr_find

 32位程序。程序如下:

image-20230417105504090

 Angr脚本如下:

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
import angr


# Create a Pro --> Create a simu --> Explore
pro = angr.Project("./00_angr_find")

init_state = pro.factory.entry_state() # start() addr
simu = pro.factory.simgr(init_state)

good_addr = 0x804868f
simu.explore(find=good_addr)

# get res
if simu.found:
res = simu.found[0]
for i in range(3):
# print stdin/stdout/stderr, stdin is flag
print(res.posix.dumps(i))
else:
print("No result!")


# 最后三行输出依次是stdin/stdout/stderr的值
# stdin代表输入的passwd即flag
# stdout是程序运行的输出
# 程序没有运行出错,所以stderr没有输出。

# output:
# b'IICLTGRK'
# b'Enter the password: '
# b''

0x01 angr_avoid

 发现由于main函数过大,而无法反编译。而maybe_good函数如下:

image-20230417114414306

 因此,只要should_succeed==1s1==s2即可。而且要避免进入avoid_me函数中,此函数会将should_succeed设置为0。(不加入avoid也是可以求解的,不过会使用更多的时间。)

 Angr脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import angr

pro = angr.Project("./01_angr_avoid")

init_state = pro.factory.entry_state()
simu = pro.factory.simgr(init_state)

good_addr = 0x080485F7
avoid_addr = 0x080485BF # avoid_me func
simu.explore(find=good_addr, avoid=avoid_addr)

if simu.found:
res = simu.found[0]
for i in range(3):
print(res.posix.dumps(i))
else:
print("No result!")
"""
b'JLVUSGJZ'
b'Enter the password: '
b''
"""

0x02 angr_find_condition

 程序逻辑如下:

image-20230417115017544

 这道题的目的主要是学习另外一种条件判断的方法,前面的题目指定是地址,这里也可以指定为一个条件函数。

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
import angr

pro = angr.Project("./02_angr_find_condition")

init_state = pro.factory.entry_state()
simu = pro.factory.simgr(init_state)

def success(state):
output = state.posix.dumps(1) # get output from stdout
return b"Good Job." in output

def abort(state):
output = state.posix.dumps(1) # get output from stdout
return b"Try again." in output

simu.explore(find=success, avoid=abort)
if simu.found:
res = simu.found[0]
for i in range(3):
print(res.posix.dumps(i))
else:
print("No result!")
"""
b'OHYJUMBE'
b'Enter the password: Good Job.\n'
b''
"""

0x03 angr_symbolic_registers

 反汇编代码如下:

image-20230417135812157

 这道题最主要的区别在于scanf读取了三个参数,以前的angr版本不支持scanf获取多个参数,所以会采用设置寄存器求解的方法,如下脚本所示:

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 claripy


pro = angr.Project("./03_angr_symbolic_registers")

start_addr = 0x080488c7
init_state = pro.factory.blank_state(addr=start_addr) # blank_state, not entry_state

# create three vars
size_in_bits = 32
passwd0 = claripy.BVS("passwd0", size_in_bits)
passwd1 = claripy.BVS("passwd1", size_in_bits)
passwd2 = claripy.BVS("passwd2", size_in_bits)

# scanf --> eax/ebx/edx
init_state.regs.eax = passwd0
init_state.regs.ebx = passwd1
init_state.regs.edx = passwd2

simu = pro.factory.simgr(init_state)

def success(state):
output = state.posix.dumps(1)
return b"Good Job." in output

def abort(state):
output = state.posix.dumps(1)
return b"Try again." in output

simu.explore(find=success, avoid=abort)

if simu.found:
res = simu.found[0]
solu0 = res.solver.eval(passwd0) # you can also use init_state.regs.eax replace passwd0
solu1 = res.solver.eval(passwd1)
solu2 = res.solver.eval(passwd2)

solu = " ".join(map("{:x}".format, [solu0, solu1, solu2]))
print(solu)
else:
print("No result!")
"""
db01abf7 4930dc79 d17de5ce
"""

留言

2023-04-17

© 2024 wd-z711

⬆︎TOP