python_angr_模板

本文最后更新于:2023年10月7日 下午

python angr 模块

安装 angr

pip install angr

ipython angr写法模板

image

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
#导入angr 模块
import angr

#新建一个工程
p = angr.Project("./00_angr_find")

#初始化 工程入口状态
init_state = p.factory.entry_state()

#创建符号执行的模拟管理器
sm = p.factory.simulation_manager(init_state)

# 开始符号执行,探索满足条件的执行路径find 查找取得地方 avoid 不去的地方
sm.explore(find=0x08048678)
#sm.explore(find=0x08048678,avoid=0x0804866B)


#获取找到的第一个满足条件的状态
sm.found[0] #可省略

#获取找到的第一个满足条件的状态
found_state = sm.found[0]

# 获取程序的输入数据
found_state.posix.dumps(0)
# 获取程序的输出数据
found_state.posix.dumps(1)

字符串模板

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
init_state = p.factory.entry_state()
sm = p.factory.simulation_manager(init_state)

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)

sm.explore(find=is_good, avoid=is_bad)
if sm.found:
found_state = sm.found[0]
print("Solution: {}".format(found_state.posix.dumps(0)))


if __name__ == '__main__':
main(sys.argv)


03_angr_symbolic_registers 寄存器符号化

起始地址跳过get_user_input的下一个地址

image-20231007164157398

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x80488C7
init_state = p.factory.blank_state(addr=start_addr)
# 在指定地址创建一个初始状态

pass1 = claripy.BVS('pass1', 32)
pass2 = claripy.BVS('pass2', 32)
pass3 = claripy.BVS('pass3', 32)
# 创建三个符号变量

init_state.regs.eax = pass1
init_state.regs.ebx = pass2
init_state.regs.edx = pass3
# 将符号变量赋值给寄存器eax、ebx和edx

sm = p.factory.simulation_manager(init_state)
# 创建一个符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义两个函数,用于判断状态是否为好的或坏的

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,寻找满足is_good条件且避免is_bad条件的路径

if sm.found:
found_state = sm.found[0]

passwd1 = found_state.solver.eval(pass1)
passwd2 = found_state.solver.eval(pass2)
passwd3 = found_state.solver.eval(pass3)
# 获取找到的状态中的符号变量的具体值

print("Solution: {:x} {:x} {:x}".format(passwd1, passwd2, passwd3))
# 打印解决方案

else:
raise Exception('Could not find the solution')
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

04_angr_symbolic_stack 栈符号化

起始地址跳过___isoc99_scanf的下一个地址

add esp, 10h是恢复栈空间平衡

image-20231007164420424

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x80486AE # 地址
init_state = p.factory.blank_state(addr=start_addr)
# 在指定地址创建一个初始状态

padding_size = 8
init_state.stack_push(init_state.regs.ebp)
init_state.regs.ebp = init_state.regs.esp
init_state.regs.esp -= padding_size
# 配置堆栈框架

pass1 = init_state.solver.BVS('pass1', 32)
pass2 = init_state.solver.BVS('pass2', 32)
# 创建两个符号变量

init_state.stack_push(pass1)
init_state.stack_push(pass2)
# 将符号变量放到堆栈上

sm = p.factory.simgr(init_state)
# 创建一个符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义两个函数,用于判断状态是否为好的或坏的

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,寻找满足is_good条件且避免is_bad条件的路径

if sm.found:
found_state = sm.found[0]
passwd1 = found_state.solver.eval(pass1)
passwd2 = found_state.solver.eval(pass2)
# 获取找到的状态中的符号变量的具体值

print("Solution: {:x} {:x}".format(passwd1, passwd2))
# 打印解决方案

else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

05_angr_symbolic_memory 内存符号化

起始地址跳过___isoc99_scanf的下一个地址

add esp, 20h是恢复栈空间平衡
image-20231007164845370

让后程序是__cdecl __cdecl | Microsoft Learn原理

参数传递顺序 | 从右向左。

image-20231007165314484

image-20231007165516873

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
58
59
60
61
62
63
64
65
66
67
import angr
import sys

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x8048618 # 地址
init_state = p.factory.blank_state(addr=start_addr)
# 在指定地址创建一个初始状态

padding_size = 8
init_state.stack_push(init_state.regs.ebp)
init_state.regs.ebp = init_state.regs.esp
init_state.regs.esp -= padding_size
# 配置堆栈框架

