基础
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
68
69
70
71
72
| #coding=utf-8
import angr
import networkx as nx
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
proj = angr.Project('/bin/true')
print proj.filename # 文件名
print proj.arch # 一个 archinfo.Arch 对象
print hex(proj.entry) # 入口点
loader = proj.loader
for obj in loader.all_objects: # 程序加载时会将二进制文件和共享库映射到虚拟地址中,所有对象文件
print obj
# 二进制文件本身是main_object
print loader.main_object
print hex(loader.main_object.min_addr)
print hex(loader.main_object.max_addr)
## 但是通常会选择关闭auto_load_libs,避免angr加载共享库
proj = angr.Project('/bin/true', auto_load_libs=False)
print proj.loader.all_objects
# project.factory 提供了很多类对二进制文件进行分析
# project.factory.block() 用于从给定地址解析一个 basic block,对象类型为 Block
block = proj.factory.block(proj.entry)
print block.pp() # 打印
print block.instructions # 指令数量
print block.instruction_addrs # 指令地址
# 将block类型转换为其他形式
print block.capstone.pp()
print block.vex.pp()
# 程序的执行需要初始化一个模拟程序状态的 SimState 对象
state = proj.factory.entry_state()
# 该对象包含了程序的内存、寄存器、文件系统数据等等模拟运行时动态变化的数据
print state.regs # 寄存器
print state.regs.rip # BV64对象
print state.regs.rsp
print state.regs.rsp.length
print state.mem[proj.entry].int.resolved # 将入口点的内存解释为c语言的int类型
# 这里的 BV,即 bitvectors,可以理解为一个比特串,用于在 angr 里表示 CPU 数据。看到在这里 rdi 有点特殊,它没有具体的数值,而是在符号执行中所使用的符号变量
# python int与bitvector之间的转换
bv = state.solver.BVV(0x1234, 32) # 创建一个32位的bitvector对象,值为0x1234
print hex(state.solver.eval(bv))
bv = state.solver.BVV(0x1234, 64) # 64位
# bitvector之间的数学运算
one = state.solver.BVV(1, 64)
one_hundred = state.solver.BVV(2, 64)
print one + one_hundred # 位数相同时可以直接运算
five = state.solver.BVV(5, 27)
print one + five.zero_extend(64 - 27) # 位数不同时需要进行扩展
print one + five.sign_extend(64 - 27) # 有符号扩展
# 使用 bitvectors 可以直接来设置寄存器和内存的值,当传入的是 Python int 时,angr 会自动将其转换成 bitvectors
# >>> state.regs.rsi = state.solver.BVV(3, 64)
# >>> state.regs.rsi
# <BV64 0x3>
# >>> state.mem[0x1000].long = 4 # 在地址 0x1000 存放一个 long 类型的值 4
# >>> state.mem[0x1000].long.resolved # .resolved 获取 bitvectors
# <BV64 0x4>
# >>> state.mem[0x1000].long.concrete # .concrete 获得 Python int
# 4L
# 初始化的 state 可以经过模拟执行得到一系列的 states,模拟管理器(Simulation Managers)的作用就是对这些 states 进行管理
simgr = proj.factory.simulation_manager(state)
print simgr.active # 当前状态
simgr.step() # 模拟执行一个basic block
print simgr.active # 当前状态被更新
print simgr.active[0].regs.rip # active[0] 是当前 state
# attention: 被改变的仅仅是simgr的状态,原始状态并不会被改变
print state.regs.rip
# angr 提供了大量函数用于程序分析,在这些函数在 Project.analyses.
p = angr.Project('/bin/true', load_options={'auto_load_libs': False})
cfg = p.analyses.CFGFast()
nx.draw(cfg.graph) # 画图
plt.savefig('temp.png')
|
00_angr_find
find的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import angr, sys
def main():
filename = "00_angr_find"
proj = angr.Project(filename)
initial_state = proj.factory.entry_state()
simgr = proj.factory.simgr(initial_state)
address = 0x8048675
simgr.explore(find=address)
if simgr.found:
solution = simgr.found[0]
print(solution.posix.dumps(sys.stdin.fileno()))
if __name__ == "__main__":
main()
|
01_angr_avoid
avoid的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import angr, sys
def main():
filename = "01_angr_avoid"
proj = angr.Project(filename)
initial_state = proj.factory.entry_state()
simgr = proj.factory.simgr(initial_state)
address = 0x80485B5
simgr.explore(find=address, avoid=0x80485A8)
if simgr.found:
solution = simgr.found[0]
print(solution.posix.dumps(sys.stdin.fileno()))
if __name__ == "__main__":
main()
|
带参数执行
1
2
3
4
5
6
7
| import angr, claripy
proj = angr.Project('./angr2', auto_load_libs=False)
argv1 = claripy.BVS("argv1", 9 * 8) // 这里用的单位是bit,因此需要乘以8
state = proj.factory.entry_state(args=['./angr2', argv1]) // 导入参数
simgr = proj.factory.simgr(state)
print(simgr.explore(find=0x4007DC, avoid=0x4007EA))
print(simgr.found[0].solver.eval(argv1, cast_to=bytes)) // 直接输出是ascii码,用cast_to=bytes转为bytes类型
|
02_angr_find_condition
find 跟 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
25
26
27
28
| import angr, sys
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno()) # (1)
if b'Good Job.' in stdout_output: # (2)
return True # (3)
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
def main():
filename = "02_angr_find_condition"
proj = angr.Project(filename)
initial_state = proj.factory.entry_state()
simgr = proj.factory.simgr(initial_state)
simgr.explore(find=is_successful, avoid=should_abort)
if simgr.found:
solution = simgr.found[0]
print(solution.posix.dumps(sys.stdin.fileno()))
if __name__ == "__main__":
main()
|
03_angr_symbolic_registers
当调用 scanf()
的时候,angr无法处理复杂的格式。可以将符号值注入寄存器。也可以自己选择开始执行的地址,不一定要从entry开始执行,需要用 blank_state() 方法替代了entry_state()。
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
| #coding=utf-8
import angr, sys, claripy
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno()) # (1)
if b'Good Job.' in stdout_output: # (2)
return True # (3)
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
def main():
filename = "03_angr_symbolic_registers"
proj = angr.Project(filename)
start_address = 0x8048980
initial_state = proj.factory.blank_state(addr=start_address)
# 用 claripy 通过 BVS() 方法生成三个位向量。这个方法需要两个参数:第一个参数表示符号名,第二个参数表示这个符号的长度 单位bit。位数与寄存器的位数相同,是32位
password_size_in_bits = 32
password0 = claripy.BVS('password0', password_size_in_bits)
password1 = claripy.BVS('password1', password_size_in_bits)
password2 = claripy.BVS('password2', password_size_in_bits)
# 更新寄存器的内容
initial_state.regs.eax = password0
initial_state.regs.ebx = password1
initial_state.regs.edx = password2
simgr = proj.factory.simgr(initial_state)
simgr.explore(find=is_successful, avoid=should_abort)
if simgr.found:
solution_state = simgr.found[0]
# 根据注入的三个符号值调用求解引擎的 eval()方法; format() 方法格式化解并去掉16进制的 “0x”。
solution0 = format(solution_state.solver.eval(password0), 'x') # (1)
solution1 = format(solution_state.solver.eval(password1), 'x')
solution2 = format(solution_state.solver.eval(password2), 'x')
solution = solution0 + " " + solution1 + " " + solution2
print("[+] Success! Solution is: {}".format(solution))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
main()
|
04_angr_symbolic_stack
上面一个是变量储存在寄存器上,所以可以直接设置寄存器,这里是变量储存在栈上。针对栈的操作需要注意调整一下栈空间.
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
| #coding=utf-8
import angr, sys, claripy
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno()) # (1)
if b'Good Job.' in stdout_output: # (2)
return True # (3)
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
def main():
filename = "04_angr_symbolic_stack"
proj = angr.Project(filename)
start_address = 0x08048697
initial_state = proj.factory.blank_state(addr=start_address)
initial_state.regs.ebp = initial_state.regs.esp # 模拟mov ebp, esp
# esp减8再push进两个4字节的变量,相当于sub esp, 0x10
padding_length_in_bytes = 8
initial_state.regs.esp -= padding_length_in_bytes
password0 = claripy.BVS('password0', 32)
password1 = claripy.BVS('password1', 32)
# 压栈
initial_state.stack_push(password0)
initial_state.stack_push(password1)
simgr = proj.factory.simgr(initial_state)
simgr.explore(find=is_successful, avoid=should_abort)
if simgr.found:
solution_state = simgr.found[0]
solution0 = format(solution_state.solver.eval(password0), 'x') # (1)
solution1 = format(solution_state.solver.eval(password1), 'x')
solution = solution0 + " " + solution1
print("[+] Success! Solution is: {}".format(solution))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
main()
|
05_angr_symbolic_memory
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
32
33
34
35
36
37
38
| #coding=utf-8
import angr, sys, claripy
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno()) # (1)
if b'Good Job.' in stdout_output: # (2)
return True # (3)
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
def main():
filename = "05_angr_symbolic_memory"
proj = angr.Project(filename)
start_address = 0x80485FE
initial_state = proj.factory.blank_state(addr=start_address)
password = claripy.BVS('password', 256)
user_input_address = 0xA1BA1C0
# 将内容写入内存
initial_state.memory.store(user_input_address, password)
simgr = proj.factory.simgr(initial_state)
simgr.explore(find=is_successful, avoid=should_abort)
if simgr.found:
solution_state = simgr.found[0]
solution = solution_state.solver.eval(password, cast_to=bytes)
print("[+] Success! Solution is: {}".format(solution.decode('utf-8')))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
main()
|
06_angr_symbolic_dynamic_memory
上面05中是把输入的内容直接存储在user_inout处的固定地址上,而这道题中,buffer0和buffer1中存储的是malloc分配内存的地址,这个地址是动态的,地址指向的内容才是真正的输入。所以首先要将输入符号存储在内存中,然后将内存地址写入buffer0和buffer1。
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
| #coding=utf-8
import angr, sys, claripy
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno()) # (1)
if b'Good Job.' in stdout_output: # (2)
return True # (3)
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
def main():
filename = "06_angr_symbolic_dynamic_memory"
proj = angr.Project(filename)
start_address = 0x8048696
initial_state = proj.factory.blank_state(addr=start_address)
password0 = claripy.BVS('password0', 64)
password1 = claripy.BVS('password1', 64)
fake_heap_address0 = 0xffffc93c # (1)
pointer_to_malloc_memory_address0 = 0xabcc8a4 # (2)
fake_heap_address1 = 0xffffc94c # (3)
pointer_to_malloc_memory_address1 = 0xabcc8ac # (4)
# 将buffer0, buffer1中写入虚假的堆地址
initial_state.memory.store(pointer_to_malloc_memory_address0, fake_heap_address0, endness=proj.arch.memory_endness) # (5)
initial_state.memory.store(pointer_to_malloc_memory_address1, fake_heap_address1, endness=proj.arch.memory_endness) # (6)
# 在堆地址中写入输入的符号内容
initial_state.memory.store(fake_heap_address0, password0) # (7)
initial_state.memory.store(fake_heap_address1, password1) # (8)
simgr = proj.factory.simgr(initial_state)
simgr.explore(find=is_successful, avoid=should_abort)
if simgr.found:
solution_state = simgr.found[0]
solution0 = solution_state.solver.eval(password0, cast_to=bytes)
solution1 = solution_state.solver.eval(password1, cast_to=bytes)
solution = solution0 + b" " + solution1
print("[+] Success! Solution is: {}".format(solution.decode('utf-8')))
else:
raise Exception('Could not find the solution')
if __name__ == "__main__":
main()
|
07_angr_symbolic_file
符号化文件中的内容
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
| import angr
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
start_addr = 0x080488D6
init_state = project.factory.blank_state(addr = start_addr)
filename = "OJKSQYDP.txt"
file_size = 0x40
password = init_state.solver.BVS("password", file_size)
# SimFile是构造文件信息,包括文件名,文件内容和文件大小
simgr_file = angr.storage.SimFile(
filename, content=password, size=file_size)
# angr.fs.insert是将文件插入到文件系统中,需要文件名与符号化的文件
init_state.fs.insert(filename, simgr_file)
simgr = project.factory.simgr(init_state)
def is_successful(state):
return b"Good Job." in state.posix.dumps(1)
def should_abort(state):
return b"Try again." in state.posix.dumps(1)
print(simgr.explore(find=is_successful, avoid=should_abort))
if simgr.found:
print(simgr.found[0].solver.eval(password, cast_to=bytes))
else:
raise(Exception("Solution not found."))
if __name__ == "__main__":
main(sys.argv)
|
08_angr_constraints
自己添加约束条件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 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 + 134520912) = complex_function(*(char *)(i + 134520912), 15 - i);
if ( check_equals_AUPDNNPROEZRJWKB((int)&buffer, 0x10u) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}
|
原函数check_equals_AUPDNNPROEZRJWKB
是一个比较简单的函数,但是因为字符一个一个比较会产生路径爆炸问题,所以当执行到这个函数里面时,我们用自己的方法来实现,实现的方法是添加约束add_constraints
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
| import angr
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
start_addr = 0x08048625
init_state = project.factory.blank_state(addr = start_addr)
buff_addr = 0x0804A050
password = init_state.solver.BVS("password", 16 * 8)
init_state.memory.store(buff_addr, password)
simgr = project.factory.simgr(init_state)
check_addr = 0x08048565
# 当找到这个函数时
simgr.explore(find = check_addr)
if simgr.found:
check_state = simgr.found[0]
desired_string = "AUPDNNPROEZRJWKB"
check_param1 = buff_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)
print(check_state.solver.eval(password, cast_to = bytes))
if __name__ == "__main__":
main(sys.argv)
|
也可以直接对check函数进行hook
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 claripy
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
initial_state = project.factory.entry_state()
# call check_equals_AUPDNNPROEZRJWKB处的地址
check_equals_called_address = 0x8048673
instruction_to_skip_length = 5
@project.hook(check_equals_called_address, length=instruction_to_skip_length)
def skip_check_equals_(state):
user_input_buff_address = 0x804a054
user_input_buff_length = 16
user_input_string = state.memory.load(
user_input_buff_address,
user_input_buff_length
)
check_against_string = "XKSPZSJKJYQCQXZV"
# 函数对比的结果保存在eax中返回
state.regs.eax = claripy.If (
user_input_string == check_against_string,
claripy.BVV(1, 32),
claripy.BVV(0, 32)
)
simulation = project.factory.simgr(initial_state)
def is_successful(state):
stdout_output = state.posix.dumps(1)
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(1)
return b"Try again." in stdout_output
simulation.explore(find = is_successful, avoid = should_abort)
if simulation.found:
print(simulation.found[0].posix.dumps(0))
else:
raise(Exception("Could not find the solution"))
if __name__ == "__main__":
main(sys.argv)
|
10_angr_simprocedures
使用函数名进行hook(出现多个地方call func的时候对每个call指令地址进行hook太麻烦,针对有符号的函数)
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
| import angr
import claripy
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
initial_state = project.factory.entry_state()
class mySimPro(angr.SimProcedure):
def run(self, user_input, user_input_length):
angr_bvs = self.state.memory.load (
user_input,
user_input_length
)
check_string = "ORSDDWXHZURJRBDH"
return claripy.If (
check_string == angr_bvs,
claripy.BVV(1, 32),
claripy.BVV(0, 32)
)
check_symbol = "check_equals_ORSDDWXHZURJRBDH"
project.hook_symbol(check_symbol, mySimPro())
simulation = project.factory.simgr(initial_state)
def is_successful(state):
stdout_output = state.posix.dumps(1)
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(1)
return b"Try again." in stdout_output
simulation.explore(find = is_successful, avoid = should_abort)
if simulation.found:
print(simulation.found[0].posix.dumps(0))
else:
raise(Exception("Could not find the solution"))
if __name__ == "__main__":
main(sys.argv)
|
还可以用符号hook 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
46
47
| import angr
import claripy
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
initial_state = project.factory.entry_state()
class ReplacementScanf(angr.SimProcedure):
def run(self, format_string, scanf0_address, scanf1_address):
scanf0 = claripy.BVS('scanf0', 32)
scanf1 = claripy.BVS('scanf1', 32)
self.state.memory.store(scanf0_address, scanf0, endness = project.arch.memory_endness)
self.state.memory.store(scanf1_address, scanf1, endness = project.arch.memory_endness)
self.state.globals['solutions'] = (scanf0, scanf1)
scanf_symbol = "__isoc99_scanf"
project.hook_symbol(scanf_symbol, ReplacementScanf())
simulation = project.factory.simgr(initial_state)
def is_successful(state):
stdout_output = state.posix.dumps(1)
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(1)
return b"Try again." in stdout_output
simulation.explore(find = is_successful, avoid = should_abort)
if simulation.found:
solution_state = simulation.found[0]
stored_solutions = solution_state.globals['solutions']
scanf0_solution = solution_state.solver.eval(stored_solutions[0], cast_to = bytes)
scanf1_solution = solution_state.solver.eval(stored_solutions[1], cast_to = bytes)
print(scanf0_solution, scanf1_solution)
else:
raise(Exception("Could not find the solution"))
if __name__ == "__main__":
main(sys.argv)
|
12_angr_veritesting
学习使用Veritesting的技术解决路径爆炸问题
Python
Veritesting
- 结合静态符号执行和动态符号执行
- 把限制式全部合并到一条路径上
- 减少 path explosion 的影响
project.factory.simgr(initial_state, veritesting=True)
IDA打开,其中这个循环会在二叉决策的时候导致路径爆炸
1
2
3
4
5
6
| for ( i = 0; i <= 31; ++i )
{
v5 = *((char *)s + i + 3);
if ( v5 == complex_function(75, i + 93) )
++v15;
}
|
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
| import angr
import claripy
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state, veritesting = True)
def is_successful(state):
stdout_output = state.posix.dumps(1)
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(1)
return b"Try again." in stdout_output
simulation.explore(find = is_successful, avoid = should_abort)
if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(0))
else:
raise(Exception("Could not find the solution"))
if __name__ == "__main__":
main(sys.argv)
|
13_angr_static_binary
针对静态编译的程序,angr提供了一些常用库函数的实现,eg:
1
2
3
4
5
6
7
8
9
10
11
| # angr.SIM_PROCEDURES['libc']['malloc']
# angr.SIM_PROCEDURES['libc']['fopen']
# angr.SIM_PROCEDURES['libc']['fclose']
# angr.SIM_PROCEDURES['libc']['fwrite']
# angr.SIM_PROCEDURES['libc']['getchar']
# angr.SIM_PROCEDURES['libc']['strncmp']
# angr.SIM_PROCEDURES['libc']['strcmp']
# angr.SIM_PROCEDURES['libc']['scanf']
# angr.SIM_PROCEDURES['libc']['printf']
# angr.SIM_PROCEDURES['libc']['puts']
# angr.SIM_PROCEDURES['libc']['exit']
|
需要找到这些函数进行hook
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
| import angr
import claripy
import sys
def main(argv):
bin_path = argv[1]
project = angr.Project(bin_path)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)
project.hook(0x804ed40, angr.SIM_PROCEDURES['libc']['printf']())
project.hook(0x804ed80, angr.SIM_PROCEDURES['libc']['scanf']())
project.hook(0x804f350, angr.SIM_PROCEDURES['libc']['puts']())
project.hook(0x8048d10, angr.SIM_PROCEDURES['glibc']['__libc_start_main']())
def is_successful(state):
stdout_output = state.posix.dumps(1)
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(1)
return b"Try again." in stdout_output
simulation.explore(find = is_successful, avoid = should_abort)
if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(0))
else:
raise(Exception("Could not find the solution"))
if __name__ == "__main__":
main(sys.argv)
|
参考链接
https://xz.aliyun.com/t/6557
https://lantern.cool/2020/05/15/note-tool-angr/
https://xz.aliyun.com/t/7117
https://github.com/firmianay/CTF-All-In-One/blob/master/doc/5.3.1_angr.md