使用 afl-unicorn: Fuzzing 任意二进制代码
字数 1840 2025-08-03 16:44:47

AFL-Unicorn 模糊测试任意二进制代码教学文档

一、AFL-Unicorn 概述

AFL-Unicorn 是 American Fuzzy Lop (AFL) 的一个扩展模式,它结合了 Unicorn 引擎的能力,允许对任意二进制代码进行模糊测试,即使这些代码无法通过传统命令行方式访问。

1.1 核心功能

  • 模拟目标代码执行环境
  • 提供基于覆盖率的模糊测试
  • 支持任意架构的二进制代码
  • 可针对嵌入式系统、复杂程序中的特定函数进行测试

1.2 适用场景

  1. 嵌入式系统中通过RF接收输入的解析函数
  2. 深藏在复杂、缓慢程序中的特定代码段
  3. 难以调试的系统组件
  4. 需要模拟执行环境的测试场景

二、安装与配置

2.1 系统要求

  • Linux 系统(推荐 Ubuntu 16.04 LTS)
  • 已卸载任何现有的 Unicorn 二进制文件

2.2 安装步骤

# 克隆 afl-unicorn 仓库
git clone https://github.com/[afl-unicorn-repo].git

# 构建和安装 AFL
cd /path/to/afl-unicorn
make
sudo make install

# 构建 Unicorn 支持
cd unicorn_mode
sudo ./build_unicorn_support.sh

2.3 注意事项

  • 构建过程会编译并安装修补版本的 Unicorn Engine v1.0.1
  • 必须卸载任何现有的 Unicorn 二进制文件
  • 仅支持 Linux 系统

三、工作原理

3.1 基本架构

AFL-Unicorn 通过实现 AFL 的 QEMU 模式用于 Unicorn Engine 的块边缘检测来工作:

  1. AFL 使用来自模拟代码段的块覆盖信息驱动输入生成
  2. 测试工具加载目标代码并设置初始状态
  3. 加载 AFL 从磁盘变异的数据
  4. 模拟目标二进制代码执行
  5. 检测崩溃或错误时抛出信号

3.2 关键组件

  • Unicorn Engine: 提供多架构模拟能力
  • AFL Fork Server: 高效管理模糊测试进程
  • Coverage Tracking: 跟踪代码块执行情况
  • Crash Detection: 识别异常执行情况

四、测试工具开发

4.1 基本要求

测试工具必须:

  1. 通过命令行指定的文件加载变异输入
  2. 在检测到崩溃时强制自身崩溃(如抛出异常)
  3. 在加载模糊输入数据前至少模拟1条指令(AFL fork server要求)

4.2 示例测试工具结构

import argparse
import os
import signal
from unicorn import *
from unicorn.mips_const import *

# 1. 定义内存映射
CODE_ADDRESS = 0x00100000  # 代码加载地址
STACK_ADDRESS = 0x00200000 # 栈地址
DATA_ADDRESS = 0x00300000 # 数据缓冲区地址

# 2. 初始化Unicorn引擎
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN)

# 3. 加载目标二进制文件
binary_file = open(BINARY_FILE, 'rb')
binary_code = binary_file.read()
binary_file.close()

# 4. 映射内存并写入代码
uc.mem_map(CODE_ADDRESS, CODE_SIZE_MAX)
uc.mem_write(CODE_ADDRESS, binary_code)

# 5. 设置初始寄存器状态
uc.reg_write(UC_MIPS_REG_PC, CODE_ADDRESS)
uc.reg_write(UC_MIPS_REG_SP, STACK_ADDRESS + STACK_SIZE)

# 6. 启动AFL fork server(必须执行至少1条指令)
uc.emu_start(uc.reg_read(UC_MIPS_REG_PC), 0, 0, count=1)

# 7. 加载变异输入
input_file = open(args.input_file, 'rb')
input = input_file.read()
input_file.close()
uc.mem_write(DATA_ADDRESS, input)

# 8. 执行目标代码
try:
    uc.emu_start(uc.reg_read(UC_MIPS_REG_PC), end_address)
except UcError as e:
    force_crash(e)  # 检测到崩溃时通知AFL

4.3 崩溃检测函数

