linux下安装,执行如下
sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
source ~/.bashrc
mkvirtualenv --python=$(which python3) angr && pip install angr
在虚拟环境中安装,可以防止冲突。
题目为00_angr_find
import angr#引入angr p = angr.Project()#建立project init_state = p.factory.entry_state()#告诉angr main函数的位置 sm = p.factory.simulation_manager(init_state)#创建模拟管理器 angr.explore(find = print_good_address)#设立正确地址 found_state = sm.found[0] print(found_state.posix.dumps(1))#打印出正确的地址
先打开ida看
设置正确地址到达Good Job处
根据函数写出我们的脚本
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] print(found_state.posix.dumps(0))
成功打印出数据
在angr.explore语句中除了进行find操作之外我们还可以进行avoid操作,达到减少运算的目的。
ida打开例题,main函数过大无法进行反编译。
我们直接进入maybe_good函数
发现good job,这时候直接写出angr脚本来进行解题就可以了。大致思路同上题
import angr p = angr.Project("01_angr_avoid") init_state = p.factory.entry_state() sm = p.factory.simulation_manager(init_state) sm.explore(find=0x080485E5,avoid=0x080485A8)#正确的地址,外加avoid sm.found[0] found_state = sm.found[0] print(found_state.posix.dumps(0))
但要avoid一个特别复杂的函数,如果不进行avoid操作会导致程序卡死。
成功打印出答案
先根据以上的思路写出脚本
import angr p = angr.Project("01_angr_avoid") init_state = p.factory.entry_state() sm = p.factory.simulation_manager(init_state) sm.explore(find=0x08048718)#正确的地址,外加avoid sm.found[0] found_state = sm.found[0] print(found_state.posix.dumps(0))
可以跑出答案但并不是正确答案。
在ida中查看
发现有很多函数可以输出good job,此时再使用地址作为条件进行搜索非常麻烦,你们我们使用函数输出作为搜索条件。
import angr p = angr.Project("02_angr_find_condition") 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(found_state.posix.dumps(0))
可以跑出正确答案。
要求多个输入,并且将输入存入寄存器中。
当程序要求多个输入的时候angr不能很好的进行符号向量的输入,我们使用手动将符号向量注入寄存器的方法来解决这个问题。
import angr import sys import claripy p = angr.Project("03_angr_symbolic_registers") start_addr = 0x08048980#直接跳过程序本身的输入函数 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] password1 = found_state.solver.eval(pass1) password2 = found_state.solver.eval(pass2) password3 = found_state.solver.eval(pass3) print(password1,password2,password3)#输出可以转16进制
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寄存器之中。
start_addr = 0x08048980#直接跳过程序本身的输入函数 init_state = p.factory.blank_state(addr=start_addr)
跳过了程序本身对寄存器的赋值。
跑出答案
angr更新后解决了多个输入的问题,为此可以将脚本写的更为简便。
import angr p = angr.Project("03_angr_symbolic_registers") 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(found_state.posix.dumps(0))
同样可以跑出答案来。
本题直接使用了栈,于是需要手动布栈。大概流程如下
将esp抬高8位后写出脚本。
import angr import claripy p = angr.Project("04_angr_symbolic_stack") init_state = p.factory.blank_state(addr=0x08048697) init_state.stack_push(init_state.regs.ebp) init_state.regs.ebp = init_state.regs.esp init_state.regs.esp -= 8#手动布栈,进行8位的偏移。 #设置向量 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.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] passwodr1 = found_state.solver.eval(pass1) passwodr2 = found_state.solver.eval(pass2) print(int(passwodr1), int(passwodr2))
可以将flag直接跑出来
当程序将输入存入内存时需要用到内存符号化
可以发现题目将传入的八个字符传到内存之中。写出脚本。
import angr import claripy p = angr.Project("04_angr_symbolic_stack") startAddr = 0x08048697 init_state = p.factory.blank_state(addr=startAddr) init_state.stack_push(init_state.regs.ebp) init_state.regs.ebp = init_state.regs.esp init_state.regs.esp -= 8#手动布栈 #设置向量 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.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] passwodr1 = found_state.solver.eval(pass1) passwodr2 = found_state.solver.eval(pass2) print(int(passwodr1), int(passwodr2))
成功打印出flag。