使用angr的SIM_PROCEDURES进行二进制文件中函数的符号执行
angr是一个符号执行引擎,可以被用于对二进制文件进行符号执行,以自动化地寻找漏洞和安全问题。它通过执行程序的每条指令,跟踪和修改程序状态,并支持使用符号值作为输入和输出,从而创建一个或多个路径来最终到达程序的目标。
为了让angr可以理解特定函数的行为,我们可以使用SIM_PROCEDURES来定义它们的行为。SIM_PROCEDURES是angr中的一个机制,它允许我们为每个特定的函数定义自定义行为。
下面是一个使用SIM_PROCEDURES的例子,我们将定义一个名为my_function的函数,该函数的行为将使程序在argc等于0时返回1,在argc等于1时返回2,在argc等于2时返回3,并在其他情况下返回4。
import angr
def my_function(state):
argc = state.solver.eval(state.regs.rdi) # 获取rdi寄存器的值,即argc参数的值
if argc == 0:
state.regs.rax = 1 # 设置rax寄存器的值为1
elif argc == 1:
state.regs.rax = 2 # 设置rax寄存器的值为2
elif argc == 2:
state.regs.rax = 3 # 设置rax寄存器的值为3
else:
state.regs.rax = 4 # 设置rax寄存器的值为4
proj = angr.Project('./binary', auto_load_libs=False) # 加载二进制文件
cfg = proj.analyses.CFG() # 构建程序的控制流图
# 在控制流图中找到my_function函数的地址
my_function_addr = cfg.kb.functions.function(name='my_function').addr
# 在my_function的地址上定义一个SimProcedure对象
my_function_simprocedure = angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained']()
# 将我们自定义的my_function函数添加到该SimProcedure对象
my_function_simprocedure.procedure = my_function
# 在SIM_PROCEDURES中注册我们的新SimProcedure对象
angr.SIM_PROCEDURES['my_function'] = my_function_simprocedure
# 创建一个初始状态
state = proj.factory.entry_state()
# 生成SimProcedure的调用
state.regs.rip = my_function_addr # 将rip寄存器设置为my_function的地址
state.regs.rdi = 2 # 设置rdi寄存器的值为2,模拟传递参数
# 执行符号执行
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0xaddress_of_success) # 指定成功的目标地址
# 输出符号执行的结果
if simgr.found:
found_state = simgr.found[0]
print("Returned value:", found_state.solver.eval(found_state.regs.rax)) # 获取返回值
else:
print("No feasible path found")
在以上例子中,我们首先定义了一个名为my_function的自定义函数,它使用了angr的符号执行状态对象来获取函数的参数argc的值,并设置函数的返回值rax的值。然后,我们使用SIM_PROCEDURES机制将这个自定义函数和一个SimProcedure对象进行关联,并将SimProcedure对象注册到SIM_PROCEDURES中。
然后,我们使用angr的Project类加载二进制文件,并使用CFG类构建控制流图。通过控制流图,我们找到了my_function函数的地址,并在该地址上定义了我们的SimProcedure对象。
接下来,我们创建了一个初始状态,并在初始状态中设置了函数调用的参数。然后,我们使用simulation_manager来进行符号执行,并指定了一些找到目标的条件。
最后,我们检查符号执行的结果。如果找到了一个可行的路径,我们可以从找到的状态中获取返回值rax的值,并进行输出。
总结来说,通过使用angr的SIM_PROCEDURES机制,我们可以对二进制文件中的函数进行符号执行,并自定义函数的行为。这使得我们能够自动化地分析二进制文件,寻找漏洞和安全问题。
