由于官方文档中关于数据依赖图(DDG)的说明少之又少,所以这是一篇对angr构造数据依赖图由浅入深的分析博客。下面就开始吧。
DDG的使用案例:
#先加载一个二进制文件,选择符号分析模式
proj = angr.Project(binary_path,load_options={'auto_load_libs': False},default_analysis_mode='symbolic')
#利用CFGAccurate构造一个cfg,记得将选项keep_state设置为True,state添加选项sim_options.refs
cfg = proj.analyses.CFGAccurate(context_sensitivity_level=2, keep_state=True,state_add_options=angr.sim_options.refs)
#传入刚刚构造好的cfg,构造数据依赖图
ddg = proj.analyses.DDG(cfg, start=cfg.functions['main'].addr)
#打印出构造好的DDG的节点数目
print len(ddg.graph)
下面我们从DDG的构造函数开始,梳理DDG的构造过程。
在DDG的构造函数前,有这样一段声明:这是一个快速的数据依赖图,直接由我们的CFG分析结果生成。合理性或准确性是零保证的。仅用于跟踪简单的数据依赖。
可以看出angr DDG的构造是真的很不靠谱哦。但是为了能改进它,也要先了解它的原理。
构造函数的参数很少,所以可定制的地方也不多:
:param cfg: 控制流图,保证每个node都有state,这也是需要打开keep_state选项的原因。
:param start: 一个地址, 指定从哪里开始生成数据依赖图.
:param call_depth: 整数或空. 一个非负整数,代表跟进调用图的深度,空代表无深度限制.
:param iterable or None block_addrs: 一个块地址集合,表示DDG分析的范围.
构造函数的前面都是变量的初始化,然后直接调用了self._construct()函数开始构造。函数执行流程以及在下述代码的注释中,如果真的想了解其中的原理,是一定要结合代码来看的。
def _construct(self):
"""
Construct the data dependence graph.
主要跟踪如下类型的依赖:
- (Intra-IRSB) IRSB内部的临时变量依赖
- 寄存器依赖
- 内存依赖, 尽管它是有限制的
跟踪如下类型的内存访问:
- (函数内) 栈的读写.
跟踪函数内栈的改变, 和栈指针的依赖.
- (函数间) 栈的读写.
- (全局) 静态内存位置.
将所有可访问内存位置映射到它们每个函数的原语句。在那之后,我们遍历CFG并将每一对读取/写入以控制流的顺序链接在一起.
不跟踪如下类型的内存访问
- 符号内存的访问
好吧,它们不能在fastpath模式下被追踪(这是我们生成CTF的模式).
"""
worklist = []
worklist_set = set()
# Initialize the worklist
if self._start is None: #如何没有给出分析的起始点
# 初始化在CFG中入度为0的点
for n in self._cfg.graph.nodes():
if self._cfg.graph.in_degree(n) == 0:
# Put it into the worklist
job = DDGJob(n, 0) #创建job
self._worklist_append(job, worklist, worklist_set)
else: #否则将跟据start获得node,并创建job,加入到worklist中
for n in self._cfg.get_all_nodes(self._start):
job = DDGJob(n, 0)
self._worklist_append(job, worklist, worklist_set)
# A dict storing defs set
# DDGJob -> LiveDefinition
live_defs_per_node = {}
while worklist:
# 从worklist中取出一个节点
ddg_job = worklist[0]
l.debug("Processing %s.", ddg_job)
node, call_depth = ddg_job.cfg_node, ddg_job.call_depth
worklist = worklist[ 1 : ]
worklist_set.remove(node)
# 获取一个节点node所有的final states. 通常超过一个 (一个successors