def force_crash(uc_error):
    mem_errors = [
        UC_ERR_READ_UNMAPPED, UC_ERR_READ_PROT, UC_ERR_READ_UNALIGNED,
        UC_ERR_WRITE_UNMAPPED, UC_ERR_WRITE_PROT, UC_ERR_WRITE_UNALIGNED,
        UC_ERR_FETCH_UNMAPPED, UC_ERR_FETCH_PROT, UC_ERR_FETCH_UNALIGNED,
    ]
    
    if uc_error.errno in mem_errors:
        os.kill(os.getpid(), signal.SIGSEGV)  # 内存错误
    elif uc_error.errno == UC_ERR_INSN_INVALID:
        os.kill(os.getpid(), signal.SIGILL)   # 非法指令
    else:
        os.kill(os.getpid(), signal.SIGABRT)  # 其他错误

五、模糊测试执行

5.1 准备测试环境

  1. 创建样本输入目录:mkdir -p sample_inputs
  2. 准备初始测试用例(至少一个文件)

5.2 启动模糊测试

afl-fuzz -U -m none -i ./sample_inputs -o ./output -- python simple_test_harness.py @@

参数说明:

  • -U: 启用Unicorn模式
  • -m none: 禁用内存限制(Unicorn可能需要较多RAM)
  • -i: 输入样本目录
  • -o: 输出结果目录
  • @@: 表示AFL将替换为输入文件路径

5.3 结果分析

  • 崩溃用例位于output/crashes/目录
  • 可手动运行测试工具调试崩溃:
    python simple_test_harness.py output/crashes/id:000000,sig:11
    

六、高级应用技巧

6.1 路径探索

通过修改测试工具,可以强制特定条件下的"崩溃",使AFL捕获导致特定代码路径的输入:

if pc == TARGET_ADDRESS:  # 当执行到特定地址时
    os.kill(os.getpid(), signal.SIGUSR1)  # 使用自定义信号

6.2 性能优化

  1. 使用C语言测试工具:比Python实现快5-10倍
  2. 减少模拟范围:只模拟必要的代码段
  3. 优化内存映射:减少不必要的内存区域

6.3 多平台支持

虽然示例使用MIPS架构,但Unicorn支持:

  • ARM, ARM64 (Thumb, ARM)
  • M68K
  • MIPS
  • PowerPC
  • SPARC
  • x86 (16, 32, 64-bit)

七、实际应用案例

7.1 嵌入式系统分析

  1. 提取固件中的目标函数
  2. 确定输入数据位置(如硬件寄存器映射)
  3. 构建模拟环境(内存布局、外设行为)
  4. 进行模糊测试

7.2 Windows/Linux/Android进程功能测试

  1. 从进程中提取目标函数
  2. 重建执行上下文(寄存器、内存状态)
  3. 模拟函数执行
  4. 模糊测试特定功能

八、调试技巧

  1. 启用详细日志

    uc.hook_add(UC_HOOK_CODE, unicorn_debug_instruction)
    uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, unicorn_debug_mem_access)
    
  2. 使用Capstone反汇编

    from capstone import *
    cs = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN)
    for i in cs.disasm(code, size):
        print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
    
  3. 寄存器状态检查

    print("PC: 0x%x" % uc.reg_read(UC_MIPS_REG_PC))
    

九、限制与注意事项

  1. 性能考虑:模拟执行比原生执行慢
  2. 环境准确性:模拟环境与真实环境可能存在差异
  3. 输入约束:需要明确输入数据的格式和位置
  4. 状态初始化:需要正确设置初始寄存器状态
  5. 架构支持:并非所有架构特性都被完美模拟

十、扩展资源

  1. 官方资源

    • AFL-Unicorn GitHub: [链接]
    • Unicorn Engine: [链接]
    • American Fuzzy Lop: [链接]
  2. 相关工具

    • uEmu (IDA插件)
    • AFLTriforce (NCC Group项目)
  3. 进阶阅读

    • Project Zero的Broadcom WiFi芯片组漏洞研究
    • Comsecuris的嵌入式系统安全研究
