angr学习【1】

本文介绍了如何在Python虚拟环境中安装angr,并详细阐述了如何创建project、使用SimState、hook代码以及模拟执行。通过示例展示了angr的基本操作,包括设置寄存器值、内存操作和栈管理。此外,还提到了在OSX上安装的特殊注意事项,如指定Python2路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中gccclang占用,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进行模拟执行。执行结果会有unconstrainedfoundactiveavoid等。

>>> 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'])))
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值