trapfuzzer 源码分析
字数 2064 2025-08-09 15:23:13

TrapFuzzer 源码分析与使用指南

概述

TrapFuzzer 是一款基于断点技术获取程序覆盖率的模糊测试工具,与 AFL 等传统 Fuzz 工具相比具有以下特点:

优点

  • 对程序性能影响较小
  • 支持单模块插桩
  • 平台要求低(仅需支持软件断点)
  • 无需深入分析目标程序的数据处理函数

缺点

  • 覆盖率记录粒度较粗(基本块级别)

基本原理

TrapFuzzer 的核心工作原理:

  1. 预处理阶段

    • 使用 IDA 将目标模块所有基本块的第一条指令替换为断点指令(x86 下为 \xcc
    • 保存原始指令的位置、大小和内容到文件中
  2. Fuzz 阶段

    • 当程序执行到新基本块时触发断点
    • 记录执行到的基本块地址
    • 恢复原始指令让程序继续执行
    • 通过这种方式收集程序执行路径

可选配置

  • 是否在每次测试后恢复二进制文件中的断点指令(patch_to_binary 选项)
    • 开启:提升速度(每个断点只命中一次),但只能记录新发现的基本块
    • 关闭:完整记录所有执行路径,但速度较慢

核心模块分析

1. Tracer 模块

负责获取进程执行过程中的覆盖率,支持两种实现方式:

1.1 Python-ptrace 实现

关键函数 trace() 流程:

  1. 创建并附加到目标进程
  2. 循环等待进程信号
  3. 当捕获 SIGTRAP 信号时:
    • 获取指令指针
    • 计算断点地址偏移
    • 恢复原始指令
    • 记录基本块地址

1.2 GDB Python 插件实现

关键组件:

  • gdbtracer.py:主控制脚本
  • trap.py:GDB 插件脚本
  • cmd.gdb:GDB 初始化脚本

工作流程:

  1. 通过 subprocess 启动 GDB 加载目标程序
  2. 注册 GDB 事件处理器(stop_handler
  3. 当触发断点时:
    • 通过 socket 通信获取原始指令
    • 恢复指令并继续执行
    • 记录基本块地址

2. 数据变异模块

支持三种变异器:

2.1 RadamsaMutator

  • 直接调用 radamsa 命令行工具进行变异
  • 简单但依赖外部工具

2.2 VanapaganMutator

  • 包含两种变异策略:
    • FileBitFlipping:比特翻转
    • FileByteValues:特殊字节替换

2.3 HonggfuzzMutater

  • 将 honggfuzz 的变异器用 Python 重写
  • 提供更丰富的变异策略

3. Fuzz 调度模块

3.1 测试用例加载 (load_testcase)

  • 从指定目录加载初始测试用例
  • 只保存产生新路径的用例
  • 计算样本平均执行时间(用于 DOS 检测)

3.2 用例集精简 (minimize)

  1. 为所有用例生成覆盖率信息
  2. 选择覆盖率最大的用例加入精简集
  3. 剔除冗余用例(覆盖率已被包含的)
  4. 重复直到没有新用例

3.3 主循环 (fuzz)

  1. 加载初始用例(或恢复之前状态)
  2. 随机选择变异器
  3. 遍历样本队列:
    • 变异当前样本
    • 执行并获取覆盖率
    • 处理结果:
      • 新路径:加入队列
      • DOS/崩溃:特殊处理
  4. 持续循环

3.4 样本打分策略 (Testcase 类)

  • 初始执行次数:50
  • 发现新路径:增加 10% 执行次数
  • 导致 DOS:减少 10% 执行次数

使用指南

1. 准备工作

  1. 使用 IDA 分析目标程序
  2. 运行 dump_bb.py 导出基本块信息到 bb.txt
  3. 运行 setbp.py 修改二进制文件(替换为断点指令)

2. 配置文件 (config.json)

{
    "tracer": "gdb",
    "mutator": "radamsa-mutator",
    "args": ["/path/to/target", "/input/file"],
    "basic_block_file_path": ["/path/to/bb.txt"],
    "coverage_module_name": ["target_module"],
    "file_read_by_target": "/input/file",
    "manage_port": "8821",
    "exit_basci_block_list": "0xCF3",
    "output": "/output/dir/",
    "testcase": "/initial/testcases/",
    "patch_to_binary": true,
    "resume_execution": false
}

关键配置项说明

配置项 说明
tracer 覆盖率获取方式:gdb, python-ptrace, gdb-run
mutator 变异器:Vanapagan-mutator, radamsa-mutator, honggfuzz-mutator
basic_block_file_path 基本块信息文件路径
coverage_module_name 要收集覆盖率的模块名
patch_to_binary 是否恢复二进制中的断点指令(影响速度/完整性)
exit_basci_block_list 触发退出的基本块地址(多个用逗号分隔)

3. 运行流程

  1. 准备目标程序(已插桩)
  2. 准备初始测试用例
  3. 配置 config.json
  4. 运行 trap_fuzzer.py

总结

TrapFuzzer 提供了一种在性能开销和测试效率间取得平衡的 Fuzz 方案:

  1. 适用场景

    • 大型软件测试
    • 需要快速上手的项目
    • 资源受限环境
  2. 优势

    • 无需深入分析目标程序
    • 较低的性能开销
    • 灵活的配置选项
  3. 局限性

    • 覆盖率粒度较粗
    • 依赖 IDA 进行预处理

通过合理配置和优化,TrapFuzzer 可以成为传统 Fuzz 工具的有效补充,特别适合在资源受限或需要快速测试大型软件的场景下使用。

TrapFuzzer 源码分析与使用指南 概述 TrapFuzzer 是一款基于断点技术获取程序覆盖率的模糊测试工具,与 AFL 等传统 Fuzz 工具相比具有以下特点: 优点 : 对程序性能影响较小 支持单模块插桩 平台要求低(仅需支持软件断点) 无需深入分析目标程序的数据处理函数 缺点 : 覆盖率记录粒度较粗(基本块级别) 基本原理 TrapFuzzer 的核心工作原理: 预处理阶段 : 使用 IDA 将目标模块所有基本块的第一条指令替换为断点指令(x86 下为 \xcc ) 保存原始指令的位置、大小和内容到文件中 Fuzz 阶段 : 当程序执行到新基本块时触发断点 记录执行到的基本块地址 恢复原始指令让程序继续执行 通过这种方式收集程序执行路径 可选配置 : 是否在每次测试后恢复二进制文件中的断点指令( patch_to_binary 选项) 开启:提升速度(每个断点只命中一次),但只能记录新发现的基本块 关闭:完整记录所有执行路径,但速度较慢 核心模块分析 1. Tracer 模块 负责获取进程执行过程中的覆盖率,支持两种实现方式: 1.1 Python-ptrace 实现 关键函数 trace() 流程: 创建并附加到目标进程 循环等待进程信号 当捕获 SIGTRAP 信号时: 获取指令指针 计算断点地址偏移 恢复原始指令 记录基本块地址 1.2 GDB Python 插件实现 关键组件: gdbtracer.py :主控制脚本 trap.py :GDB 插件脚本 cmd.gdb :GDB 初始化脚本 工作流程: 通过 subprocess 启动 GDB 加载目标程序 注册 GDB 事件处理器( stop_handler ) 当触发断点时: 通过 socket 通信获取原始指令 恢复指令并继续执行 记录基本块地址 2. 数据变异模块 支持三种变异器: 2.1 RadamsaMutator 直接调用 radamsa 命令行工具进行变异 简单但依赖外部工具 2.2 VanapaganMutator 包含两种变异策略: FileBitFlipping:比特翻转 FileByteValues:特殊字节替换 2.3 HonggfuzzMutater 将 honggfuzz 的变异器用 Python 重写 提供更丰富的变异策略 3. Fuzz 调度模块 3.1 测试用例加载 ( load_testcase ) 从指定目录加载初始测试用例 只保存产生新路径的用例 计算样本平均执行时间(用于 DOS 检测) 3.2 用例集精简 ( minimize ) 为所有用例生成覆盖率信息 选择覆盖率最大的用例加入精简集 剔除冗余用例(覆盖率已被包含的) 重复直到没有新用例 3.3 主循环 ( fuzz ) 加载初始用例(或恢复之前状态) 随机选择变异器 遍历样本队列: 变异当前样本 执行并获取覆盖率 处理结果: 新路径:加入队列 DOS/崩溃:特殊处理 持续循环 3.4 样本打分策略 ( Testcase 类) 初始执行次数:50 发现新路径:增加 10% 执行次数 导致 DOS:减少 10% 执行次数 使用指南 1. 准备工作 使用 IDA 分析目标程序 运行 dump_bb.py 导出基本块信息到 bb.txt 运行 setbp.py 修改二进制文件(替换为断点指令) 2. 配置文件 ( config.json ) 关键配置项说明 : | 配置项 | 说明 | |--------|------| | tracer | 覆盖率获取方式: gdb , python-ptrace , gdb-run | | mutator | 变异器: Vanapagan-mutator , radamsa-mutator , honggfuzz-mutator | | basic_block_file_path | 基本块信息文件路径 | | coverage_module_name | 要收集覆盖率的模块名 | | patch_to_binary | 是否恢复二进制中的断点指令(影响速度/完整性) | | exit_basci_block_list | 触发退出的基本块地址(多个用逗号分隔) | 3. 运行流程 准备目标程序(已插桩) 准备初始测试用例 配置 config.json 运行 trap_fuzzer.py 总结 TrapFuzzer 提供了一种在性能开销和测试效率间取得平衡的 Fuzz 方案: 适用场景 : 大型软件测试 需要快速上手的项目 资源受限环境 优势 : 无需深入分析目标程序 较低的性能开销 灵活的配置选项 局限性 : 覆盖率粒度较粗 依赖 IDA 进行预处理 通过合理配置和优化,TrapFuzzer 可以成为传统 Fuzz 工具的有效补充,特别适合在资源受限或需要快速测试大型软件的场景下使用。