Skip to content

jay-waves/barefuzz

Repository files navigation

使用方法

  1. 在 *vte/fuzz 目录下, 配置 config.json.
  2. 将 radare2/bin 路径添加到系统 PATH
  3. 用 VTest 打开项目 .vte, 在项目设计页面中:
    1. 点击 CmdSys, 关闭与 DTP 连接. 目前版本无需 DTP.
    2. 将 fuzz_dongle.dll 添加到工程中
    3. 将 fuzz_dongle.dll 和 CmdSys 芯片 RECV_CMD 虚拟端口连接. 用于转发前端测试用例.
    4. 将 fuzz_dongle.dll 和 BM3803 芯片 IRQ GPIO (如果有) 连接. 用于主动触发中断.

运行时所有信息都放在 *vte/fuzz 目录下.

使用时注意事项 (FAQ)

  • VTest 版本至少高于 2.80
  • VTest 只支持 DWARF2 及之前版本的 ELF 调试信息
  • 在没有 VS2022 环境的机器上 (比如 Win10 早期版本), 需要安装 VC++ Redistributable 2022 来补充依赖的新版标准库.
  • 不建议路径有中文, 配置文件中的中文请使用 utf-8 编码
  • dongle.dll 或项目配置有更新时, 请重启整个 VTest. VTest 关闭项目不保证刷新 DLL.
  • 250911 版本似乎偶尔有线程泄漏? 关闭 VTest 后也无法清除.
  • 项目有更新时, 可以删除 fuzz/ 中除 config.json 外所有的状态文件, 来刷新整个缓存.

/fuzz 目录

  • config.json 配置文件, 见下.
  • analz.json 存放静态分析数据, 由 static_analz.h 模块自动生成.
  • stats/ 状态数据文件
    • func_cov.json 函数覆盖率等
    • N.json 总运行计次
  • logs/ 运行时日志, 按 运行计次 + 时间戳 命名
  • bugs/ 漏洞数据, 按 运行计次 + 时间戳 命名
  • corpus/ 用于存放测试用例

config.json 配置

需要在 *.vte/fuzz 目录下提供 config.json, 用于配置参数. 其中包含如下信息:

{
  "log_level":"debug", // 日志级别 (debug, info, warn, error), 推荐设置为 info. 
  "proj_name":  "xxx", // 项目名
  "vtestc_path": "xxxxx/vtestc.exe", // 命令行 vtestc 启动路径 (可选). 路径要用 \\ 或 /
  "vte_path": "path/to/PRJ.vte", // vte 路径. (可选). 其实就是 proj_dir
  "target_path": "/path/to/xxx.elf", // elf 执行文件的路径. 支持相对 proj_dir 的相对路径.
  "socket": "tcp://localhost:5555", // 前端 ZeroMQ 通信绑定到的地址. 一般默认值即可.
  "socket_enable": false,

  // "entry_addr":  "0x0000", // 程序入口, 也是向量表入口. 固定式 0x0000, 不再需要
  "trap_table_base": "0x0000", // Trap Table 入口地址. 这个不一定是 0x0000, 可用 TBR 修改.
  "init_sp": "0x5fffffff", // 初始栈指针值
  "irqs": [1, 2, ...], // 使用到的中断, 从 1~15 (对应 TBR TT 0x11~0x1f). 不要有零.
  "memory_map": [ // 不再此处声明的内存段, 不会插入内存 HooK
    {
      "name": "ram", // 内存段名称, 不要超过 20 字符
      "base_addr": "0x40000000", //  内存基地址
      "size": "0x1ffff", // 字节大小
      "flags": "rw-" // 权限
    }
  ],
  "sanitizers": { // 检查器开关
    "segv_check_enable": true,
    "trap_check_enable": true,
    "shadow_mem_enable": true,
    "shadow_reg_enable": true, // 要使用影子寄存器, 需同时开启 REG_HOOK 宏
    "int_overflow_check_enable": true,
    "atomv_check_enable": true
  }
}

