ANGR符号执行
2023-7-9 19:22:0 Author: xz.aliyun.com(查看原文) 阅读量:16 收藏

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=0x080485E5avoid=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。


文章来源: https://xz.aliyun.com/t/12676
如有侵权请联系:admin#unsafe.sh