对比一下 QEMU 模式的 Fuzzing 和源码模式的 Fuzzing

1. 源码模式 Fuzzing

源码模式 Fuzzing(也称为插桩式 Fuzzing)是在编译时对目标程序进行修改,插入额外的代码(即“插桩”)。这些桩点会在程序运行时收集代码覆盖率等信息,并反馈给 Fuzzer,指导其生成更有效的输入

工作原理

  • 编译插桩:Fuzzer 使用专门的编译器前端(如 AFL-Clang 或 LLVM-sanitizer)来编译目标程序的源码
  • 插入探针:编译器会在每个基本块(Basic Block)的开头插入一个探针。当程序执行到一个新的基本块时,探针会向 Fuzzer 反馈这个信息
  • 反馈循环:Fuzzer 根据这些覆盖率信息,判断哪些输入探索了新的代码路径。它会保留这些有价值的输入,并对其进行变异,以期能找到更深层次的代码逻辑

优点

  • 高效:插桩非常轻量级,几乎不会引入额外的性能开销。Fuzzer 能够以极高的速度运行和测试样本,每秒可达数千甚至数万次
  • 精确的代码覆盖率:由于插桩在编译时完成,Fuzzer 能够获得非常精确的、基本块级别的代码覆盖率,这使得它能够更有效地探索代码路径
  • 直接定位崩溃点:由于 Fuzzer 能够知道输入触发了哪段代码,一旦发生崩溃,它能迅速定位到崩溃发生的基本块

缺点

  • 需要源码:这是最大的局限性。如果目标程序是闭源的,你就无法使用这种方法
  • 编译复杂:对于复杂的项目,编译过程可能会很复杂,需要处理各种依赖和编译选项

2. QEMU 模式 Fuzzing

QEMU 模式 Fuzzing(也称为黑盒或二进制 Fuzzing)是在二进制级别进行插桩和监控。它使用 QEMU 模拟器来运行目标程序,并通过修改 QEMU 的代码来收集代码覆盖率信息。

工作原理

  • 二进制插桩:Fuzzer 启动一个修改过的 QEMU 用户模式模拟器
  • 动态翻译:QEMU 在运行目标程序时,会动态地将目标程序的机器码翻译成宿主机的机器码。在翻译过程中,Fuzzer 的插桩逻辑会被嵌入到生成的代码中
  • 收集覆盖率:当翻译后的代码执行时,插桩逻辑会收集代码覆盖率信息,并反馈给 Fuzzer。

优点

  • 无需源码:这是 QEMU 模式最大的优势。它能够 Fuzz 任何闭源的、可执行的二进制文件,这在分析恶意软件或商业软件时至关重要
  • 全系统覆盖:除了用户态程序,QEMU 还可以模拟整个系统。这意味着你可以用它来 Fuzz 驱动程序或内核

缺点

  • 性能开销大:由于 QEMU 是一个模拟器,它会引入大量的性能开销。Fuzzing 速度比源码模式慢得多,通常每秒只能运行几十到几百次
  • 覆盖率信息粗糙:QEMU 模式通常只能提供基本块级别的覆盖率,但可能无法像源码模式那样精确地追踪到每一条指令的执行
  • 不稳定性:由于 QEMU 本身的复杂性,Fuzzing 过程中可能会出现一些不稳定的情况
特性 源码模式 Fuzzing QEMU 模式 Fuzzing
是否需要源码
性能 极高(每秒数千次) 较低(每秒数十次)
代码覆盖率 非常精确(基本块级别) 较精确(基本块级别)
适用场景 开源项目、内部代码审计 闭源软件、恶意软件分析、驱动程序 Fuzzing
代表工具 AFL++、LibFuzzer AFL-QEMU
Copyright © 版权信息 all right reserved,powered by Gitbook该文件修订时间: 2025-09-25 03:13:08

results matching ""

    No results matching ""