explore
首先介绍下stash,stash用来保存程序的运行路径,形成数组,我们也能通过指令去访问。
>>> proj = angr.Project('/home/fivefiveopen/Desktop/angr/r100' )
>>> state = proj.factory.entry_state()
>>> simgr = proj.factory.simgr()
>>> simgr.active
[<SimState @ 0x400610>]
>>> simgr.step()
<SimulationManager with 1 active>
>>> simgr.active
[<SimState @ 0x4005d0>]
>>> simgr.move(from_stash = 'deadended',to_stash = 'authenticated',filter_func = lambda s:'Nice' in simgr.posix.dump(1))
<SimulationManager with 1 active>//使用move使stash移动,可以通过要求将状态移入某个新的stash的方法来创建一个新的stash
>>> simgr.explore(find = lambda s:'Nice' in s.posix.dumps(1))//explore来找到符合我们要求的stash,比如这个是标准输出出现Nice,当然也能用指定地址的那种
<SimulationManager with 1 found, 10 deadended, 4 active>
>>> simgr.found[0]
<SimState @ 0x40084e>
>>> simgr.found[0].posix.dumps(1)
'Enter the password: Nice!\n'
>>> simgr.found[0].posix.dumps(0)
'Code_Talkers\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\x00'
除了explore这种方法以外还有一些其他的探索方法也能用,比如DFS,深度优先搜索,每次只同时保持一个运行。
断点
同样angr也支持给程序下断点
>>> state.inspect.b("mem_write",when = angr.BP_AFTER,action = angr.BP_IPYTHON)
<BP after-action with conditions {}, no condition func, with action func>
下断点的类型
类型 | 含义 |
---|---|
mem_read | 内存正在被读取 |
mem_write | 内存正在被写 |
reg_read | 寄存器正在被读 |
reg_write | 寄存器正在被写 |
tmp_read | 一个临时值(立即数?)正在被读 |
temp_write | 一个临时值正在被写 |
expr | 一个表达式正在被建立(比如一次数学计算的结果,或者IR中的常量(a constant in the IR)) |
statement | 一个IR statement正在被解释执行(translate) |
instruction | 一个新的(本地native)指令正在被解释执行 |
lrsb | 一个新的基本块正在被解释执行 |
constraints | 一个新的约束正在被加入某个状态中 |
exit | 一个继承状态正由一次执行中产生 |
symbolic_variable | 一个新的符号变量正在被创建 |
call | 一个call指令正在被执行 |
address_concretization | 一个符号化的内存值正在被解析 |
对于不同事件对应的不同的条件
事件类型 | 属性名 | 适用的时机 | 属性含义 |
---|---|---|---|
mem_read | mem_read_address | BP_BEFOR 或 BP_AFTER | 正在被读取的内存的地址 |
mem_read | mem_read_length | BP_BEFOR 或 BP_AFTER | 读取的内存的长度 |
mem_read | mem_read_expr | BP_AFTER | 地址中的表达式 |
mem_write | mem_write_address | BP_BEFOR 或 BP_AFTER | 正在被写入的内存地址 |
mem_write | mem_write_length | BP_BEFOR 或 BP_AFTER | 写入内存的长度 |
mem_write | mem_write_expr | BP_BEFOR 或 BP_AFTER | 写入内存的表达式 |
reg_read | reg_read_offset | BP_BEFOR 或 BP_AFTER | 被读取的寄存器的偏移 |
reg_read | reg_read_length | BP_BEFOR 或 BP_AFTER | 被读取寄存器的值的长度 |
reg_read | reg_read_expr | BP_BEFOR 或 BP_AFTER | 被读取的寄存器中的表达式 |
reg_write | reg_write_length | BP_BEFOR 或 BP_AFTER | 被写入寄存器数据的长度 |
reg_write | reg_write_expr | BP_BEFOR 或 BP_AFTER | 被写入寄存器的表达式 |
tmp_read | tmp_read_num | BP_BEFOR 或 BP_AFTER | 被读入的临时值的长度 |
tmp_read | tmp_read_expr | BP_AFTER | 被读入的临时表达式 |
tmp_write | tmp_write_num | BP_BEFOR 或 BP_AFTER | 被写入临时值的数 |
tmp_write | tmp_write_expr | BP_AFTER | 被写入临时值的表达式 |
expr | expr | BP_AFTER | 表达式的值 |
statement | statement | BP_AFTER 或BP_BEFOR IR | 在其所在的基本块中的索引值(即断在当前基本块中的索引值) |
instruction | instruction | BP_BEFORE 或 BP_AFTER | 本地指令的地址 |
irsb | address | BP_BEFORE 或 BP_AFTER | 基本块地址 |
constraints | added_constraints | BP_BEFORE 或 BP_AFTER | 被加入的约束的列表 |
call | function_address | BP_BEFORE 或 BP_AFTER | 被调用的函数名 |
exit | exit_target | BP_BEFORE 或 BP_AFTER | 代表SimExit的目标的表达式 |
exit | exit_guard | BP_BEFORE 或 BP_AFTER | 代表SimExit的限制的表达式 |
exit | jumpkind | BP_BEFORE 或 BP_AFTER | 代表SimExit的种类的表达式 |
symbolic_variable | symbolic_name | BP_BEFORE 或 BP_AFTER | 正在被创建的符号变量的名字。解析引擎可能改变这个名字(通过在后面添加唯一的ID和长度)。检查symbolic_expr来得到最终的符号表达式 |
symbolic_variable | symbolic_size | BP_BEFORE 或 BP_AFTER | 正在被创建的符号变量的长度 |
symbolic_variable | symbolic_expr | BP_AFTER | 代表新的符号变量的符号表达式 |
address_concretization | address_concretization_strategy | BP_BEFORE 或 BP_AFTER | 被用于解析地址的SimConcretizationStrategy。断点处理函数可以改变将要被应用于解析当前地址的策略。如果你的断点处理函数被置为None,这个策略就会被忽略 |
address_concretization | address_concretization_action | BP_BEFORE 或 BP_AFTER | 用于记录内存操作的SimAction对象 |
address_concretization | address_concretization_memory | BP_BEFORE 或 BP_AFTER | 被操作的SimMemory对象 |
address_concretization | address_concretization_expr | BP_BEFORE 或 BP_AFTER | 代表正在被解析的地址的AST。断点处理函数可以改变这个来影响正在被解析的地址 |
address_concretization | address_concretization_add_constraints | BP_BEFORE 或 BP_AFTER | 约束是否应该别加入到这次读取中 |
address_concretization | address_concretization_result | BP_AFTER | 被解析的地址列表(整型数)。断点处理函数可以覆盖这个来产生不同的解析结果。 |
差不多Angr的基础功能就差不多了,感觉其他的功能也不怎么会用到。可以着手去用Angr搞点好玩的了,实践实践,多运用下。
感谢v1gor大佬的翻译文档