00_find_angr
从这道题逻辑看非常简单,就一个complex_function加密函数,我们可以选择爆破和逆向,但这里可以选择简单的方式
找到“Good Job”的地址,写代码
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 import sys import angr def main(argv): # 目标文件的路径 path_to_binary = './00_angr_find' # 创建angr项目 project = angr.Project(path_to_binary) # 设置项目起点,entry_state代表程序的入口点,即main函数 initial_state = project.factory.entry_state() # 设置模拟器 sm = project.factory.simgr(initial_state) # 设置目标地址 is_good_addr = 0x08048678 sm.explore(find=is_good_addr) #约束模拟器到达find指定的地址 # 如果到达目标地址,打印此时的符号向量 if sm.found: solution_state = sm.found[0] print(solution_state.posix.dumps(0)) # 否者抛出失败异常 else: raise Exception('Could not find solution')
结果:
01_angr_avoid 当我们找到main函数想F5进去的时候,却反编译不了,然后我们就找到Good Job地址;
写代码:
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 sys import angr def main(argv): # 目标文件的路径 path_to_binary = './01_angr_avoid' # 创建angr项目 project = angr.Project(path_to_binary) # 设置项目起点,enter_state代表程序的入口点,即main函数 initial_state = project.factory.entry_state() # 设置模拟器 sm = project.factory.simgr(initial_state) # 设置目标地址 is_good_addr = 0x080485E0 fail_addr = 0x080485F2 sm.explore(find=is_good_addr, avoid=fail_addr) #avoid避开avoid的地址 # 如果到达目标地址,打印此时的符号向量 if sm.found: solution_state = sm.found[0] print(solution_state.posix.dumps(0)) # 否者抛出失败异常 else: raise Exception('Could not find solution') if __name__ == '__main__': main(sys.argv)
我们新增了一个avoid选项,但是在某些题目中,添加avoid可以有效地防止路径爆炸
02_angr_find_condition 和第一题类似:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import sys import angr def main(argv): bin_path = "./02_angr_find_condition" 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)
find处也可以是函数,可以不写函数地址,写字符串。
03_angr_symbolic_registers
这里输入三个参数,angr没法解出来。
这里看到分别把三个参数给了eax,ebx和edx,我们就可以写如下代码:
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 import claripy def main(argv): bin_path = "./03_angr_symbolic_registers" p = angr.Project(bin_path) start_addr = 0x8048980 init_state = p.factory.blank_state(addr = start_addr) #将eax,ebx,edx符号化为32位的位向量 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] password1 = found_state.solver.eval(pass1) password2 = found_state.solver.eval(pass2) password3 = found_state.solver.eval(pass3) print("Solution:{:x} {:x} {:x}".format(password1,password2,password3)) else: raise Exception("No solution found") if __name__ == '__main__': main(sys.argv)
地址0x8048978处是恢复栈,所以我们从下一个地址开始。
结果:
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 import angr import sys import claripy def main(argv): bin_path = "./04_angr_symbolic_stack" p = angr.Project(bin_path) start_addr = 0x08048697 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] password1 = found_state.solver.eval(pass1) password2 = found_state.solver.eval(pass2) print("Solution:{} {}".format(password1,password2)) else: raise Exception("Solution not found") if __name__ == '__main__': main(sys.argv)
结果:
05_angr_symbolic_memory
我们要将 将内存地址符号化 :
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 import angr import sys import claripy def main(argv): bin_path = "./05_angr_symbolic_memory" p = angr.Project(bin_path) start_addr = 0x08048601 init_state = p.factory.blank_state(addr = start_addr) 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 = 0xA1BA1C0 p2_addr = 0xA1BA1C8 p3_addr = 0xA1BA1D0 p4_addr = 0xA1BA1D8 #内存地址符号化 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] password1 = found_state.solver.eval(p1,cast_to = bytes).decode('utf-8') password2 = found_state.solver.eval(p2,cast_to = bytes).decode('utf-8') password3 = found_state.solver.eval(p3,cast_to = bytes).decode('utf-8') password4 = found_state.solver.eval(p4,cast_to = bytes).decode('utf-8') print("Solution:{} {} {} {}".format(password1,password2,password3,password4)) else: raise Exception("solution not found") if __name__ == '__main__': main(sys.argv)
结果:
06_angr_symbolic_dynamic_memory 这一节关于堆区的内容,程序申请两块内存,把输入存进去
虽然malloc来的空间是动态的,但是存放malloc返回值的变量buffer位于bss段,是静态的,那么我们可以伪造指针,使其指向一片可写内存,将这块内存符号化
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 main(argv): bin_path = "./06_angr_symbolic_dynamic_memory" p = angr.Project(bin_path) start_addr = 0x08048699 init_state = p.factory.blank_state(addr = start_addr) print("ESP:",init_state.regs.esp) #开辟内存 buffer0 = 0x7fff0000-0x100 buffer1 = 0x7fff0000-0x200 buffer0_addr = 0x0ABCC8A4 buffer1_addr = 0x0ABCC8AC #buffer_addr保存着buffer0的地址 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",8*8) p2 = init_state.solver.BVS("p2",8*8) 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] pass1 = found_state.solver.eval(p1,cast_to = bytes).decode('utf-8') pass2 = found_state.solver.eval(p2,cast_to = bytes).decode('utf-8') print("Solution: {} {}".format(pass1,pass2)) else: raise Exception("solution not found") if __name__ == '__main__': main(sys.argv)
endness = p.arch.memory_endness
默认情况angr以大端方式写入数据,该参数以小端写入
结果:
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 38 import angr import sys import claripy def main(argv): bin_path = "./07_angr_symbolic_file" p = angr.Project(bin_path) start_addr = 0x080488D6 init_state = p.factory.blank_state(addr = start_addr) filename = "OJKSQYDP.txt" file_size = 0x40 password = init_state.solver.BVS("password",file_size*8) sim_file = angr.storage.SimFile(filename,content = password,size = file_size) #符号化文件插入 init_state.fs.insert(filename,sim_file) 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] password_str = found_state.solver.eval(password,cast_to = bytes).decode('utf-8') print("Solution:{}".format(password_str)) 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 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 main(argv): bin_path = "./08_angr_constraints" p = angr.Project(bin_path) start_addr = 0x08048625 init_state = p.factory.blank_state(addr = start_addr) buffer_addr = 0x0804A050 password = init_state.solver.BVS("password",16*8) init_state.memory.store(buffer_addr,password) sm = p.factory.simgr(init_state) check_addr = 0x08048565 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) password1 = check_state.solver.eval(password,cast_to = bytes).decode('utf-8') print("Solution:{}".format(password1)) if __name__ == '__main__': main(sys.argv)
结果:
09_angr_hooks
这里把输入加密与password比较,然后再把password加密与输入比较,所以就不能简单的用上题的方法
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 sys import claripy def main(argv): bin_path = "./09_angr_hooks" p = angr.Project(bin_path) init_state = p.factory.entry_state() check_addr = 0x080486B3 check_skip_size = 5 @p.hook(check_addr,length = check_skip_size) def check_hook(state): user_input_addr = 0x804A054 user_input_length = 0x10 user_input_bvs = state.memory.load( user_input_addr, user_input_length ) desired = "XYMKBKUHNIQYNQXE" 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: found_state = sm.found[0] print("Solution:{}".format(found_state.posix.dumps(0))) else: raise Exception("solution not found") if __name__ == '__main__':
结果:
10_angr_simprocedures 这次函数的比较我们需要hook
通过对函数交叉引用我们发现有多处调用这个函数,所以我们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 mport angr import sys import claripy def main(argv): bin_path = "./10_angr_simprocedures" 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 = "ORSDDWXHZURJRBDH" return claripy.If( desired == angr_bvs, claripy.BVV(1,32), claripy.BVV(0,32) ) #以函数名字hook check_symbol = "check_equals_ORSDDWXHZURJRBDH" 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] password = found_state.posix.dumps(0).decode('utf-8') print("Solution:{}".format(password)) else: raise Exception("solution not found") if __name__ == '__main_
结果:
11_angr_sim_scanf
这里我们需要模拟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 48 import sys import angr import claripy def main(argv): binary_path = './11_angr_sim_scanf' p = angr.Project(binary_path) initial_state = p.factory.entry_state() class ReplacementScanf(angr.SimProcedure): def run(self, fmt, scanf0_addr, scanf1_addr): scanf0 = claripy.BVS('scanf0', 4*8) scanf1 = claripy.BVS('scanf1', 4*8) self.state.memory.store(scanf0_addr, scanf0, endness=p.arch.memory_endness) self.state.memory.store(scanf1_addr, scanf1, endness=p.arch.memory_endness) # 将scanf0和scanf1保存到当前状态 self.state.globals['solution0'] = scanf0 self.state.globals['solution1'] = scanf1 scanf_symbol = '__isoc99_scanf' p.hook_symbol(scanf_symbol, ReplacementScanf()) sm = p.factory.simgr(initial_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: solution_state = sm.found[0] #从当前状态取出scanf0和scanf1 solution0 = solution_state.globals['solution0'] solution1 = solution_state.globals['solution1'] solution = '%u %u' % (solution_state.solver.eval(solution0), solution_state.solver.eval(solution1)) print(solution) else: raise Exception('Could not find the solution') if __name__ == '__main__': main(sys.argv)
结果:
12_angr_veritesting 程序输入32个字符,然后加密并在每次加密之后进行比较
如果直接搜索路径,分支太多很浪费时间,所以的想办法简化
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 sys import angr def main(argv): bin_path = './12_angr_veritesting' p = angr.Project(bin_path) initial_state = p.factory.entry_state() sm = p.factory.simgr(initial_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] solution = found_state.posix.dumps(0) print(solution) else: raise Exception('Could not find the solution') if __name__ == '__main__': main(sys.argv)
结果:
13_angr_static_binary 对于静态库函数
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 import angr import sys def main(argv): bin_path = './13_angr_static_binary' p = angr.Project(bin_path) printf_addr = 0x0804ED40 scanf_addr = 0x0804ED80 strcmp_addr = 0x08048280 puts_addr = 0x0804F350 libc_start_main_addr = 0x08048D10 init_state = p.factory.entry_state() sm = p.factory.simgr(init_state, veritesting=True) p.hook(printf_addr,angr.SIM_PROCEDURES['libc']['printf']()) p.hook(scanf_addr,angr.SIM_PROCEDURES['libc']['scanf']()) p.hook(strcmp_addr,angr.SIM_PROCEDURES['libc']['strcmp']()) p.hook(puts_addr,angr.SIM_PROCEDURES['libc']['puts']()) p.hook(libc_start_main_addr,angr.SIM_PROCEDURES['glibc']['__libc_start_main']()) 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("solution not found") if __name__ == '__main__': main(sys.argv)
结果·:
14_angr_shared_library
程序接受输入,然后将输入传递给validate函数处理,validate函数位于共享库中,作用是验证加密后的输入共享库,其实也算一种可执行文件,只是没有经过符号链接,但是在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 import sys import angr import claripy def main(): bin_path = './lib14_angr_shared_library.so' base = 0x400000 # 这个地址随便写 p = angr.Project( bin_path,load_options={'main_opts' : {'custom_base_addr' : base}} ) # 加载共享库 password_addr = claripy.BVV(0x300000, 32) password = claripy.BVS('password', 8 * 8) validate_function_addr = base + 0x6D7 init_state = p.factory.call_state(validate_function_addr, password_addr, 8) # 构造一个指向password的指针传递给函数使用 init_state.memory.store(password_addr, password) sm = p.factory.simgr(init_state) success_addr = base + 0x783 sm.explore(find=success_addr) # 寻找返回指令地址 if sm.found: solution_state = sm.found[0] solution_state.add_constraints(solution_state.regs.eax != 0) # 约束返回 值 solution = solution_state.se.eval(password,cast_to = bytes) print(long_to_bytes(solution).decode()) if __name__ == '__main__': main() ~
结果:
15_angr_arbitrary_read
看似程序不管如何都输出try _again
我们发现输入的v4与s相差16个字节
而good_job与try_again相差四个字节,而输入会有20个字节,所以内存泄漏会导致good_job输出
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 import angr import sys import claripy def main(): bin_path = './15_angr_arbitrary_read' p = angr.Project(bin_path) init_state = p.factory.entry_state() class ReplacementScanf(angr.SimProcedure): # hook scanf函数,符号化输入 def run(self, fmt, number_addr, string_addr): scanf0 = claripy.BVS('scanf0', 4 * 8) scanf1 = claripy.BVS('scanf1', 20 * 8) for char in scanf1.chop(bits=8): self.state.add_constraints(char >= '0', char <= 'z') scanf0_addr = number_addr self.state.memory.store(scanf0_addr, scanf0,endness=p.arch.memory_endness) scanf1_addr = string_addr self.state.memory.store(scanf1_addr, scanf1, endmess=p.arch.memory_endness) self.state.globals['solution0'] = scanf0 self.state.globals['solution1'] = scanf1 scanf_symbol = '__isoc99_scanf' p.hook_symbol(scanf_symbol, ReplacementScanf()) def check_puts(state): # 检查puts的参数是否指向good job puts_parameter = state.memory.load(state.regs.esp + 4, 4, endness=p.arch.memory_endness) # 从栈中取出puts的参数 if state.solver.symbolic(puts_parameter): # 如果参数是符号化的 good_job_string_addr = 0x4D52584B is_vulnerable_expresion = puts_parameter == good_job_string_addr copied_state = state.copy() copied_state.add_constraints(is_vulnerable_expresion) if copied_state.satisfiable(): # 如果参数指向good job state.add_constraints(is_vulnerable_expresion) return True else: return False else: return False sm = p.factory.simgr(init_state) def is_good(state): puts_addr = 0x08048370 if state.addr == puts_addr: # 当程序执行到puts函数时 return check_puts(state) else: return False sm.explore(find=is_good) if sm.found: solution_state = sm.found[0] solution = '%u %s' % (solution_state.solver.eval(solution_state.globals['solution0']), solution_state.solver.eval(solution_state.globals['solution1'],cast_to = bytes).decode()) print(solution) else: raise Exception('Could not find the solution') if __name__ == '__main__': main()
结果:
16_angr_arbitrary_write
password_buffer不等于那一串,但是我们发现输入的s可以溢出到dest对dest修改使其指向password_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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import angr import sys import claripy def main(): bin_path = './16_angr_arbitrary_write' p = angr.Project(bin_path) init_state = p.factory.entry_state() class ReplacementScanf(angr.SimProcedure): # hook scanf函数,符号化key和s def run(self, fmt, number_addr, string_addr): scanf0 = claripy.BVS('scanf0', 4 * 8) scanf1 = claripy.BVS('scanf1', 20 * 8) scanf0_addr = number_addr scanf1_addr = string_addr for char in scanf1.chop(bits=8): self.state.add_constraints(char >= '0', char <= 'z') self.state.memory.store(scanf0_addr, scanf0) self.state.memory.store(scanf1_addr, scanf1) self.state.globals['solution0'] = scanf0 self.state.globals['solution1'] = scanf1 scanf_symbol = '__isoc99_scanf' p.hook_symbol(scanf_symbol, ReplacementScanf()) def check_strncpy(state): # 检查s和dest是否正确 strncpy_src = state.memory.load(state.regs.esp + 8, 4, endness=p.arch.memory_endness) strncpy_des = state.memory.load(state.regs.esp + 4, 4, endness=p.arch.memory_endness) src_contents = state.memory.load(strncpy_src, 8) if state.solver.symbolic(src_contents) and state.solver.symbolic(strncpy_des): password_string = 'NDYNWEUJ' buffer_addr = 0x57584344 dose_src_hold_password = src_contents == password_string dose_dest_equal_buffer_addr = strncpy_des == buffer_addr if state.satisfiable(extra_constraints=(dose_dest_equal_buffer_addr, dose_src_hold_password)): state.add_constraints(dose_src_hold_password, dose_dest_equal_buffer_addr) return True else: return False else: return False sm = p.factory.simgr(init_state) def is_good(state): # 判断是否来到strncpy函数位置 strncpy_addr = 0x08048410 if state.addr == strncpy_addr: return check_strncpy(state) else: return False sm.explore(find=is_good) if sm.found: solution_state = sm.found[0] solution0 = solution_state.globals['solution0'] solution1 = solution_state.globals['solution1'] solution = "%u %s" % (solution_state.solver.eval(solution0), solution_state.solver.eval(solution1,cast_to = bytes).decode()) print(solution) else: raise Exception('Could not find the solution') if __name__ == '__main__': main()
结果:
17_angr_arbitrary_iump 栈溢出漏洞
我们只需要在read_input函数中检查返回地址是否print_good函数的地址即可
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 import angr import claripy def main(): binary_path = './17_angr_arbitrary_jump' project = angr.Project(binary_path) initial_state = project.factory.entry_state() simulation = project.factory.simgr( initial_state, save_unconstrained=True, stashes={ 'active' : [initial_state], 'unconstrained' : [], 'found' : [], 'not_needed' : [] } ) class ReplacementScanf(angr.SimProcedure): def run(self, fmt, string_addr): exploit = claripy.BVS('exploit', 8*64) for char in exploit.chop(bits=8): self.state.add_constraints(char >= '0', char <= 'z') exploit_addr = string_addr self.state.memory.store(exploit_addr, exploit) self.state.globals['solution'] = exploit scanf_symbol = '__isoc99_scanf' project.hook_symbol(scanf_symbol, ReplacementScanf()) while (simulation.active or simulation.unconstrained) and (not simulation.found): for unconstrained_state in simulation.unconstrained: def should_move(s): return s is unconstrained_state simulation.move('unconstrained', 'found', filter_func=should_move) simulation.step() if simulation.found: solution_state = simulation.found[0] solution_state.add_constraints(solution_state.regs.eip == 0x42585249) solution = solution_state.se.eval(solution_state.globals['solution'],cast_to = bytes) print(solution) else: raise Exception('Could not find the solution') if __name__ == '__main__': main()
结果: