angr学习(三)
loader
查看模拟的内存空间,获取入口点、内存边界、模拟寄存器、地址偏移、重定位。。。
查看加载的模块信息(主程序、共享库、无法解析的库)
解析符号,通过符号查找对应内存地址,符号判断其导出或导入来确定所在模块,获取模块的导入信息
加载选项: 可选择是否加载相应共享库
指定加载程序所需反编译模块
符号化函数 在SimProcedures中实现了大量的符号化函数,Project会尝试用符号化函数代替程序中对库函数的外部调用。通过angr.SIM_PROCEDURES字典调用,模块名+库函数名双重映射。
hook:通过对指定地址设置hook使其执行指定函数,可以是符号化函数,或自定义函数。
Solver Engine
符号表示、约束求解
符号表示
BV:bitvector
构造符号值或具体值的一个比特容器,它具有大小。
例子:
- 建立一个32bit的符号值容器 "x":
claripy.BVS('x',32)
- 建立一个32bit的具体值(0xc001b3475)容器:
claripy.BVV(0xc001b3a75,32)
- 建立一个32bit的步进值,从1000到2000能被10整除的数:
claripy.SI(name='x',bits=32,lower_bound=1000,upper_bound=2000,stride=10)
BitvectorValues
这些值并不是简单数值(不可以直接参与算术运算),它是一个bit序列,可以用有界整数(可以直接参与算术运算)来解释。
# 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> >>> one + one_hundred <BV64 0x65> # You can provide normal python integers and they will be coerced to the appropriate type: >>> one_hundred + 0x100 <BV64 0x164> # The semantics of normal wrapping arithmetic apply >>> one_hundred - one*200 <BV64 0xffffffffffffff9c>
如果两个bitvector的长度不同是不能共同运算的,需要将其扩展:
>>> weird_nine.zero_extend(64 - 27) <BV64 0x9> >>> one + weird_nine.zero_extend(64 - 27) <BV64 0xa>
BitvectorSymbols
# 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> >>> x + one <BV64 x_9_64 + 0x1> >>> (x + one) / 2 <BV64 (x_9_64 + 0x1) / 0x2> >>> x - y <BV64 x_9_64 - y_10_64>
符号bit序列运算结果不是bit序列,而是一个抽象语法树(AST),由.op
和.args
组成,即操作符和操作数。
>>> tree = (x + 1) / (y + 2) >>> tree <BV64 (x_9_64 + 0x1) / (y_10_64 + 0x2)> >>> tree.op '__div__' >>> tree.args (<BV64 x_9_64 + 0x1>, <BV64 y_10_64 + 0x2>) >>> tree.args[0].op '__add__' >>> tree.args[0].args (<BV64 x_9_64>, <BV64 0x1>) >>> tree.args[0].args[1].op 'BVV' >>> tree.args[0].args[1].args (1, 64)
符号约束
当两个AST进行比较时会产生另一个AST,以符号化boolean为结果的AST。
约束求解
>>> state.solver.add(x > y) >>> state.solver.add(y > 2) >>> state.solver.add(10 > x) >>> state.solver.eval(x) 4
通过向求解器中加入约束条件(实际为一个个AST),最后求解器会得到一个满足该约束树的最大/小值。