Angr-Learn-0x3
注意
本文可以理解为官方文档的简单翻译+一部分个人理解
符号执行与约束求解
angr之所以强大并不因为它是一个模拟器,而是它能使用符号变量来执行。使用符号变量算术运算将产生一颗运算树(AST)。AST可以转换为SMT求解器的约束。
使用位向量
例子:
# 64-bit bitvectors with concrete values 1 and 100
>>> one = state.solver.BVV(1, 64)
>>> one
<BV64 0x1>
>>> one_hundred = state.solver.BVV(100, 64)
>>> one_hundred
<BV64 0x64>
# create a 27-bit bitvector with concrete value 9
>>> weird_nine = state.solver.BVV(9, 27)
>>> weird_nine
<BV27 0x9>
不同长度的位向量可以进行扩展,使得具有适当的位数。
接下来我们来引入符号与位向量是如何使用的:
# Create a bitvector symbol named "x" of length 64 bits
>>> x = state.solver.BVS("x", 64)
>>> x
<BV64 x_9_64>
>>> y = state.solver.BVS("y", 64)
>>> y
<BV64 y_10_64>
可以看到使用了state.solver.BVS
来创建一个64位的符号,我们可以简单理解为是我们数学中学习到的代数中的变量。我们对符号进行算术运算不会得到一个数字,而是得到一个AST
最后,我们要知道angr使用“位向量”一词来指代其最顶层操作生成位向量的任何 AST。还可以通过 AST 表示其他数据类型,包括浮点数以及我们即将看到的布尔值。
符号约束
AST之间的比较是默认比较无符号,而且任何两个相似类型的 AST 之间执行比较操作将产生另一个 AST ,这个AST是一个符号布尔值。
x == 1
<Bool x_9_64 == 0x1>
x == one
<Bool x_9_64 == 0x1>
x > 2
<Bool x_9_64 > 0x2>
x + y == one_hundred + 5
<Bool (x_9_64 + y_10_64) == 0x69>
one_hundred > 5
<Bool True>
one_hundred > -5
<Bool False>
这说明了我们不能直接将符号比较在if、while语句中使用,而是应该通过state.solver.is_true(yes)
这样的语句间接使用。
约束求解
约束求解其实就是单个或多个符号的约束一起计算,获取满足约束的符号的有效值。我们可以通过state.solver.add()
来添加约束。
浮点数运算
-
state.solver.FPS
约束求解有关API
solver.eval(expression)
将为您提供给定表达式的一种可能的解决方案。solver.eval_one(expression)
将为您提供给定表达式的解决方案,或者如果可能有多个解决方案,则抛出错误。solver.eval_upto(expression, n)
将为您提供给定表达式的最多 n 个解决方案,如果可能的数量少于 n,则返回少于 n 的解决方案。solver.eval_atleast(expression, n)
将为您提供给定表达式的 n 个解决方案,如果可能的解决方案少于 n 个,则会抛出错误。solver.eval_exact(expression, n)
将为您提供给定表达式的 n 个解决方案,如果少于或多于可能的解决方案,则会抛出错误。solver.min(expression)
将为您提供给定表达式的最小可能解决方案。solver.max(expression)
将为您提供给定表达式的最大可能解决方案。
此外,所有这些方法都可以采用以下关键字参数:
extra_constraints
可以作为约束元组传递。此评估将考虑这些约束,但不会添加到状态中。cast_to
可以传递一个数据类型来将结果转换为。目前,这只能是int
andbytes
,这将导致该方法返回基础数据的相应表示。例如, 将返回.state.solver.eval(state.solver.BVV(0x41424344, 32), cast_to=bytes)``b'ABCD'