p1 = init_state.solver.BVS('p1', 64)
p2 = init_state.solver.BVS('p2', 64)
p3 = init_state.solver.BVS('p3', 64)
p4 = init_state.solver.BVS('p4', 64)
# 创建符号变量

p1_addr = 0xAB232C0
p2_addr = 0xAB232C8
p3_addr = 0xAB232D0
p4_addr = 0xAB232D8
# 参数地址

init_state.memory.store(p1_addr, p1)
init_state.memory.store(p2_addr, p2)
init_state.memory.store(p3_addr, p3)
init_state.memory.store(p4_addr, p4)
# 将符号变量存储到内存中

sm = p.factory.simgr(init_state)
# 创建一个符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义两个函数,用于判断状态是否为好的或坏的

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,寻找满足is_good条件且避免is_bad条件的路径

if sm.found:
found_state = sm.found[0]
passwd1 = found_state.solver.eval(p1, cast_to=bytes)
passwd2 = found_state.solver.eval(p2, cast_to=bytes)
passwd3 = found_state.solver.eval(p3, cast_to=bytes)
passwd4 = found_state.solver.eval(p4, cast_to=bytes)
# 获取找到的状态中的符号变量的具体值

print("Solution: {} {} {} {}".format(passwd1.decode("utf-8"), passwd2.decode("utf-8"), passwd3.decode("utf-8"), passwd4.decode("utf-8")))
# 打印解决方案

else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

06_angr_symbolic_dynamic_memory 动态内存地址

起始地址跳过___isoc99_scanf的下一个地址

add esp, 10h是恢复栈空间平衡

image-20231007165802494

image-20231007165913264

在跳过输入后的angr 查看当前栈地址print("ESP:",init_state.regs.esp)

0x7fff0000

尝试给buffer0偏移+0x100,buffer1+0x200

在将原始的buffer0和buffer1的地址给到程序里面

image-20231007170259012

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
58
59
60
61
import angr
import sys

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x80486AF # 地址
init_state = p.factory.blank_state(addr=start_addr)
# 在指定call scanf后的地址创建一个初始状态

print("ESP:",init_state.regs.esp)#0x7fff0000
buffer0 = 0x7fff0000 - 0x100
buffer1 = 0x7fff0000 - 0x200

buffer0_addr = 0xA2DEF74
buffer1_addr = 0xA2DEF7C

init_state.memory.store(buffer0_addr, buffer0, endness=p.arch.memory_endness)
init_state.memory.store(buffer1_addr, buffer1, endness=p.arch.memory_endness)
# 将buffer0和buffer1的地址存储到指定的地址中

p1 = init_state.solver.BVS('p1', 64)
p2 = init_state.solver.BVS('p2', 64)
# 创建两个64位的符号变量

init_state.memory.store(buffer0, p1)
init_state.memory.store(buffer1, p2)
# 将符号变量存储到buffer0和buffer1的地址中

sm = p.factory.simgr(init_state)
# 创建一个符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义两个函数,用于判断状态是否为好的或坏的

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,寻找满足is_good条件且避免is_bad条件的路径

if sm.found:
found_state = sm.found[0]
passwd1 = found_state.solver.eval(p1, cast_to=bytes).decode("utf-8")
passwd2 = found_state.solver.eval(p2, cast_to=bytes).decode("utf-8")
# 获取找到的状态中的符号变量的具体值

print("Solution: {} {}".format(passwd1, passwd2))
# 打印解决方案

else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)


07_angr_symbolic_file 文件符号化

起始地址跳过输入的下一个地址

add esp, 10h是恢复栈空间平衡

image-20231007170652656

配置打开文件名称和文件大小

image-20231007170529406

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x80488BC # 地址
init_state = p.factory.blank_state(addr=start_addr)
# 在指定call scanf后的地址创建一个初始状态

FileName = "FOQVSBZB.txt"
FileSize = 0x40

passwd = init_state.solver.BVS("passwd",FileSize*8)
sim_file = angr.storage.SimFile(FileName,content=passwd,size = FileSize)
init_state.fs.insert(FileName,sim_file)
# 插入一个符号化文件,将文件名设置为“FOQVSBZB.txt”,文件大小为64字节(0x40)。
# 该文件的内容为一个64位符号变量,名称为passwd。

sm = p.factory.simulation_manager(init_state)
# 创建一个符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义两个函数,用于判断状态是否为好的或坏的

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,寻找满足is_good条件且避免is_bad条件的路径

