深入浅出angr(四)
字数 1064 2025-08-06 08:35:35
angr Hook技术深入解析
一、Hook基础概念
在二进制逆向工程中,Hook技术是一种非常重要的方法,它允许我们在程序执行过程中拦截和修改特定函数或指令的行为。angr框架提供了强大的Hook功能,可以将复杂的问题简单化处理。
二、基本Hook方法
1. 地址Hook
通过@proj.hook(address)装饰器可以直接Hook任意地址:
import angr
project = angr.Project("binary", auto_load_libs=False)
@project.hook(0x400844)
def print_flag(state):
print("FLAG SHOULD BE:", state.posix.dumps(0))
project.terminate_execution()
project.execute()
关键点:
project.execute()启动符号执行project.terminate_execution()终止执行- 执行流程:初始化→Hook→execute→遇到terminate_execution结束
2. 符号表Hook
使用hook_symbol函数可以根据符号名Hook对应函数:
p.hook_symbol('ptrace', angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'](return_value=0))
关键点:
angr.SIM_PROCEDURES是angr实现的符号化函数字典- 格式:
angr.SIM_PROCEDURES['模块名']['库函数名']() - 常用于绕过反调试等场景
三、Hook实际应用案例
案例1:绕过反调试(tumctf2016_zwiebel)
# 初始化支持自修改代码的项目
p = angr.Project("zwiebel", support_selfmodifying_code=True)
# Hook ptrace绕过反调试
p.hook_symbol('ptrace', angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'](return_value=0))
# 执行管理
state = p.factory.full_init_state(add_options=angr.options.unicorn)
sm = p.factory.simulation_manager(state)
# 分步执行
while sm.active:
sm.run(n=20)
# 内存优化处理
if 'deadended' in sm.stashes and sm.deadended:
sm.stashes['deadended'] = sm.deadended[-20:]
if sm.errored:
sm.errored = sm.errored[-20:]
flag = sm.deadended[-1].posix.dumps(0).split(b"\n")[0]
案例2:控制输入(defcon2016quals_baby-re)
import angr
import claripy
def main():
proj = angr.Project('./baby-re', auto_load_libs=False)
flag_chars = [claripy.BVS('flag_%d' % i, 32) for i in range(13)]
# 自定义scanf函数
class my_scanf(angr.SimProcedure):
def run(self, fmt, ptr):
self.state.mem[ptr].dword = flag_chars[self.state.globals['scanf_count']]
self.state.globals['scanf_count'] += 1
# Hook标准scanf函数
proj.hook_symbol('__isoc99_scanf', my_scanf(), replace=True)
sm = proj.factory.simulation_manager()
sm.one_active.options.add(angr.options.LAZY_SOLVES)
sm.one_active.globals['scanf_count'] = 0
# 探索执行路径
sm.explore(find=0x4028E9, avoid=0x402941)
# 获取flag
flag = ''.join(chr(sm.one_found.solver.eval(c)) for c in flag_chars)
return flag
关键实现细节:
- 创建符号变量数组
flag_chars - 自定义
my_scanf类继承SimProcedure - 使用
state.mem[ptr].dword存储符号变量 - 使用全局变量
scanf_count跟踪输入位置 replace=True确保完全替换原函数
四、高级Hook技巧
1. 自定义SimProcedure
可以创建自己的SimProcedure类来实现复杂Hook逻辑:
class MyHook(angr.SimProcedure):
def run(self, arg1, arg2):
# 自定义处理逻辑
return self.state.solver.BVV(0, 32)
2. 内存操作Hook
通过Hook内存操作函数可以监控或修改内存访问:
def mem_write(state):
addr = state.inspect.mem_write_address
print(f"Writing to {addr}")
state.inspect.b('mem_write', when=angr.BP_BEFORE, action=mem_write)
3. 寄存器操作Hook
监控或修改寄存器值:
def reg_write(state):
if state.inspect.reg_write_offset == state.arch.registers['rax'][0]:
print("RAX is being written to")
state.inspect.b('reg_write', when=angr.BP_BEFORE, action=reg_write)
五、性能优化建议
- 限制状态数量:在处理大量状态时,只保留最近的状态
sm.stashes['deadended'] = sm.deadended[-20:]
- 使用LAZY_SOLVES:延迟求解约束以提高性能
state = proj.factory.entry_state(add_options={angr.options.LAZY_SOLVES})
- 选择性Hook:只Hook必要的函数,避免不必要的性能开销
六、常见问题解决方案
1. 处理自修改代码(SMC)
proj = angr.Project("binary", support_selfmodifying_code=True)
2. 绕过反调试
# 返回固定值绕过ptrace检测
p.hook_symbol('ptrace', angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'](return_value=0))
3. 处理复杂输入
通过Hook输入函数控制程序输入:
class my_scanf(angr.SimProcedure):
def run(self, fmt, ptr):
self.state.mem[ptr].dword = flag_chars[self.state.globals['count']]
self.state.globals['count'] += 1
七、总结
angr的Hook技术为二进制分析提供了强大而灵活的工具,通过本文介绍的方法,您可以:
- 拦截和修改任意地址或函数的执行
- 自定义输入输出行为
- 绕过各种保护机制
- 监控程序运行时的内存和寄存器变化
掌握这些Hook技术将显著提高您在逆向工程和漏洞分析中的效率和能力。