ANGR符号执行
ANGR符号执行 angr库的安装 linux下安装,执行如下 sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper export WORKON_HOME=$HOME/.virtualenvs source /usr/share/virtualenvwrapper/virtualenvwrapper
ANGR符号执行
angr库的安装
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))#打印出正确的地址
00_angr_find:
先打开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 avoid
在angr.explore语句中除了进行find操作之外我们还可以进行avoid操作,达到减少运算的目的。
01_angr_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操作会导致程序卡死。

成功打印出答案

根据函数的输出条件搜索正确输入
02_angr_find_condition
先根据以上的思路写出脚本
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))

可以跑出正确答案。
多个输入寄存器
03_angr_symbolic_registers

要求多个输入,并且将输入存入寄存器中。
当程序要求多个输入的时候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))
同样可以跑出答案来。

将符号向量存入栈内与手动布栈
04_angr_symbolic_stack

本题直接使用了栈,于是需要手动布栈。大概流程如下

将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直接跑出来

内存符号化
05_angr_symbolic_memory
当程序将输入存入内存时需要用到内存符号化

可以发现题目将传入的八个字符传到内存之中。写出脚本。
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。