if sm.found:
found_state = sm.found[0]
passwd1 = found_state.solver.eval(passwd, cast_to=bytes).decode("utf-8")
# 获取找到的状态中的符号变量passwd的具体值

print("Solution: {}".format(passwd1))
# 打印解决方案

else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

08_angr_constraints

直接跳到buffer地址中执行

image-20231007170951294

检查地址

image-20231007171124816

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
# 创建一个angr项目,加载二进制文件

start_addr = 0x0804863C # 地址
init_state = p.factory.blank_state(addr=start_addr)
# 在指定call scanf后的地址创建一个初始状态


buffer_addr = 0x804A040
passwd = init_state.solver.BVS("passwd", 16*8)
init_state.memory.store(buffer_addr, passwd)
# 设置缓冲区地址,并将16字节的符号变量passwd存储到该地址


sm = p.factory.simgr(init_state)
# 创建一个符号执行管理器

check_addr = 0x804857C
sm.explore(find=check_addr)
# 对符号执行管理器进行探索,寻找到达检查地址的路径

if sm.found:
check_state = sm.found[0]

desired_string = "AUPDNNPROEZRJWKB"
check_param1 = buffer_addr
check_param2 = 0x10
# 设置所需字符串、缓冲区地址和长度参数

check_bvs = check_state.memory.load(check_param1, check_param2)
# 加载缓冲区内容

check_constraint = desired_string == check_bvs
check_state.add_constraints(check_constraint)
# 添加约束条件,要求缓冲区内容等于目标字符串

passwd1 = check_state.solver.eval(passwd, cast_to=bytes).decode("utf-8")
# 获取符号变量passwd的具体值

print("Solution: {}".format(passwd1))
# 打印解决方案

else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

09_angr_hooks hook

挂钩子

call地址减去下面的地址就是跳过的长度

image-20231007171524832

这边输入存放的buffer地址

image-20231007171700841

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)

init_state = p.factory.entry_state()
# 创建初始状态

check_addr = 0x80486CA
check_skip_size = 0x5
# 设置检查地址和长度

@p.hook(check_addr, length=check_skip_size)
def check_hook(state):
user_input_addr = 0x804A044
user_input_length = 0x10
# 设置用户输入的地址和长度

user_input_bvs = state.memory.load(user_input_addr, user_input_length)
desired = "OSIWHBXIFOQVSBZB"
# 加载用户输入的内容和目标字符串

state.regs.eax = claripy.If(desired == user_input_bvs,
claripy.BVV(1,32),
claripy.BVV(0,32))
# 根据用户输入内容是否等于目标字符串,设置eax寄存器的值为1或0

def is_good(state):
return b'Good Job' in state.posix.dumps(1)
# 定义一个判断状态是否正确的函数

def is_bad(state):
return b'Try again' in state.posix.dumps(1)
# 定义一个判断状态是否错误的函数

sm = p.factory.simgr(init_state)
# 创建符号执行管理器

sm.explore(find=is_good, avoid=is_bad)
# 对符号执行管理器进行探索,找到满足is_good条件且避免is_bad条件的路径

if sm.found:
check_state = sm.found[0]
print("Solution: {}".format(check_state.posix.dumps(0)))
# 打印解决方案
else:
raise Exception("No Solution found")
# 如果没有找到解决方案,则抛出异常

if __name__ == '__main__':
main(sys.argv)

10_angr_simprocedures hook 函数

好多函数不能像上面上面写只能hook函数名称

check_equals_OSIWHBXIFOQVSBZB

image-20231007172258702

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

import angr
import sys
import claripy

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)

init_state = p.factory.entry_state()

# 定义一个自定义的SimProcedure类来处理符号执行的逻辑
class mySimPro(angr.SimProcedure):
def run(self, user_input_addr, user_input_length):
# 从内存中加载用户输入的内容
angr_bvs = self.state.memory.load(user_input_addr, user_input_length)
desired = "OSIWHBXIFOQVSBZB"

return claripy.If(
desired == angr_bvs,
claripy.BVV(1, 32), # 如果用户输入等于目标字符串,返回1
claripy.BVV(0, 32) # 否则返回0
)

check_symbol = 'check_equals_OSIWHBXIFOQVSBZB'

# 将自定义的SimProcedure与指定的符号关联起来
p.hook_symbol(check_symbol, mySimPro())

sm = p.factory.simgr(init_state)

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)

