本文最后更新于:2023年10月7日 下午
python angr 模块
安装 angr
pip install angr
ipython 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
| import angr
p = angr.Project("./00_angr_find")
init_state = p.factory.entry_state()
sm = p.factory.simulation_manager(init_state)
sm.explore(find=0x08048678)
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的下一个地址
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)
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
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]
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
是恢复栈空间平衡
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)
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)
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
是恢复栈空间平衡
让后程序是__cdecl
__cdecl | Microsoft Learn原理
参数传递顺序 | 从右向左。
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)
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)
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
是恢复栈空间平衡
在跳过输入后的angr 查看当前栈地址print("ESP:",init_state.regs.esp)
0x7fff0000
尝试给buffer0偏移+0x100,buffer1+0x200
在将原始的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 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)
start_addr = 0x80486AF init_state = p.factory.blank_state(addr=start_addr)
print("ESP:",init_state.regs.esp) 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)
p1 = init_state.solver.BVS('p1', 64) p2 = init_state.solver.BVS('p2', 64)
init_state.memory.store(buffer0, p1) init_state.memory.store(buffer1, p2)
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] 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
是恢复栈空间平衡
配置打开文件名称和文件大小
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)
start_addr = 0x80488BC init_state = p.factory.blank_state(addr=start_addr)
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)
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] passwd1 = found_state.solver.eval(passwd, cast_to=bytes).decode("utf-8")
print("Solution: {}".format(passwd1))
else: raise Exception("No Solution found")
if __name__ == '__main__': main(sys.argv)
|
08_angr_constraints
直接跳到buffer地址中执行
检查地址
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)
start_addr = 0x0804863C init_state = p.factory.blank_state(addr=start_addr)
buffer_addr = 0x804A040 passwd = init_state.solver.BVS("passwd", 16*8) init_state.memory.store(buffer_addr, 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")
print("Solution: {}".format(passwd1))
else: raise Exception("No Solution found")
if __name__ == '__main__': main(sys.argv)
|
09_angr_hooks hook
挂钩子
call地址减去下面的地址就是跳过的长度
这边输入存放的buffer地址
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))
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)
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
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()
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), claripy.BVV(0, 32) )
check_symbol = 'check_equals_OSIWHBXIFOQVSBZB'
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)
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
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' 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)
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首地址
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()
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)
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