aflpp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAFL++
AFL++
AFL++ is a fork of the original AFL fuzzer that offers better fuzzing performance and more advanced features while maintaining stability. A major benefit over libFuzzer is that AFL++ has stable support for running fuzzing campaigns on multiple cores, making it ideal for large-scale fuzzing efforts.
AFL++ 是原生AFL模糊测试工具的一个分支,在保持稳定性的同时,提供了更出色的模糊测试性能和更多高级功能。与libFuzzer相比,其一大优势是AFL++稳定支持在多核上运行模糊测试任务,非常适合大规模模糊测试工作。
When to Use
适用场景
| Fuzzer | Best For | Complexity |
|---|---|---|
| AFL++ | Multi-core fuzzing, diverse mutations, mature projects | Medium |
| libFuzzer | Quick setup, single-threaded, simple harnesses | Low |
| LibAFL | Custom fuzzers, research, advanced use cases | High |
Choose AFL++ when:
- You need multi-core fuzzing to maximize throughput
- Your project can be compiled with Clang or GCC
- You want diverse mutation strategies and mature tooling
- libFuzzer has plateaued and you need more coverage
- You're fuzzing production codebases that benefit from parallel execution
| 模糊测试工具 | 适用场景 | 复杂度 |
|---|---|---|
| AFL++ | 多核模糊测试、多样化变异、成熟项目 | 中等 |
| libFuzzer | 快速搭建、单线程、简单测试套 | 低 |
| LibAFL | 自定义模糊测试工具、研究、高级场景 | 高 |
选择AFL++的场景:
- 你需要多核模糊测试以最大化吞吐量
- 你的项目可以用Clang或GCC编译
- 你需要多样化的变异策略和成熟的工具链
- libFuzzer的测试覆盖进入瓶颈,你需要更高的覆盖率
- 你正在对受益于并行执行的生产代码库进行模糊测试
Quick Start
快速开始
c
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Call your code with fuzzer-provided data
check_buf((char*)data, size);
return 0;
}Compile and run:
bash
undefinedc
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Call your code with fuzzer-provided data
check_buf((char*)data, size);
return 0;
}编译并运行:
bash
undefinedSetup AFL++ wrapper script first (see Installation)
Setup AFL++ wrapper script first (see Installation)
./afl++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
mkdir seeds && echo "aaaa" > seeds/minimal_seed
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz
undefined./afl++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
mkdir seeds && echo "aaaa" > seeds/minimal_seed
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz
undefinedInstallation
安装
AFL++ has many dependencies including LLVM, Python, and Rust. We recommend using a current Debian or Ubuntu distribution for fuzzing with AFL++.
| Method | When to Use | Supported Compilers |
|---|---|---|
| Ubuntu/Debian repos | Recent Ubuntu, basic features only | Ubuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12 |
| Docker (from Docker Hub) | Specific AFL++ version, Apple Silicon support | As of 4.35c: Clang 19 & GCC 11 |
| Docker (from source) | Test unreleased features, apply patches | Configurable in Dockerfile |
| From source | Avoid Docker, need specific patches | Adjustable via |
AFL++有许多依赖项,包括LLVM、Python和Rust。我们推荐使用最新的Debian或Ubuntu发行版来运行AFL++模糊测试。
| 安装方式 | 适用场景 | 支持的编译器 |
|---|---|---|
| Ubuntu/Debian仓库 | 新版Ubuntu、仅需基础功能 | Ubuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12 |
| Docker(来自Docker Hub) | 指定AFL++版本、支持Apple Silicon | 截至4.35c版本: Clang 19 & GCC 11 |
| Docker(从源码构建) | 测试未发布功能、应用补丁 | 可在Dockerfile中配置 |
| 从源码安装 | 避免使用Docker、需要特定补丁 | 通过 |
Ubuntu/Debian
Ubuntu/Debian
Prior to installing afl++, check the clang version dependency of the packge with , and install the matching version (e.g., ).
apt-cache show afl++lldlld-17bash
apt install afl++ lld-17在安装afl++之前,使用检查软件包的Clang版本依赖,并安装匹配的版本(例如)。
apt-cache show afl++lldlld-17bash
apt install afl++ lld-17Docker (from Docker Hub)
Docker(来自Docker Hub)
bash
docker pull aflplusplus/aflplusplus:stablebash
docker pull aflplusplus/aflplusplus:stableDocker (from source)
Docker(从源码构建)
bash
git clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .bash
git clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .From source
从源码安装
Refer to the Dockerfile for Ubuntu version requirements and dependencies. Set to specify Clang version (e.g., ).
LLVM_CONFIGllvm-config-18Wrapper Script Setup
包装器脚本设置
Create a wrapper script to run AFL++ on host or Docker:
bash
cat <<'EOF' > ./afl++
#!/bin/sh
AFL_VERSION="${AFL_VERSION:-"stable"}"
case "$1" in
host)
shift
bash -c "$*"
;;
docker)
shift
/usr/bin/env docker run -ti \
--privileged \
-v ./:/src \
--rm \
--name afl_fuzzing \
"aflplusplus/aflplusplus:$AFL_VERSION" \
bash -c "cd /src && bash -c \"$*\""
;;
*)
echo "Usage: $0 {host|docker}"
exit 1
;;
esac
EOF
chmod +x ./afl++Security Warning: The and scripts require root privileges and disable OS security features. Do not fuzz on production systems or your development environment. Use a dedicated VM instead.
afl-system-configafl-persistent-config创建一个包装器脚本以在主机或Docker上运行AFL++:
bash
cat <<'EOF' > ./afl++
#!/bin/sh
AFL_VERSION="${AFL_VERSION:-"stable"}"
case "$1" in
host)
shift
bash -c "$*"
;;
docker)
shift
/usr/bin/env docker run -ti \
--privileged \
-v ./:/src \
--rm \
--name afl_fuzzing \
"aflplusplus/aflplusplus:$AFL_VERSION" \
bash -c "cd /src && bash -c \"$*\""
;;
*)
echo "Usage: $0 {host|docker}"
exit 1
;;
esac
EOF
chmod +x ./afl++安全警告:和脚本需要root权限,并且会禁用操作系统安全功能。不要在生产系统或开发环境中进行模糊测试,请使用专用虚拟机替代。
afl-system-configafl-persistent-configSystem Configuration
系统配置
Run after each reboot for up to 15% more executions per second:
bash
./afl++ <host/docker> afl-system-configFor maximum performance, disable kernel security mitigations (requires grub bootloader, not supported in Docker):
bash
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ <host/docker> afl-system-configVerify with - output should include .
cat /proc/cmdlinemitigations=off每次重启后运行以下命令,可提升最高15%的每秒执行次数:
bash
./afl++ <host/docker> afl-system-config为了获得最佳性能,禁用内核安全缓解措施(需要grub引导加载程序,Docker中不支持):
bash
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ <host/docker> afl-system-config通过验证 - 输出应包含。
cat /proc/cmdlinemitigations=offWriting a Harness
编写测试套
Harness Structure
测试套结构
AFL++ supports libFuzzer-style harnesses:
c
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. Validate input size if needed
if (size < MIN_SIZE || size > MAX_SIZE) return 0;
// 2. Call target function with fuzz data
target_function(data, size);
// 3. Return 0 (non-zero reserved for future use)
return 0;
}AFL++支持libFuzzer风格的测试套:
c
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. Validate input size if needed
if (size < MIN_SIZE || size > MAX_SIZE) return 0;
// 2. Call target function with fuzz data
target_function(data, size);
// 3. Return 0 (non-zero reserved for future use)
return 0;
}Harness Rules
测试套规则
| Do | Don't |
|---|---|
| Reset global state between runs | Rely on state from previous runs |
| Handle edge cases gracefully | Exit on invalid input |
| Keep harness deterministic | Use random number generators |
| Free allocated memory | Create memory leaks |
| Validate input sizes | Process unbounded input |
See Also: For detailed harness writing techniques, patterns for handling complex inputs, and advanced strategies, see the fuzz-harness-writing technique skill.
| 建议做法 | 禁止做法 |
|---|---|
| 重置每次运行之间的全局状态 | 依赖前一次运行的状态 |
| 优雅处理边缘情况 | 遇到无效输入时退出 |
| 保持测试套的确定性 | 使用随机数生成器 |
| 释放分配的内存 | 造成内存泄漏 |
| 验证输入大小 | 处理无界输入 |
另请参阅: 有关编写测试套的详细技巧、处理复杂输入的模式以及高级策略,请查看fuzz-harness-writing技术文档。
Compilation
编译
AFL++ offers multiple compilation modes with different trade-offs.
AFL++提供多种编译模式,各有不同的权衡。
Compilation Mode Decision Tree
编译模式决策树
Choose your compilation mode:
- LTO mode (): Best performance and instrumentation. Try this first.
afl-clang-lto - LLVM mode (): Fall back if LTO fails to compile.
afl-clang-fast - GCC plugin (): For projects requiring GCC.
afl-gcc-fast
选择你的编译模式:
- LTO模式 (): 最佳性能和插桩效果,优先尝试此模式。
afl-clang-lto - LLVM模式 (): 如果LTO编译失败,可回退到此模式。
afl-clang-fast - GCC插件模式 (): 适用于需要GCC编译的项目。
afl-gcc-fast
Basic Compilation (LLVM mode)
基础编译(LLVM模式)
bash
./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzbash
./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzGCC Compilation
GCC编译
bash
./afl++ <host/docker> afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzImportant: GCC version must match the version used to compile the AFL++ GCC plugin.
bash
./afl++ <host/docker> afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz**重要提示:**GCC版本必须与编译AFL++ GCC插件时使用的版本匹配。
With Sanitizers
结合Sanitizers使用
bash
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzSee Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
bash
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz另请参阅: 有关Sanitizer的详细配置、常见问题和高级标志,请查看address-sanitizer和undefined-behavior-sanitizer技术文档。
Build Flags
构建标志
Note that is not necessary, it is added by default by the AFL++ compilers.
-g| Flag | Purpose |
|---|---|
| Skip main function when using libFuzzer harness |
| Production optimization level (recommended for fuzzing) |
| Enable libFuzzer compatibility mode and adds the fuzzer runtime when linking executable |
| Instrument without linking fuzzer runtime (for static libraries and object files) |
注意不是必需的,AFL++编译器会默认添加此标志。
-g| 标志 | 用途 |
|---|---|
| 使用libFuzzer测试套时跳过main函数 |
| 生产环境优化级别(推荐用于模糊测试) |
| 启用libFuzzer兼容模式,并在链接可执行文件时添加模糊测试运行时 |
| 插桩但不链接模糊测试运行时(适用于静态库和目标文件) |
Corpus Management
测试用例库管理
Creating Initial Corpus
创建初始测试用例库
AFL++ requires at least one non-empty seed file:
bash
mkdir seeds
echo "aaaa" > seeds/minimal_seedFor real projects, gather representative inputs:
- Download example files for the format you're fuzzing
- Extract test cases from the project's test suite
- Use minimal valid inputs for your file format
AFL++至少需要一个非空的种子文件:
bash
mkdir seeds
echo "aaaa" > seeds/minimal_seed对于实际项目,收集有代表性的输入:
- 下载你要模糊测试的格式的示例文件
- 从项目的测试套件中提取测试用例
- 使用你的文件格式的最小有效输入
Corpus Minimization
测试用例库最小化
After a campaign, minimize the corpus to keep only unique coverage:
bash
./afl++ <host/docker> afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzzSee Also: For corpus creation strategies, dictionaries, and seed selection, see the fuzzing-corpus technique skill.
测试任务完成后,最小化测试用例库,仅保留具有唯一覆盖范围的用例:
bash
./afl++ <host/docker> afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzz另请参阅: 有关测试用例库创建策略、字典和种子选择,请查看fuzzing-corpus技术文档。
Running Campaigns
运行测试任务
Basic Run
基础运行
bash
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzzbash
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzzSetting Environment Variables
设置环境变量
bash
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzzbash
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzzInterpreting Output
输出解读
The AFL++ UI shows real-time fuzzing statistics:
| Output | Meaning |
|---|---|
| execs/sec | Execution speed - higher is better |
| cycles done | Number of queue passes completed |
| corpus count | Number of unique test cases in queue |
| saved crashes | Number of unique crashes found |
| stability | % of stable edges (should be near 100%) |
AFL++的UI界面显示实时模糊测试统计数据:
| 输出项 | 含义 |
|---|---|
| execs/sec | 执行速度 - 数值越高越好 |
| cycles done | 完成的队列遍历次数 |
| corpus count | 队列中唯一测试用例的数量 |
| saved crashes | 发现的唯一崩溃案例数量 |
| stability | 稳定边的百分比(应接近100%) |
Output Directory Structure
输出目录结构
text
out/default/
├── cmdline # How was the SUT invoked?
├── crashes/ # Inputs that crash the SUT
│ └── id:000000,sig:06,src:000002,time:286,execs:13105,op:havoc,rep:4
├── hangs/ # Inputs that hang the SUT
├── queue/ # Test cases reproducing final fuzzer state
│ ├── id:000000,time:0,execs:0,orig:minimal_seed
│ └── id:000001,src:000000,time:0,execs:8,op:havoc,rep:6,+cov
├── fuzzer_stats # Campaign statistics
└── plot_data # Data for plottingtext
out/default/
├── cmdline # 被测系统的调用方式
├── crashes/ # 导致被测系统崩溃的输入
│ └── id:000000,sig:06,src:000002,time:286,execs:13105,op:havoc,rep:4
├── hangs/ # 导致被测系统挂起的输入
├── queue/ # 重现最终模糊测试状态的测试用例
│ ├── id:000000,time:0,execs:0,orig:minimal_seed
│ └── id:000001,src:000000,time:0,execs:8,op:havoc,rep:6,+cov
├── fuzzer_stats # 测试任务统计数据
└── plot_data # 用于绘图的数据Analyzing Results
结果分析
View live campaign statistics:
bash
./afl++ <host/docker> afl-whatsup outCreate coverage plots:
bash
apt install gnuplot
./afl++ <host/docker> afl-plot out/default out_graph/查看实时测试任务统计数据:
bash
./afl++ <host/docker> afl-whatsup out生成覆盖范围图表:
bash
apt install gnuplot
./afl++ <host/docker> afl-plot out/default out_graph/Re-executing Test Cases
重新执行测试用例
bash
./afl++ <host/docker> ./fuzz out/default/crashes/<test_case>bash
./afl++ <host/docker> ./fuzz out/default/crashes/<test_case>Fuzzer Options
模糊测试工具选项
| Option | Purpose |
|---|---|
| Maximum test input length (default: 1048576 bytes) |
| Timeout in milliseconds for each test case (default: 1000ms) |
| Memory limit in megabytes (default: 0 = unlimited) |
| Use dictionary file to guide mutations |
| 选项 | 用途 |
|---|---|
| 测试输入的最大长度(默认:1048576字节) |
| 每个测试用例的超时时间(毫秒,默认:1000ms) |
| 内存限制(兆字节,默认:0=无限制) |
| 使用字典文件指导变异操作 |
Multi-Core Fuzzing
多核模糊测试
AFL++ excels at multi-core fuzzing with two major advantages:
- More executions per second (scales linearly with physical cores)
- Asymmetrical fuzzing (e.g., one ASan job, rest without sanitizers)
AFL++在多核模糊测试方面表现出色,具有两大优势:
- 更高的每秒执行次数(与物理核心数线性扩展)
- 非对称模糊测试(例如,一个ASan任务,其余任务不使用Sanitizers)
Starting a Campaign
启动测试任务
Start the primary fuzzer (in background):
bash
./afl++ <host/docker> afl-fuzz -M primary -i seeds -o state -- ./fuzz 1>primary.log 2>primary.error &Start secondary fuzzers (as many as you have cores):
bash
./afl++ <host/docker> afl-fuzz -S secondary01 -i seeds -o state -- ./fuzz 1>secondary01.log 2>secondary01.error &
./afl++ <host/docker> afl-fuzz -S secondary02 -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &启动主模糊测试进程(后台运行):
bash
./afl++ <host/docker> afl-fuzz -M primary -i seeds -o state -- ./fuzz 1>primary.log 2>primary.error &启动从模糊测试进程(数量与核心数一致):
bash
./afl++ <host/docker> afl-fuzz -S secondary01 -i seeds -o state -- ./fuzz 1>secondary01.log 2>secondary01.error &
./afl++ <host/docker> afl-fuzz -S secondary02 -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &Monitoring Multi-Core Campaigns
监控多核测试任务
List all running jobs:
bash
jobsView live statistics (updates every second):
bash
./afl++ <host/docker> watch -n1 --color afl-whatsup state/列出所有运行中的任务:
bash
jobs查看实时统计数据(每秒更新一次):
bash
./afl++ <host/docker> watch -n1 --color afl-whatsup state/Stopping All Fuzzers
停止所有模糊测试进程
bash
kill $(jobs -p)bash
kill $(jobs -p)Coverage Analysis
覆盖范围分析
AFL++ automatically tracks coverage through edge instrumentation. Coverage information is stored in and .
fuzzer_statsplot_dataAFL++通过边插桩自动跟踪覆盖范围,覆盖范围信息存储在和中。
fuzzer_statsplot_dataMeasuring Coverage
测量覆盖范围
Use to visualize coverage over time:
afl-plotbash
./afl++ <host/docker> afl-plot out/default out_graph/使用可视化随时间变化的覆盖范围:
afl-plotbash
./afl++ <host/docker> afl-plot out/default out_graph/Improving Coverage
提升覆盖范围
- Use dictionaries for format-aware fuzzing
- Run longer campaigns (cycles_wo_finds indicates plateau)
- Try different mutation strategies with multi-core fuzzing
- Analyze coverage gaps and add targeted seed inputs
See Also: For detailed coverage analysis techniques, identifying coverage gaps, and systematic coverage improvement, see the coverage-analysis technique skill.
- 使用字典进行格式感知的模糊测试
- 运行更长时间的测试任务(cycles_wo_finds表示进入瓶颈)
- 在多核模糊测试中尝试不同的变异策略
- 分析覆盖范围缺口并添加针对性的种子输入
另请参阅: 有关详细的覆盖范围分析技巧、识别覆盖范围缺口和系统性提升覆盖范围的方法,请查看coverage-analysis技术文档。
CMPLOG
CMPLOG
CMPLOG/RedQueen is the best path constraint solving mechanism available in any fuzzer.
To enable it, the fuzz target needs to be instrumented for it.
Before building the fuzzing target set the environment variable:
bash
./afl++ <host/docker> AFL_LLVM_CMPLOG=1 makeNo special action is needed for compiling and linking the harness.
To run a fuzzer instance with a CMPLOG instrumented fuzzing target, add to the command like arguments:
-c0bash
./afl++ <host/docker> afl-fuzz -c0 -S cmplog -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &CMPLOG/RedQueen是目前所有模糊测试工具中最出色的路径约束求解机制。要启用它,需要对模糊测试目标进行插桩。在构建模糊测试目标之前,设置环境变量:
bash
./afl++ <host/docker> AFL_LLVM_CMPLOG=1 make编译和链接测试套不需要特殊操作。
要运行带有CMPLOG插桩的模糊测试目标实例,在命令参数中添加:
-c0bash
./afl++ <host/docker> afl-fuzz -c0 -S cmplog -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &Sanitizer Integration
Sanitizer集成
Sanitizers are essential for finding memory corruption bugs that don't cause immediate crashes.
Sanitizers对于发现不会立即导致崩溃的内存损坏漏洞至关重要。
AddressSanitizer (ASan)
AddressSanitizer (ASan)
bash
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzNote: Memory limit () is not supported with ASan due to 20TB virtual memory reservation.
-mbash
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz**注意:**由于ASan会保留20TB的虚拟内存,因此内存限制()在使用ASan时不被支持。
-mUndefinedBehaviorSanitizer (UBSan)
UndefinedBehaviorSanitizer (UBSan)
bash
./afl++ <host/docker> AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzzbash
./afl++ <host/docker> AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzzCommon Sanitizer Issues
Sanitizer常见问题
| Issue | Solution |
|---|---|
| ASan slows fuzzing | Use only 1 ASan job in multi-core setup |
| Stack exhaustion | Increase stack with |
| GCC version mismatch | Ensure system GCC matches AFL++ plugin version |
See Also: For comprehensive sanitizer configuration and troubleshooting, see the address-sanitizer technique skill.
| 问题 | 解决方案 |
|---|---|
| ASan降低模糊测试速度 | 在多核设置中仅使用1个ASan任务 |
| 栈溢出 | 使用 |
| GCC版本不匹配 | 确保系统GCC版本与AFL++插件版本一致 |
另请参阅: 有关Sanitizer的全面配置和故障排除,请查看address-sanitizer技术文档。
Advanced Usage
高级用法
Tips and Tricks
技巧与窍门
| Tip | Why It Helps |
|---|---|
| Use LLVMFuzzerTestOneInput harnesses where possible | If a fuzzing campaign has at least 85% stability then this is the most efficient fuzzing style. If not then try standard input or file input fuzzing |
| Use dictionaries | Helps fuzzer discover format-specific keywords and magic bytes |
| Set realistic timeouts | Prevents false positives from system load |
| Limit input size | Larger inputs don't necessarily explore more space |
| Monitor stability | Low stability indicates non-deterministic behavior |
| 技巧 | 优势 |
|---|---|
| 尽可能使用LLVMFuzzerTestOneInput风格的测试套 | 如果模糊测试任务的稳定性至少达到85%,这是最高效的模糊测试方式。如果稳定性不足,尝试通过标准输入或文件输入进行模糊测试 |
| 使用字典 | 帮助模糊测试工具发现特定格式的关键字和魔术字节 |
| 设置合理的超时时间 | 避免因系统负载导致的误报 |
| 限制输入大小 | 更大的输入不一定能探索更多空间 |
| 监控稳定性 | 低稳定性表示存在非确定性行为 |
Standard Input Fuzzing
标准输入模糊测试
AFL++ can fuzz programs reading from stdin without a libFuzzer harness:
bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_stdin.c -o fuzz_stdin
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_stdinThis is slower than persistent mode but requires no harness code.
AFL++可以对读取标准输入的程序进行模糊测试,无需libFuzzer测试套:
bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_stdin.c -o fuzz_stdin
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_stdin这种方式比持久模式慢,但不需要编写测试套代码。
File Input Fuzzing
文件输入模糊测试
For programs that read files, use placeholder:
@@bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_file.c -o fuzz_file
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_file @@For better performance, use to create file descriptors from memory.
fmemopen对于读取文件的程序,使用占位符:
@@bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_file.c -o fuzz_file
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_file @@为了获得更好的性能,使用从内存创建文件描述符。
fmemopenArgument Fuzzing
命令行参数模糊测试
Fuzz command-line arguments using :
argv-fuzz-inl.hc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __AFL_COMPILER
#include "argv-fuzz-inl.h"
#endif
void check_buf(char *buf, size_t buf_len) {
if(buf_len > 0 && buf[0] == 'a') {
if(buf_len > 1 && buf[1] == 'b') {
if(buf_len > 2 && buf[2] == 'c') {
abort();
}
}
}
}
int main(int argc, char *argv[]) {
#ifdef __AFL_COMPILER
AFL_INIT_ARGV();
#endif
if (argc < 2) {
fprintf(stderr, "Usage: %s <input_string>\n", argv[0]);
return 1;
}
char *input_buf = argv[1];
size_t len = strlen(input_buf);
check_buf(input_buf, len);
return 0;
}Download the header:
bash
curl -O https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/argv_fuzzing/argv-fuzz-inl.hCompile and run:
bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_arg.c -o fuzz_arg
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_arg使用对命令行参数进行模糊测试:
argv-fuzz-inl.hc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __AFL_COMPILER
#include "argv-fuzz-inl.h"
#endif
void check_buf(char *buf, size_t buf_len) {
if(buf_len > 0 && buf[0] == 'a') {
if(buf_len > 1 && buf[1] == 'b') {
if(buf_len > 2 && buf[2] == 'c') {
abort();
}
}
}
}
int main(int argc, char *argv[]) {
#ifdef __AFL_COMPILER
AFL_INIT_ARGV();
#endif
if (argc < 2) {
fprintf(stderr, "Usage: %s <input_string>\n", argv[0]);
return 1;
}
char *input_buf = argv[1];
size_t len = strlen(input_buf);
check_buf(input_buf, len);
return 0;
}下载头文件:
bash
curl -O https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/argv_fuzzing/argv-fuzz-inl.h编译并运行:
bash
./afl++ <host/docker> afl-clang-fast++ -O2 main_arg.c -o fuzz_arg
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_argPerformance Tuning
性能调优
| Setting | Impact |
|---|---|
| CPU core count | Linear scaling with physical cores |
| Persistent mode | 10-20x faster than fork server |
| Smaller = faster, but may miss bugs |
| ASan ratio | 1 ASan job per 4-8 non-ASan jobs |
| 设置 | 影响 |
|---|---|
| CPU核心数 | 与物理核心数线性扩展 |
| 持久模式 | 比fork服务器快10-20倍 |
| 越小=越快,但可能遗漏漏洞 |
| ASan比例 | 每4-8个非ASan任务对应1个ASan任务 |
Real-World Examples
实际案例
Example: libpng
示例:libpng
Fuzzing libpng demonstrates fuzzing a C project with static libraries:
bash
undefined对libpng进行模糊测试演示了如何对C静态库项目进行模糊测试:
bash
undefinedGet source
Get source
curl -L -O https://downloads.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar xf libpng-1.6.37.tar.xz
cd libpng-1.6.37/
curl -L -O https://downloads.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar xf libpng-1.6.37.tar.xz
cd libpng-1.6.37/
Install dependencies
Install dependencies
apt install zlib1g-dev
apt install zlib1g-dev
Configure and build static library
Configure and build static library
export CC=afl-clang-fast CFLAGS=-fsanitize=fuzzer-no-link
export CXX=afl-clang-fast++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
export AFL_LLVM_CMPLOG=1
export AFL_USE_ASAN=1
make
export CC=afl-clang-fast CFLAGS=-fsanitize=fuzzer-no-link
export CXX=afl-clang-fast++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
export AFL_LLVM_CMPLOG=1
export AFL_USE_ASAN=1
make
Download harness
Download harness
Link fuzzer
Link fuzzer
export AFL_USE_ASAN=1
$CXX -fsanitize=fuzzer libpng_read_fuzzer.cc .libs/libpng16.a -lz -o fuzz
export AFL_USE_ASAN=1
$CXX -fsanitize=fuzzer libpng_read_fuzzer.cc .libs/libpng16.a -lz -o fuzz
Prepare seeds and dictionary
Prepare seeds and dictionary
Start fuzzing
Start fuzzing
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
undefined./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
undefinedExample: CMake-based Project
示例:基于CMake的项目
cmake
project(BuggyProgram)
cmake_minimum_required(VERSION 3.0)
add_executable(buggy_program main.cc)
add_executable(fuzz main.cc harness.cc)
target_compile_definitions(fuzz PRIVATE NO_MAIN=1)
target_compile_options(fuzz PRIVATE -O2 -fsanitize=fuzzer-no-link)
target_link_libraries(fuzz -fsanitize=fuzzer)Build and fuzz:
bash
undefinedcmake
project(BuggyProgram)
cmake_minimum_required(VERSION 3.0)
add_executable(buggy_program main.cc)
add_executable(fuzz main.cc harness.cc)
target_compile_definitions(fuzz PRIVATE NO_MAIN=1)
target_compile_options(fuzz PRIVATE -O2 -fsanitize=fuzzer-no-link)
target_link_libraries(fuzz -fsanitize=fuzzer)构建并模糊测试:
bash
undefinedBuild non-instrumented binary
Build non-instrumented binary
./afl++ <host/docker> cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .
./afl++ <host/docker> cmake --build . --target buggy_program
./afl++ <host/docker> cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .
./afl++ <host/docker> cmake --build . --target buggy_program
Build fuzzer
Build fuzzer
./afl++ <host/docker> cmake -DCMAKE_C_COMPILER=afl-clang-fast -DCMAKE_CXX_COMPILER=afl-clang-fast++ .
./afl++ <host/docker> cmake --build . --target fuzz
./afl++ <host/docker> cmake -DCMAKE_C_COMPILER=afl-clang-fast -DCMAKE_CXX_COMPILER=afl-clang-fast++ .
./afl++ <host/docker> cmake --build . --target fuzz
Fuzz
Fuzz
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
undefined./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
undefinedTroubleshooting
故障排除
| Problem | Cause | Solution |
|---|---|---|
| Low exec/sec (<1k) | Not using persistent mode | Create a LLVMFuzzerTestOneInput style harness |
| Low stability (<85%) | Non-deterministic code | Fuzz a program via stdin or file inputs, or create such a harness |
| GCC plugin error | GCC version mismatch | Ensure system GCC matches AFL++ build and install gcc-$GCC_VERSION-plugin-dev |
| No crashes found | Need sanitizers | Recompile with |
| Memory limit exceeded | ASan uses 20TB virtual | Remove |
| Docker performance loss | Virtualization overhead | Use bare metal or VM for production fuzzing |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 低执行速度(<1k次/秒) | 未使用持久模式 | 创建LLVMFuzzerTestOneInput风格的测试套 |
| 低稳定性(<85%) | 代码存在非确定性 | 通过标准输入或文件输入对程序进行模糊测试,或创建此类测试套 |
| GCC插件错误 | GCC版本不匹配 | 确保系统GCC版本与AFL++构建版本一致,并安装gcc-$GCC_VERSION-plugin-dev |
| 未发现崩溃 | 需要使用Sanitizers | 使用 |
| 超出内存限制 | ASan使用20TB虚拟内存 | 使用ASan时移除 |
| Docker性能损失 | 虚拟化开销 | 使用裸机或虚拟机进行生产环境模糊测试 |
Related Skills
相关技术文档
Technique Skills
技术技巧文档
| Skill | Use Case |
|---|---|
| fuzz-harness-writing | Detailed guidance on writing effective harnesses |
| address-sanitizer | Memory error detection during fuzzing |
| undefined-behavior-sanitizer | Detect undefined behavior bugs |
| fuzzing-corpus | Building and managing seed corpora |
| fuzzing-dictionaries | Creating dictionaries for format-aware fuzzing |
| 文档 | 适用场景 |
|---|---|
| fuzz-harness-writing | 编写高效测试套的详细指南 |
| address-sanitizer | 模糊测试期间的内存错误检测 |
| undefined-behavior-sanitizer | 检测未定义行为漏洞 |
| fuzzing-corpus | 构建和管理种子测试用例库 |
| fuzzing-dictionaries | 创建格式感知的模糊测试字典 |
Related Fuzzers
相关模糊测试工具
| Skill | When to Consider |
|---|---|
| libfuzzer | Quick prototyping, single-threaded fuzzing is sufficient |
| libafl | Need custom mutators or research-grade features |
| 文档 | 适用场景 |
|---|---|
| libfuzzer | 快速原型开发、单线程模糊测试足够的场景 |
| libafl | 需要自定义变异器或研究级功能的场景 |
Resources
资源
Key External Resources
关键外部资源
AFL++ GitHub Repository
Official repository with comprehensive documentation, examples, and issue tracker.
Fuzzing in Depth
Advanced documentation by the AFL++ team covering instrumentation modes, optimization techniques, and advanced use cases.
AFL++ Under The Hood
Technical deep-dive into AFL++ internals, mutation strategies, and coverage tracking mechanisms.
AFL++: Combining Incremental Steps of Fuzzing Research
Research paper describing AFL++ architecture and performance improvements over original AFL.
AFL++ GitHub仓库
官方仓库,包含全面的文档、示例和问题追踪系统。
Fuzzing in Depth
AFL++团队编写的高级文档,涵盖插桩模式、优化技巧和高级使用场景。
AFL++ Under The Hood
关于AFL++内部机制、变异策略和覆盖范围跟踪机制的技术深度解析。
AFL++: Combining Incremental Steps of Fuzzing Research
描述AFL++架构和相比原生AFL的性能提升的研究论文。
Video Resources
视频资源
- Fuzzing cURL - Trail of Bits blog post on using AFL++ argument fuzzing for cURL
- Sudo Vulnerability Walkthrough - LiveOverflow series on rediscovering CVE-2021-3156
- Rediscovery of libpng bug - LiveOverflow video on finding CVE-2023-4863
- Fuzzing cURL - Trail of Bits的博客文章,介绍如何使用AFL++对cURL进行参数模糊测试
- Sudo Vulnerability Walkthrough - LiveOverflow的系列视频,重现CVE-2021-3156漏洞的发现过程
- Rediscovery of libpng bug - LiveOverflow的视频,演示如何发现CVE-2023-4863漏洞