AFL-Unicorn 模糊测试任意二进制代码教学文档 一、AFL-Unicorn 概述 AFL-Unicorn 是 American Fuzzy Lop (AFL) 的一个扩展模式,它结合了 Unicorn 引擎的能力,允许对任意二进制代码进行模糊测试,即使这些代码无法通过传统命令行方式访问。 1.1 核心功能 模拟目标代码执行环境 提供基于覆盖率的模糊测试 支持任意架构的二进制代码 可针对嵌入式系统、复杂程序中的特定函数进行测试 1.2 适用场景 嵌入式系统中通过RF接收输入的解析函数 深藏在复杂、缓慢程序中的特定代码段 难以调试的系统组件 需要模拟执行环境的测试场景 二、安装与配置 2.1 系统要求 Linux 系统(推荐 Ubuntu 16.04 LTS) 已卸载任何现有的 Unicorn 二进制文件 2.2 安装步骤 2.3 注意事项 构建过程会编译并安装修补版本的 Unicorn Engine v1.0.1 必须卸载任何现有的 Unicorn 二进制文件 仅支持 Linux 系统 三、工作原理 3.1 基本架构 AFL-Unicorn 通过实现 AFL 的 QEMU 模式用于 Unicorn Engine 的块边缘检测来工作: AFL 使用来自模拟代码段的块覆盖信息驱动输入生成 测试工具加载目标代码并设置初始状态 加载 AFL 从磁盘变异的数据 模拟目标二进制代码执行 检测崩溃或错误时抛出信号 3.2 关键组件 Unicorn Engine : 提供多架构模拟能力 AFL Fork Server : 高效管理模糊测试进程 Coverage Tracking : 跟踪代码块执行情况 Crash Detection : 识别异常执行情况 四、测试工具开发 4.1 基本要求 测试工具必须: 通过命令行指定的文件加载变异输入 在检测到崩溃时强制自身崩溃(如抛出异常) 在加载模糊输入数据前至少模拟1条指令(AFL fork server要求) 4.2 示例测试工具结构 4.3 崩溃检测函数 五、模糊测试执行 5.1 准备测试环境 创建样本输入目录: mkdir -p sample_inputs 准备初始测试用例(至少一个文件) 5.2 启动模糊测试 参数说明: -U : 启用Unicorn模式 -m none : 禁用内存限制(Unicorn可能需要较多RAM) -i : 输入样本目录 -o : 输出结果目录 @@ : 表示AFL将替换为输入文件路径 5.3 结果分析 崩溃用例位于 output/crashes/ 目录 可手动运行测试工具调试崩溃: 六、高级应用技巧 6.1 路径探索 通过修改测试工具,可以强制特定条件下的"崩溃",使AFL捕获导致特定代码路径的输入: 6.2 性能优化 使用C语言测试工具 :比Python实现快5-10倍 减少模拟范围 :只模拟必要的代码段 优化内存映射 :减少不必要的内存区域 6.3 多平台支持 虽然示例使用MIPS架构,但Unicorn支持: ARM, ARM64 (Thumb, ARM) M68K MIPS PowerPC SPARC x86 (16, 32, 64-bit) 七、实际应用案例 7.1 嵌入式系统分析 提取固件中的目标函数 确定输入数据位置(如硬件寄存器映射) 构建模拟环境(内存布局、外设行为) 进行模糊测试 7.2 Windows/Linux/Android进程功能测试 从进程中提取目标函数 重建执行上下文(寄存器、内存状态) 模拟函数执行 模糊测试特定功能 八、调试技巧 启用详细日志 : 使用Capstone反汇编 : 寄存器状态检查 : 九、限制与注意事项 性能考虑 :模拟执行比原生执行慢 环境准确性 :模拟环境与真实环境可能存在差异 输入约束 :需要明确输入数据的格式和位置 状态初始化 :需要正确设置初始寄存器状态 架构支持 :并非所有架构特性都被完美模拟 十、扩展资源 官方资源 : AFL-Unicorn GitHub: [ 链接 ] Unicorn Engine: [ 链接 ] American Fuzzy Lop: [ 链接 ] 相关工具 : uEmu (IDA插件) AFLTriforce (NCC Group项目) 进阶阅读 : Project Zero的Broadcom WiFi芯片组漏洞研究 Comsecuris的嵌入式系统安全研究