angr中SIM_PROCEDURES的高级用法介绍
在angr中,SIM_PROCEDURES是一种特殊的插件,用于处理和执行函数调用。它提供了一个强大的接口,可以用于模拟执行程序中的函数调用,并为我们提供了更多控制程序行为的能力。下面将详细介绍SIM_PROCEDURES的一些高级用法,并提供使用示例。
一、SIM_PROCEDURES的基本用法
在介绍SIM_PROCEDURES的高级用法之前,先来了解一下它的基本用法。
SIM_PROCEDURES允许我们指定一个函数的模拟执行过程,包括参数的传递、函数的执行和返回值的处理等。使用SIM_PROCEDURES时,我们需要定义一个继承自angr类procedure.Procedure的子类,并重写其中的run方法。run方法会在执行函数调用时被调用,并接收一个angr中的SimState对象作为参数。
下面是一个简单的示例,演示了如何使用SIM_PROCEDURES来模拟一个简单的函数调用过程。
import angr
from angr.procedures import SIM_PROCEDURES
class CustomProcedure(angr.procedures.procedure.Procedure):
def run(self, state):
# 获取参数
arg1 = state.solver.eval(state.regs.rdi)
arg2 = state.solver.eval(state.regs.rsi)
# 执行函数操作
result = arg1 + arg2
# 将结果设置为返回值
state.regs.rax = result
p = angr.Project('binary')
state = p.factory.blank_state()
# 使用SIM_PROCEDURES将我们的自定义过程添加到angr的SimProcedures中
p.hook_symbol('add', SIM_PROCEDURES['stubs']['ReturnUnconstrained']())
p.hook_symbol('sub', CustomProcedure())
# 运行程序
simulation = p.factory.simulation_manager(state)
simulation.explore(find=0xdeadbeef)
print(simulation.found[0].registers.rax)
在上面的例子中,我们定义了一个CustomProcedure类,继承自angr的procedure.Procedure类,并重写了其中的run方法。在run方法中,我们首先通过state.solver.eval函数获取了函数调用的参数arg1和arg2,然后执行了一个简单的加法操作,并将结果设置为返回值。
然后,我们使用SIM_PROCEDURES的stubs类型中的ReturnUnconstrained过程来模拟了函数add的执行过程。将add和sub函数的名称与我们定义的过程关联起来,可以通过hook_symbol函数将自定义过程添加到angr的SimProcedures中。
最后,我们创建了一个空的SimState对象,并使用factory模块的simulation_manager函数创建了一个SimulationManager对象。通过调用simulation_manager对象的explore方法,我们可以开始模拟程序的执行过程。在找到目标地址(0xdeadbeef)后,我们打印出了RAX寄存器的值。
这个例子只是一个简单的示例,演示了如何使用SIM_PROCEDURES来模拟函数调用过程。下面,我们将进一步介绍SIM_PROCEDURES的高级用法。
二、SIM_PROCEDURES的高级用法
1. 更多类型的SIM_PROCEDURES
除了上面例子中使用的stubs类型,SIM_PROCEDURES还提供了其他类型,例如Syscalls、Trampolines和SPLs等。这些类型提供了更多的灵活性,可以模拟更多类型的函数调用。我们可以根据需求选择合适的类型,并使用相应的过程来模拟函数调用。
2. 使用SIM_PROCEDURES处理调用表
在实际程序中,经常会使用调用表(即函数指针数组),根据输入的索引值选择对应的函数进行调用。这时,我们可以使用SIM_PROCEDURES来处理调用表的模拟执行过程。
例如,下面的示例展示了如何使用SIM_PROCEDURES处理调用表的情况:
import angr
from angr.procedures import SIM_PROCEDURES
# 定义调用表
call_table = [0xdeadbeef, 0xcafebabe, 0xfeedface]
class CustomProcedure(angr.procedures.procedure.Procedure):
def run(self, state):
# 获取参数
index = state.solver.eval(state.regs.rdi)
# 执行调用表中对应的函数
func_address = call_table[index]
func = angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained']()
state.ip = func_address
state.ret_to = state.regs.rip
state.callstate.set_pushed_return_address(state.history.jumpkind)
p = angr.Project('binary')
state = p.factory.blank_state()
# 使用SIM_PROCEDURES将我们的自定义过程添加到angr的SimProcedures中
p.hook_symbol('call', CustomProcedure())
# 运行程序
simulation = p.factory.simulation_manager(state)
simulation.explore(find=0xdeadbeef)
print(simulation.found[0].registers.rax)
在上面的示例中,我们首先定义了一个call_table列表,其中包含了三个函数的地址。然后,我们定义了一个CustomProcedure类,继承自angr的procedure.Procedure类,并重写了其中的run方法。在run方法中,我们首先通过state.solver.eval函数获取了函数调用的参数index,然后根据index选择相应的函数进行执行。在这里,我们使用了stubs类型中的ReturnUnconstrained过程来模拟函数的执行过程。最后,我们将函数的地址设置为SimState对象的ip寄存器,以实现函数的模拟调用。
使用SIM_PROCEDURES处理调用表时,我们需要通过修改SimState对象的相关属性来实现函数的调用,并将函数的返回地址设置为ret_to属性。这样,当函数执行完毕后,程序会返回到正确的地址。
3. 结合其他插件的使用
SIM_PROCEDURES可以与其他插件一起使用,并发挥更大的作用。例如,我们可以结合使用SimMemory和SimProcedure类来模拟有状态的函数调用过程。
下面的示例演示了如何使用SimProcedure和SimMemory模拟一个有状态的函数调用过程:
import angr
from angr import sim_options
from angr.storage.memory_mixins.paged_memory.pages.multi_memory import NoPageFaultException
from angr.procedures import SIM_PROCEDURES
from angr.storage.memory_mixins.paged_memory.pages.multi_memory import NoPageFaultException
class StatefulProcedure(angr.procedures.SimProcedure):
def run(self, *args, **kwargs):
# 获取参数
arg1 = args[0]
arg2 = args[1]
# 从SimMemory中读取存储在全局变量state中的数据
state = self.state.memory.load(self.state.regs.rbp - 0x8, 4)
# 根据state的值执行不同的操作
if state.concrete:
if state.any() == 1:
result = arg1 + arg2
else:
result = arg1 - arg2
else:
# 当state的值未知时,我们可以进行符号执行
result = self.state.solver.If(state == 1, arg1 + arg2, arg1 - arg2)
# 返回结果
self.state.regs.rax = result
p = angr.Project('binary')
# 将SimProcedure和SIM_PROCEDURES结合使用
p.hook_symbol('add', SIM_PROCEDURES['stubs']['ReturnUnconstrained']())
p.hook_symbol('sub', StatefulProcedure())
state = p.factory.blank_state(add_options={sim_options.STRICT_PAGE_ACCESS})
# 将全局变量state写入SimMemory中
state.memory.store(state.regs.rbp - 0x8, state.solver.BVS('state', 4*8))
simulation = p.factory.simulation_manager(state)
simulation.explore(find=0xdeadbeef)
print(simulation.found[0].registers.rax)
在上面的示例中,我们定义了一个StatefulProcedure类,继承自angr的SimProcedure类,并重写了其中的run方法。在run方法中,