规定 config.json 必须是 utf-8 字符编码.

静态分析器 fuzz_analz.exe 配置

fuzz_analz.exe 是一个命令行工具, 用于静态分析目标文件, 生成数据存储在 analz.json 中. analz.json 类似数据库文件, 用于存储 fuzz_dongle.dll 需要的分析数据

需要确保 radare2 存在于系统 PATH 中.

fuzz_analz.exe 运行配置项如下:

  • --tartget: 必须项, 目标文件路径
  • --entry_addr: 程序入口地址. (可选, 裸机二进制需要配置, ELF 一般不用)
  • --load_addr: 程序加载地址. (可选, 同上)
  • --arch: ISA 架构. 目前仅支持 sparc, 默认 sparc.
  • --bits: 硬件字长. 默认 32 (sparc v8)

执行结束后, 执行目录下会出现 analz.json 文件. 手动拷贝至 VTest 项目路径下的 /fuzz 文件夹即可. fuzz_dongle.dll 和内置了 fuzz_analz.exe 的功能, 但仅支持 SPARC v8.

fuzz_analz.exe 实际的加载命令:

  • r2 -a arm -b 16 -m 0x08000000
  • r2 -a sparc -b 32 -m 0x400000 -e cfg.bigendian=true

整体框架

  • frontend: 模糊测试工具. 负责迭代和生成协议测试用例.
  • vtestc.exe: VTest 虚拟机的命令行版本
    • bm3803.dll: 定制化的虚拟 CPU. 支持主中断触发, 等.
    • cmdsys: 被测项目发令器.
    • fuzz_dongle.dll: 缺陷检查器, 程序状态监控器, 测试用例转发.

流程如下:

  1. frontend 通过 socket 连接到 fuzz_dongle, 向其发送控制命令.
  2. frontend 生成一个测试用例 tc, 发送给 fuzz_dongle
  3. fuzz_dongle 通过虚端口连接到 CmdSys, 将测试用例 tc 转发给 CmdSys
  4. CmdSys 由被测项目本身配置, 负责将 tc 通过某种串口传递给 CPU, 触发程序.
  5. 一段时间后, frontend 要求 fuzz_dongle 收集覆盖等信息

程序监视器架构

所以 虚拟机相关 API 都封装在 vtest/vtest.h 下, 相关概念定义在 vtest/concepts.h 中. 通过 vtest/plugin_registry.h 定义的反向绑定接口 REGISTER_PLUGIN(xxx, VTest) 来将自己注册为虚拟机插件. 没有前端发令时, Dongle 也被设计为能够独立工作, 执行缺陷检查功能.

Section Error

检查内存访问异常. 包括:

  • 内存节错误, 访问了 bss/data/stack 等内存间隙
  • 内存段错误, 访问了 rom/ram/falsh 外的未分配内存. 此部分需要手动 config.json 配置段定义.
  • 违反了内存 rwx 属性

Memory Uninit

检查局部变量的未初始化访问.

例外情况:

  • 局部变量未声明 volatile, 导致局部变量被优化为寄存器.
  • 全局变量未初始化. 一般在 startup.S 中清空 .bss/.data, 不能分辨是否为确切错误.

Div By Zero

检查整数除零和浮点数除零. 原理是监控 Trap Table 的除零异常和浮点数异常, 须要在 config.json 中准确 定义 trap_table_base.

Atomicity Violation

检查中断导致的原子性违反. 误报较多, 实验性.

Int Overflow

检查数据溢出错误. 原理是监控硬件汇编指令, 包括以下种类:

  • SLL: 左移指令. 超出 32b 即判错.
  • ADD: 加法指令. 由于没办法区分寄存器内数据的实际语义, 包括 位宽 (32b,16b,8b)符号 (signed, unsigned), 所以我们只视为一种情况: 32b 位宽的有符号加法.
  • SUB: 减法指令, 我们将 sub a, b 视为 add a, -b.
  • ADDX: 用于 64b 数据加法, 视为 64b 有符号加法.
  • SUBX: ...

