• 最近一些比赛出现了以前没有见过的形式,例如de1ctf 的code_runner 还有最近一次的网鼎杯faster0,感觉这样的题目还挺有意思的,所以花了点时间深入学习了一下。

环境准备

虚拟化环境内安装

  • 首先,安装一些依赖
sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper
  • 在把angr安装,然后放虚拟化环境中(需要注意的是python版本要大于3.6才能进行正常安装,否则会报一堆错)
mkvirtualenv angr && pip install angr
  • 如果这里提示mkvirtualenv未找到命令就用
virtualenv angr && pip install angr
  • 也可以拿docker安装,会省去不必要的环境配置
  • 使用的时候
workon angr 
  • 退出
deactivate

命令介绍

  • 环境准备完之后,就是学一些函数操作了。
  • 这里只介绍一些比较常用的命令,如果还想深入了解的话,请参考官方文档
import angr //导入angr
proj =angr.Project("./路径",auto_load_libs=False) //创建proj,设置不去自动去分析链接库
state=proj.factory.entry_state() //如果需要指定 程序运行地址就用:blank_state(地址)
simgr=proj.factory.simgr(state) 
simgr.explore(find=地址,avoid=地址) //explore find设置要需要执行的到地址,avoid设置避免的地址。avoid可以设为list
simgr.found[0].posix.dumps(0)//打印输入
  • 上面基本可以满足一些普通题目了,更高级一点点的用法
  • 1.需要传入命令行参数的话
import angr //导入angr
import claripy //导入claripy
proj =angr.Project("./路径") //创建proj
arg1=claripy.BVS("arg1",50*8) //创建位向量符号,所以以bit为单位 还有一个是BSS 位向量值
state = p.factory.entry_state(args=['./路径', arg1])
simgr=proj.factory.simgr(state) 
simgr.explore(find=地址,avoid=地址)
fd=simgr.found[0]
fd.solver.eval(arg1,cast_to=str) //打印输入因为是BVS所以需要转
  • 2.好像在旧版angr 不支持多参数输入,在当时想要使用angr就需要对后面参数存入的寄存器和内存地址处直接进行赋值、栈空间进行排布。为了节省时间就把一些必要的省略了。
...
proj =angr.Project("./路径") //创建proj
arg1=claripy.BVS("arg1",8*8)
state = p.factory.entry_state(args=['./路径', arg1])
state.regs.寄存器=arg1
//addr=地址
//state.memory.store(addr,arg1)
//state.memory.store(addr+0x10,arg2) 在addr后0x10存入arg2

//栈
//state.stack_push(arg1)
...
  • 对于一些命令还是很好记的,如果想要更高级的用法,还是得去看文档。

faster0

  • emmm看起来有点吓人,函数有点多。
  • 但是大致就是输入字符然后到达一个栈溢出的地方。这种非入的手工活,怎么能让我们来干呢。所以想到用angr,自动来求解。

exp

  • 贴出Railgun师傅的脚本。
import sys
import angr

#作为最后的答案
answer = ''

#从命令行获取binary
binary = sys.argv[1]

#加载binary
pro = angr.Project(binary)

#指定加载位置,创建一个state,addr即func000
state = pro.factory.blank_state(addr = 0x4008A4)

#以上一句的加载位置创建一个模拟器进行符号执行
sm = pro.factory.simulation_manager(state)

#全局变量
flag_address = 0x6090AC

#创建一个64位的bitvector对象,值为0
flag = state.solver.BVV(0,size = 64)

#将flag存放到flag_address中
state.memory.store(flag_address,flag)

#设置路径查找方式,默认BFS,否则会被Killed
sm.use_technique(angr.exploration_techniques.dfs.DFS())

#指定要执行find(vulun),而不执行aviod(exit)
sm.explore(find = 0x405EF7 , aviod = 0x4006B0)

if sm.found:
    found = sm.found[0]
    result = found.posix.dumps(0)
    for i in result:
        if i in b'0123456789':
            answer += chr(i)
        else:
            answer += '0'

print(answer)