claripy是一个符号求解引擎,大多数时候,我们只是简单使用claripy,然而当我们做一些核心的符号执行分析时,则不得不深入claripy api,了解其实现细节及处理逻辑,从而进行改进。就我目前对符号执行的理解而言,在使用符号执行解决问题时,首先要提供符号变量,然后提供求解路径,提供求解器,最终求解出结果。那么在angr中如何定义以及初始化这些参数和变量的呢?这是此次源码分析要解决的一个问题。
注:AST 是语法分析树的简写。 se 是符号执行的简写。
还是先列举出claripy的使用案列:
1. claripy作为符号求解引擎单独使用的代码:
import claripy
a = claripy.BVS("sym_val", 32)
b = claripy.RotateLeft(a, 8)
c = b + 4
s = claripy.Solver()
s.add(c == 0x41424344)
assert s.eval(c, 1)[0] == 0x41424344
assert s.eval(a, 1)[0] == 0x40414243
2. claripy在angr中的应用代码:
import angr, claripy
b = angr.Project('/bin/true')
path = b.factory.path() #获得程序的入口状态
rax_start = claripy.BVS('rax_start', 64) #得到一个名为 rax_start的符号变量,长度为64位
path.state.regs.rax = rax_start #将rax_start赋值给入口状态的寄存器
path_new = path.step()[0] #以这个状态执行符号执行
rax_new = path_new.state.regs.rax
path_new.state.se.add(rax_new == 1337) #执行符号执行,结束点为rax_new等于1337时
print path_new.state.se.eval(rax_start, 1)[0]
首先调用的函数为claripy.BVS(),该函数实际存在于claripy.ast.bv.py文件中。它的作用就是创建一个为符号向量(即,一个变量)。
函数参数:
claripy.ast.bv.
BVS
(name, size, min=None, max=None, stride=None, uninitialized=False, explicit_name=None, discrete_set=False, discrete_set_max_card=None, **kwargs)
:param name: 符号的名字.
:param size: 位向量的大小(以位为单位).
:param min: 符号的最小值,仅用于值集分析
:param max: 符号的最大值,仅用于值集分析
:param stride: 符号的stride(步幅),仅用于值集分析
:param uninitialized: 在分析过程中,这个值是否应该被视为一个未初始化的值.
:param bool explicit_name: 如果为False, 则将名称附加标识符以确保唯一性.
:param bool discrete_set: 如果为True, 则将使用DiscreteStridedIntervalSet而不是普通的StridedInterval.
:param int discrete_set_max_card: 离散集合的最大基数。如果discrete_set设置为False或None,则忽略它.
:returns: 代表该符号的BV对象.
另一个创建符号变量的函数为claripy.BVV(),用于创建一个位向量 (即,一个具体值)。
函数参数:
def BVV