例外情况:

  • 无符号 32b/64b 的加减法溢出, 会误报
  • 小于 32b 位宽的加减法, 会漏报
  • ADDCC / ADDCCX 指令, 因为通常和条件跳转有关, 不检测. 我们只关心算术.

前后端通信

在 VTest 之外的用户作为请求者, 向 VTest 中 dongle.dll 插件发起请求, 并得到回应. dongle.dll 中可能有多个 VTest 插件, 他们复用了同一个 Socket, 通过过滤 Msg::EventT 实现事件分发.

基于 ZMQ.Pair 模式, 但是仅实现了单工单向请求. 即, 前端 fuzzingloop 向其他各个组件发起一个 Request, 各个组件则回应一个 Response. 和每个组件都有独立的 Socket 连接.

包格式

{
  "type" :  "req" | "resp",
  "id" : "uuid", // 用于匹配响应
  "event" : "hello" | "testcase" | ...,  // 包实际类型
  "body" : "..." // 实际载荷, 可能为空
}

实际消息中, type, event 都是用枚举整数值实现的, 详见 ./socket.h 定义.

包类型

type event 方向 数据含义 数据
req testcase Frontend --> Dongle 单次测试用例数据 base64 编码的二进制数据
resp 测试用例派发结果 "ok"/"error"
req hello Frontend --> Dongle 心跳检测 "yyy"
resp "it's me, xxx"
req bug Dongle --> Frontend 询问上一轮是否有漏洞发现
resp 漏洞类型 "{bug_code}"
req cov_edge Frontend --> Dongle 询问覆盖的基本块边总数 (含历史)
resp "133"
req cov_func Frontend --> Dongle 询问上一轮覆盖的函数总数
resp "111"
req start_round Frontend --> Dongle 开启新一轮 fuzz
resp "ok"/"error"
req finish_round Frontend --> Dongle 结束单轮 fuzzing, 保存状态
resp "ok"

对于 req/resp, msg.id 是一致的.

操控 Fuzz 声明周期时, 消息顺序是: hello --> start_round --> finish_round --> ... --> start_round --> finish_round

想要保存状态, 请使用 finish_round, 之后稍作等待后, 再杀死虚拟机进程. 类似地, 请使用 start_round 让各组件 正确完成状态转移, 否则组件可能认为自身处于非法状态而拒绝执行功能.

通信角色定义

  • Frontend: 消息中转, 模糊测试, Python.
  • Dongle: 覆盖率检测, 缺陷监控, 转发测试用例, C++.

Frontend 负责发送 REQ, 阻塞等待 Dongle 响应 RESP. 不支持其他通信模式.

错误处理

状态转移失败时, 返回 "error". 可能的问题如下:

  • "run" 返回 "error": 发送的 round_num 无法解析为整型数字, 应该发送一个递增的整型数字
  • "testcase" 返回 "error": Issuer 中外设未成功向芯片中写入数据

缺陷代码定义

注意, 没有 bug 时返回的是代码 0. 详见 ./fuzz.h

enum BUG {
    NONE = 0,
    SECTION_ERROR,
    MEMORY_UNINIT,
    USE_AFTER_FREE,
    STACK_UNDERFLOW,
    DIV_BY_ZERO,
    FDIV_BY_ZERO, // 浮点数除零
    DATA_ACCESS_ERROR,
    ADDR_NOT_ALIGNED,
    WIN_UNDERFLOW,
    WIN_OVERFLOW,
    BUG_OUT_OF_BOUNDS,
    ILL_INSN
};

开发

