You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在angr中执行指定函数、分析结构体及传递具体参数

2. 符号执行时获取结构体A的执行轨迹

通过将结构体成员设为符号变量,运行符号执行并记录路径与内存变化,可追踪结构体的执行轨迹:

import angr
import claripy

proj = angr.Project('test_fun', auto_load_libs=False)
foo_addr = proj.loader.find_symbol('foo').rebased_addr

# 创建空白状态,将程序计数器指向foo函数地址
state = proj.factory.blank_state(addr=foo_addr)
# 为结构体分配栈内存
struct_addr = state.allocate_stack(8)
# 定义结构体成员的符号变量
data1_sym = claripy.BVS('data1', 32)
data2_sym = claripy.BVS('data2', 32)
# 将符号变量写入内存
state.memory.store(struct_addr, data1_sym, endness=proj.arch.memory_endness)
state.memory.store(struct_addr + 4, data2_sym, endness=proj.arch.memory_endness)
# 设置foo函数的第一个参数(64位架构下为rdi寄存器)为结构体指针
state.regs.rdi = struct_addr

# 创建模拟管理器并运行符号执行
simgr = proj.factory.simgr(state)
simgr.run()

# 遍历所有结束的路径
for path in simgr.deadended:
    # 打印执行的基本块地址轨迹
    print("执行的基本块地址:")
    for bbl_addr in path.history.bbl_addrs:
        print(hex(bbl_addr))
    
    # 获取执行后的结构体成员符号表达式
    final_data1 = path.memory.load(struct_addr, 4, endness=proj.arch.memory_endness)
    final_data2 = path.memory.load(struct_addr + 4, 4, endness=proj.arch.memory_endness)
    
    print(f"执行后data1的符号表达式:{final_data1}")
    print(f"执行后data2的符号表达式:{final_data2}")

执行后会输出foo和bar函数的基本块地址,以及结构体成员的符号表达式data1_sym + 1和data2_sym + 1,清晰展示结构体的变化轨迹。


3. 将结构体a设置为独立内存段并获取执行结果

若希望将结构体放在独立内存段而非栈上,可使用map_region分配自定义内存区域:

import angr
import claripy

proj = angr.Project('test_fun', auto_load_libs=False)
foo_addr = proj.loader.find_symbol('foo').rebased_addr

state = proj.factory.entry_state()
# 分配一个4KB的可读写内存段,起始地址设为0x10000000
seg_addr = 0x10000000
state.memory.map_region(seg_addr, 0x1000, permissions='rw-')
# 结构体放在该内存段的起始位置
struct_addr = seg_addr

# 初始化结构体成员
state.memory.store(struct_addr, state.solver.BVV(5, 32), endness=proj.arch.memory_endness)
state.memory.store(struct_addr + 4, state.solver.BVV(10, 32), endness=proj.arch.memory_endness)

# 调用foo函数
foo_callable = proj.factory.callable(foo_addr, base_state=state)
foo_callable(struct_addr)

# 读取执行后的结构体成员值
data1 = state.memory.load(struct_addr, 4, endness=proj.arch.memory_endness)
data2 = state.memory.load(struct_addr + 4, 4, endness=proj.arch.memory_endness)

print(f"内存段中结构体执行后:data1={state.solver.eval(data1)}, data2={state.solver.eval(data2)}")

执行后会输出内存段中结构体执行后:data1=6, data2=11,验证了自定义内存段中结构体的执行结果。


原代码问题说明

你之前的代码直接将BVS作为参数传递给foo,但foo需要的是指向结构体的指针,而非一个64位符号值。正确做法是先分配内存存储结构体(无论具体值还是符号值),再将该内存的地址作为参数传递。

内容的提问来源于stack exchange,提问作者damaoooo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:45:54