# 对符号执行管理器进行探索,找到满足is_good条件且避免is_bad条件的路径
sm.explore(find=is_good, avoid=is_bad)

if sm.found:
found_state = sm.found[0]
passwd = found_state.posix.dumps(0)
print("Solution: {}".format(passwd.decode("utf-8")))
else:
raise Exception("No Solution found")

if __name__ == '__main__':
main(sys.argv)

11_angr_sim_scanf scanf hook

image-20231007172515891

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

def main(argv):
# 从命令行参数获取二进制文件的路径
bin_path = argv[1]
p = angr.Project(bin_path)

# 创建初始状态
init_state = p.factory.entry_state()

class mySimPro(angr.SimProcedure):
def run(self, string, scanf0_addr, scanf1_addr):
# 创建两个符号变量用于存储用户输入
scanf0 = claripy.BVS('scanf0', 32)
scanf1 = claripy.BVS('scanf1', 32)

# 将符号变量存储到内存中
self.state.memory.store(scanf0_addr, scanf0, endness=p.arch.memory_endness)
self.state.memory.store(scanf1_addr, scanf1, endness=p.arch.memory_endness)

# 将符号变量保存到全局状态中,以便在后续的路径中可以访问
self.state.globals['passwd0'] = scanf0
self.state.globals['passwd1'] = scanf1

scanf_symbol = '__isoc99_scanf'
# 钩子函数来替换原始的scanf函数
p.hook_symbol(scanf_symbol, mySimPro())

sm = p.factory.simgr(init_state)

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)

# 使用符号执行探索程序路径
sm.explore(find=is_good, avoid=is_bad)

if sm.found:
found_state = sm.found[0]
pwd0 = found_state.globals['passwd0']
pwd1 = found_state.globals['passwd1']

# 获取解决方案
password0 = found_state.solver.eval(pwd0)
password1 = found_state.solver.eval(pwd1)

print("Solution: {} {}".format(password0, password1))
else:
raise Exception("No Solution found")

if __name__ == '__main__':
main(sys.argv)

12_angr_veritesting 优化路径

对比前面增加

之前

sm = p.factory.simgr(init_state)

现在

`` sm = p.factory.simgr(init_state, veritesting=True) `

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
import sys
import claripy

def main(argv):
bin_path = argv[1] # 获取命令行参数中指定的二进制文件路径
p = angr.Project(bin_path) # 创建angr项目对象

init_state = p.factory.entry_state() # 创建初始状态
sm = p.factory.simgr(init_state, veritesting=True) # 创建符号执行管理器

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)

sm.explore(find=is_good, avoid=is_bad) # 开始符号执行过程,指定找到目标状态和要避免的状态

if sm.found: # 如果找到目标状态
found_state = sm.found[0] # 获取找到的状态
print("Solution: {}".format(found_state.posix.dumps(0))) # 打印解(状态的标准输入)
else:
raise Exception("No Solution found")

if __name__ == '__main__':
main(sys.argv)

13_angr_static_binary 静态符号化

把相应的给地址给angr

如call printf 进入printf首地址

image-20231007172927800

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

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)

init_state = p.factory.entry_state()

# 钩住printf、scanf、puts和__libc_start_main函数,以避免其影响我们的符号执行
p.hook(0x804fab0, angr.SIM_PROCEDURES['libc']['printf']())
p.hook(0x804fb10, angr.SIM_PROCEDURES['libc']['scanf']())
p.hook(0x80503f0, angr.SIM_PROCEDURES['libc']['puts']())
p.hook(0x8048d60, angr.SIM_PROCEDURES['glibc']['__libc_start_main']())

sm = p.factory.simgr(init_state, veritesting=True)
# 创建符号执行管理器,启用veritesting

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try again' in state.posix.dumps(1)

sm.explore(find=is_good, avoid=is_bad)

if sm.found:
found_state = sm.found[0]
print("Solution: {}".format(found_state.posix.dumps(0)))
else:
raise Exception("No Solution found")

if __name__ == '__main__':
main(sys.argv)

题目来自GitHub:点击下载angr_ctf题目

我的文件链接:
https://pan.baidu.com/s/1mNExUpxts-NmkaMzVR__Hg?pwd=rshi 提取码: rshi 复制这段内容后打开百度网盘手机App,操作更方便哦

参考b站up主mr_m0nst3r


python_angr_模板
https://huajien.gitee.io/2023/577f7508/
作者
HUAJI
发布于
2023年10月7日
许可协议