代码风格

  • 代码风格基于 Google C++ 风格, 但有出入:
    1. 变量 / 函数 / 方法 使用蟒蛇型命名 snake_case
    2. 常量以 k_ 开头, 全局变量以 g_ 开头.
    3. 类, 结构体使用驼峰型命名: CamelCase
    4. 宏为全大写蟒蛇型命名 SNAKE_CASE
    5. 行宽度为 100 字符, 中文应占两字符
  • 使用 PEP8 python 代码风格.
  • 常用标准库和第三方库包含在 include/common.h 中, 开发时可以使用该文件.
  • 引用本项目的内部头文件时, 需要用相对项目根的引用路径, 如 #include "vtest/vtest.h"
  • 源码文件必须使用 UTF-8 编码, 这是 SPDLOG 库的要求.
  • 使用 C++20 标准库版本, 但禁用一些功能: modules + ranges. modules 支持不稳定; ranges 一些功能在 c++23 才完善, 因此改用第三方的 range-v3
  • 注意, 尽量减少对 Windows API, Windows 平台宏和系统调用的依赖, 优先使用标准库 / 第三方库替代方案.

远程仓库必须为 Private 状态. 请提交 PR, 不要直接覆盖和修改我的代码.

依赖

由于 VTest 兼容性问题, 使用 x86-windows 平台, C++20 + vcpkg + CMake(>3.25) + MSVC2022 工具链.

外部依赖项: 通过 vcpkg 提供, x86-windows-static-md 平台

cppzmq:x86-windows-static-md catch2:x86-windows-static-md spdlog:x86-windows-static-md elfio:x86-windows-static-md capstone:x86-windows-static-md cereal:x86-windows-static-md cxxopts:x86-windows-static-md nlohmann-json:x86-windows-static-md zlib:x86-windows-static-md nng:x86-windows-static-md

新版本实际不再需要的库:

  • capstone: 源码已经合并到本仓库
  • cppzmq: 提供了 nng/zmq 两种功能选择: Go 绑定默认 NNG, Python 则拿 ZeroMQ 实现.
  • jsoncpp: 完全迁移到 nlohmann-json
  • cereal: 序列化已经全部换为 nlohmann-json.
  • range-v3: 改为标准库 c++20 ranges, 部分未支持函数自己实现. range-v3 IDE 总报错.

命令行程序依赖:

  • radare2: 用于控制流分析和调试信息解析, 需要添加到 PATH 中.
  • addr2line: 可选.

编译步骤 (CMake)

  1. cmake -S . -B ./build --preset=xxx
  2. cmake --build ./build --preset=xxxx
  3. 需要调试时, 进入 ./build 内点击 xxx.sln 进入 VS 界面, 配置启动项目及调试参数即可.

需要按需配置 CMakePresets.json. 目前提供两种基于 vcpkg (记得配置 VCPKG_ROOT)

  • vs-x86-release
  • vs-x86-debug

源码分发步骤

  1. 获取源码
  2. 获取并解压提供的 vcpkg 导出包, 并配置 VCPKG_ROOT
  3. 获取第三方工具 radare2, 将 /bin 目录添加到 PATH 中.
  4. 获取第三方工具 cmake (> 3.25)
  5. 轩宇 VTest2.80 及之后版本, 详见 vtest/sunrise/vttDevice.h 要求

编译时注意事项

  1. 项目使用 CMake + VS22 编译工具链, 请确保 VS22 中的 C++ CMake Tools for Windows 组件启用.
  2. CMakePresets.json 中, 提供了 Ninja 和 VS2022 两种编译链, 推荐使用 VS2022, Ninja 仅用于调试.
  3. VTest 要求 MainProc 符号, 我们定义在 vtest/vtest_mainproc.cc 中, 但是需要用户手动在 DLL 中 导出. 通过 /EXPORT 参数.

测试

.\build\tests\Debug\all_tests.exe --list-tests

.\build\tests\Debug\all_tests.exe -s

实验性功能

addr2line

aflnet

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published