angr安装
python虚拟环境
安装python虚拟环境
pip install virtualenv
pip install virtualenv wrapper
安装完成后,将如下命令写入~/.bashrc(linux)或者~/.bash_profile(OSX)
export WORKON_HOME=your/python/env/path
source /path/to/virtualenvwrapper.sh
创建虚拟环境
mkvirtualenv angr
推出虚拟环境
deactivate
安装angr
可以参考官方文档https://docs.angr.io/introductory-errata/install
在OSX上安装angr需要先安装unicorn
。由于unicorn
依赖python2,安装时需要指定python2路径。在虚拟环境中python是python3。
UNICORN_QEMU_FLAGS="--python=/path/to/python2" pip install unicorn
如果上述命令安装失败,需要使用gcc
编译安装。
xcode-select --install #gcc安装前需要安装
brew install gcc
CC=/usr/local/bin/gcc-8 UNICORN_QEMU_FLAGS="--python=/path/to/python2" pip install unicorn
在OSX中gcc
被clang
占用,gcc
安装完后根据其版本是gcc-8(version)
。
然后安装angr
pip install angr
angr简单使用
创建project
使用Project
创建已经project
import angr
proj = angr.Project('test',auto_load_libs=True)
auto_load_libs
为False时,不会主动加载库文件。
创建完工程后就可以查询该工程的信息。
>>> proj.filename
'test'
>>> proj.arch
<Arch AMD64 (LE)>
>>> hex(proj.entry)
'0x100000f17'
>>> proj.loader
<Loaded test, maps [0x100000000:0x100180000]>
>>> proj.loader.shared_objects
OrderedDict([('test', <MachO Object test, maps [0x100000000:0x100002fff]>), ('extern-address space', <ExternObject Object cle##externs, maps [0x100100000:0x100180000]>)])
>>> proj.loader.aslr
False
>>> proj.loader.main_object.pic
False
>>> proj.loader.main_object.pie
True
>>> proj.loader.main_object.execstack
False >>> proj.factory.block(0x100000f17).pp() #获取block汇编代码
0x100000f17: push rbp
0x100000f18: mov rbp, rsp
0x100000f1b: sub rsp, 0x10
0x100000f1f: lea rax, [rbp - 0xa]
0x100000f23: mov edx, 9
0x100000f28: mov rsi, rax
0x100000f2b: mov edi, 0
0x100000f30: mov eax, 0
0x100000f35: call 0x100000f76 >>> proj.factory.block(0x100000f17).vex.pp() #获取block的vex中间语言
IRSB {
t0:Ity_I64 t1:Ity_I64 t2:Ity_I64 t3:Ity_I64 t4:Ity_I64 t5:Ity_I64 t6:Ity_I64 t7:Ity_I64 t8:Ity_I64 t9:Ity_I64 t10:Ity_I64 t11:Ity_I64 t12:Ity_I64 t13:Ity_I64 t14:Ity_I64 t15:Ity_I64 t16:Ity_I64 t17:Ity_I64 t18:Ity_I64 t19:Ity_I64 t20:Ity_I64
00 | ------ IMark(0x100000f17, 1, 0) ------
01 | t0 = GET:I64(rbp)
02 | t9 = GET:I64(rsp)
03 | t8 = Sub64(t9,0x0000000000000008)
04 | PUT(rsp) = t8
05 | STle(t8) = t0
06 | ------ IMark(0x100000f18, 3, 0) ------
07 | PUT(rbp) = t8
08 | ------ IMark(0x100000f1b, 4, 0) ------
09 | t2 = Sub64(t8,0x0000000000000010)
10 | PUT(cc_op) = 0x0000000000000008
11 | PUT(cc_dep1) = t8
12 | PUT(cc_dep2) = 0x0000000000000010
13 | ------ IMark(0x100000f1f, 4, 0) ------
14 | t11 = Add64(t8,0xfffffffffffffff6)
15 | ------ IMark(0x100000f23, 5, 0) ------
16 | PUT(rdx) = 0x0000000000000009
17 | ------ IMark(0x100000f28, 3, 0) ------
18 | PUT(rsi) = t11
19 | ------ IMark(0x100000f2b, 5, 0) ------
20 | PUT(rdi) = 0x0000000000000000
21 | ------ IMark(0x100000f30, 5, 0) ------
22 | PUT(rax) = 0x0000000000000000
23 | PUT(rip) = 0x0000000100000f35
24 | ------ IMark(0x100000f35, 5, 0) ------
25 | t17 = Sub64(t2,0x0000000000000008)
26 | PUT(rsp) = t17
27 | STle(t17) = 0x0000000100000f3a
28 | t19 = Sub64(t17,0x0000000000000080)
29 | ====== AbiHint(0xt19, 128, 0x0000000100000f76) ======
NEXT: PUT(rip) = 0x0000000100000f76; Ijk_Call
}
SimState状态
SimState通常有三种对象
>>> state = proj.factory.blank_state() #未初始化的状态
>>> state = proj.factory.entry_state() #程序入口地址的状态
>>> state = proj.factory.full_init_state() #类似entry_state,但是调用在执行到达入口点之前应该调用每个初始化函数
可以查询设置寄存器值
>>> state.regs.rip
<BV64 0x100000f17>
>>> state.regs.rip=0x100000f17
在内存中加载值和符号变量
>>> bvv = state.se.BVV('aaa',3*8)
WARNING | 2020-07-06 00:57:37,272 | claripy.ast.bv | BVV value is a unicode string, encoding as utf-8
>>> state.memory.store(state.regs.rsp, bvv)
>>> state.memory.load(state.regs.rsp) #查询内存值
<BV64 0x616161 .. Reverse(mem_7fffffffffefffb_1_40{UNINITIALIZED})>
>>> bvs = state.se.BVS('aaa',3*8) #符号变量
>>> state.memory.store(state.regs.rsp, bvs)
栈操作
>>> state.stack_push('aaaa') #压栈
WARNING | 2020-07-06 01:04:55,238 | angr.storage.memory | Storing unicode string encoded as utf-8. Did you mean to use a bytestring?
>>> state.stack_read(0,4) #查询栈上数据,offset,length
<BV32 0x61616161>
>>> state.stack_pop() #出栈
WARNING | 2020-07-06 01:05:11,855 | angr.state_plugins.symbolic_memory | Filling memory at 0x7fffffffffefff4 with 4 unconstrained bytes referenced from 0x100000f17 (not part of a loaded object)
<BV64 Reverse(0x61616161 .. mem_7fffffffffefff4_2_32{UNINITIALIZED})>
hook
hook任意代码段
>>> @proj.hook(0x100000f35, length=5) #hook的代码地址,以及需要跳过的代码段长度
... def my_read(state):
... a = state.se.BVS('aaaaaaaaaa',10*8)
... state.memory.store(state.regs.rbp-10, a)
hook symbol
>>> class my_read(angr.SimProcedure):
... def run(self,fd,buff,length):
... readin = self.state.se.BVS('aaaaaaaaaa',10*8)
... self.state.memory.store(buff, readin)
>>> proj.hook_symbol('read',my_read)
模拟执行
分析控制流
>>> cfg = proj.analyses.CFG()
>>> cfg = proj.analyses.CFGFast()
>>> cfg.graph.nodes()
NodeView((<CFGNode 0x100000f17[35]>, <CFGNode 0x100000f76[6]>, <CFGNode 0x100000f96[10]>, <CFGNode 0x100000f7c[15]>, <CFGNode 0x100000f3a[8]>, <CFGNode 0x100000f42[8]>, <CFGNode 0x100000f60[12]>, <CFGNode 0x100000f4a[8]>, <CFGNode 0x100000f70[6]>, <CFGNode 0x100000f52[12]>, <CFGNode 0x100000f8c[10]>, <CFGNode 0x100000f5e[2]>, <CFGNode 0x100000f6d[3]>, <CFGNode 0x100000fb0[15]>, <CFGNode 0x100000fd8[40]>, <CFGNode 0x10000101c[198]>, <CFGNode 0x100000f6c[1]>, <CFGNode 0x100000f8b[1]>))
单步执行分析。angr的step
是以block为单位。
>>> ss = state.step()
WARNING | 2020-07-06 01:15:40,913 | angr.state_plugins.symbolic_memory | Filling register rbp with 8 unconstrained bytes referenced from 0x100000f17 (not part of a loaded object)
>>> len(ss.successors) #遇到跳转分支,会有两个
1
>>> ss.successors
[<SimState @ 0x100000f76>]
使用simulation_manager
进行模拟执行。执行结果会有unconstrained
,found
,active
,avoid
等。
>>> simgr = proj.factory.simulation_manager(state) #指定初识状态
>>> simgr.explore()
>>> simgr.explore(find=0x100000f59, avoid=0x100000f67)
使用eval
来求解每个路径的符号值
>>> result = simgr.found[0]
>>> result.se.eval(the_BVS)
简单例子
demo程序
void main(){
char a[10];
read(0,a,9);
if(a[0]==0x30 && a[1]==0x31 && a[2]==0x33)
printf("success\n");
else
printf("fail\n");
}
python脚本
import angr
p = angr.Project('test')
s = p.factory.entry_state()
#p.hook_symbol('read',my_read)
@p.hook(0x100000f35, length=5)
def my_read(state):
a = state.se.BVS('aaaaaaaaaa',10*8)
state.memory.store(state.regs.rbp-10, a)
state.globals['a'] = a
@p.hook(0x100000f59, length=5)
def my_read(state):
print('success')
@p.hook(0x100000f67, length=5)
def my_read(state):
print('failed')
simgr = p.factory.simulation_manager(s)
simgr.explore(find=0x100000f59,avoid=0x100000f67)
result = simgr.found[0]
print(hex(result.se.eval(result.globals['a'])))