Angr初接触
最近在看angr的一些东西,可以说是刚刚入门,想把知道的东西都写下来,方便以后忘了查看一下,这篇博客适合还没入门angr的小白白,如果有奆奆看到这篇博客,欢迎指正。
简介
Angr是一个与平台无关的二进制分析框架,是一套python3的库,做符号执行的。
Angr可以做的事情:
-拆卸和中间表示提升
-程序检测
-符号执行
-控制流分析
-数据依赖性分析
-价值集分析(VSA)
-反编译
平常自己用的时候,大概就是做做简单CTF的逆向题目。
安装
关于angr的安装,Windows、mac、Linux都可以,但是推荐在Linux上使用。我是把它安装在win10的Ubuntu子系统里面的。
Angr以及虚拟环境的安装:
sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper
#安装相应的依赖
mkvirtualenv angr
#创建一个名为angr的虚拟环境,创建完以后会自动进入,进入的标志就是命令行的前面有angr的标志
pip install angr
#到这里就安装完了,打开python命令行,import angr,如果没有报错就安装完成了
这时就已经创建了一个带有python3和angr的虚拟环境,在桌面上已经有一个名为angr的文件夹
这里补充几个基本的虚拟环境的操作
workon angr
#进入名为angr的虚拟环境,或者从别的环境中切换到angr环境中
workon
#列出所有的虚拟环境
source angr/bin/activate
#激活虚拟环境,进入也行
deactivate
#退出虚拟环境
rmvirtualenv
#删除环境
angr操作
现在,angr就已经安装好了,接下来就是angr的使用。
直接拿一个简单的例子开刀。
例子是angr_CTF题00_angr_find。
相关的练习题都在GitHub上,地址为https://github.com/jakespringer/angr_ctf
>>> import angr
>>> P = angr.Project("./00_angr_find")
#加载二进制程序
#这一步加载完了以后就可以查看加载文件的一些属性,例如
>>> P.arch #程序的架构
<Arch X86 (LE)>
>>> P.entry #程序的入口地址
134513744
>>> P.filename #程序名
'./00_angr_find'
#下面是一个接口loader,可以查看二进制文件的共享库以及,资质空间信息等
>>> P.loader
<Loaded 00_angr_find, maps [0x8048000:0xb008000]>
>>> P.loader.shared_objects
OrderedDict([('00_angr_find', <ELF Object 00_angr_find, maps [0x8048000:0x804a03f]>)])
>>> P.loader.min_addr
134512640
>>> P.loader.max_addr
184582144
#还有一个接口是factory
#它的全称是AngrObjectFactory,提供重要分析对象的接口,如blocks/state/SimulationManager等
#Blocks程序基本块,可以给定地址,获取对应的基本块,为Block对象
>>> block = P.factory.block(P.entry)
>>> block
<Block for 0x8048450, 33 bytes>
#还可以通过block.xxx查看很多块信息
#state获取程序的一些状态,例如初始状态,以及一些数据等
>>> state = P.factory.entry_state()
>>> state
<SimState @ 0x8048450>
#上面创建了一个初始状态,默认的状态就是程序的入口地址
#也可以指定一个地址作为入口地址
#指定地址的时候是下面这种形式
#state = p.factory.entry_state(addr=0x<指定的地址>)
#PS:reg和mem没试过
#还可以通过state查看内存/寄存器/文件系统数据等
#state.regs.<寄存器名>
#state.mem[内存地址]
#返回地址是BV向量形式
# 对于state.mem接口
# mem[index] 指定地址
# .<type>指定类(如char,short,int,long,size_t,uint8_t,uint16_t...)
# .resolved 将数据输出为位向量
# .concrete 将数据输出为int值
#Simulation Managers
#Project对象仅仅表示程序的初始镜像,而在执行时,实际上是对Simulation对象进行操作,它代表程序的一个实例镜像,模拟执行某个时刻的状态。
>>> sm = P.factory.simulation_manager(state)
#创建一个模拟器用来模拟程序的执行
>>> sm.step()
#会模拟执行一个基本块
>>> res = sm.explore(find=0x08048678)
#使用explore执行模拟器,find和avoid用来作为约束条件
#res = sm.explore(find=0x<要到达的地址>,avoid=0x<不想去的地方>)
#然后angr会运行,来寻找find指定的地方,结果是一些状态
#比如得到一个状态,那么我们可以使用变量found_state来存储
>>> found_state = res.found[0]
#然后使用下面命令得到,到达find指定位置的输入
>>> found_state.posix.dumps(0)
#指定位置的输出
>>> found_state.posix.dumps(1)
#上述0和1标识标准输入和输出
#Analyses接口
#angr内置了一些分析方法,用于提取程序的信息。接口位于p.analyses中
>>> P.analyses
<angr.analyses.analysis.AnalysesHub object at 0x7fdbeb4db9e8>
上述是我了解到的一些上层的接口,比较简单,下面是得到标准输入的简洁的代码
import angr
P = angr.Project("./00_angr_find")
state = P.factory.entry_state()
sm = P.factory.simulation_manager(state)
res = sm.explore(find=0x08048678)
found_state = res.found[0]
found_state.posix.dumps(0)
补充
res = sm.explore(find=0x08048678)
中0x08048678
的来源。
00_angr_find
题的大意就是输入一个值,然后经过一系列操作,如果正确就输出Good Job.
。这个0x08048678
就是用IDA打开00_angr_find
以后找到的Good Job.
的地址。