aflpp by trailofbits/skills
npx skills add https://github.com/trailofbits/skills --skill aflppAFL++ 是原始 AFL 模糊测试工具的一个分支,它在保持稳定性的同时提供了更好的模糊测试性能和更高级的功能。相比于 libFuzzer 的一个主要优势是,AFL++ 对在多核上运行模糊测试活动提供了稳定的支持,使其成为大规模模糊测试工作的理想选择。
| 模糊测试工具 | 最适合的场景 | 复杂度 |
|---|---|---|
| AFL++ | 多核模糊测试、多样化变异、成熟项目 | 中等 |
| libFuzzer | 快速设置、单线程、简单的测试驱动 | 低 |
| LibAFL | 自定义模糊测试工具、研究、高级用例 | 高 |
在以下情况选择 AFL++:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 使用模糊测试器提供的数据调用您的代码
check_buf((char*)data, size);
return 0;
}
编译并运行:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
# 首先设置 AFL++ 包装脚本(参见安装部分)
./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
AFL++ 有许多依赖项,包括 LLVM、Python 和 Rust。我们建议使用当前的 Debian 或 Ubuntu 发行版来运行 AFL++ 进行模糊测试。
| 方法 | 何时使用 | 支持的编译器 |
|---|---|---|
| Ubuntu/Debian 软件源 | 最近的 Ubuntu,仅提供基本功能 | Ubuntu 23.10:Clang 14 和 GCC 13Debian 12:Clang 14 和 GCC 12 |
| Docker(来自 Docker Hub) | 特定的 AFL++ 版本,支持 Apple Silicon | 截至 4.35c:Clang 19 和 GCC 11 |
| Docker(从源代码构建) | 测试未发布的功能,应用补丁 | 可在 Dockerfile 中配置 |
| 从源代码构建 | 避免使用 Docker,需要特定补丁 | 通过 LLVM_CONFIG 环境变量调整 |
在安装 afl++ 之前,使用 apt-cache show afl++ 检查软件包的 clang 版本依赖,并安装匹配的 lld 版本(例如 lld-17)。
apt install afl++ lld-17
docker pull aflplusplus/aflplusplus:stable
git clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .
参考 Dockerfile 了解 Ubuntu 版本要求和依赖项。设置 LLVM_CONFIG 以指定 Clang 版本(例如 llvm-config-18)。
创建一个包装脚本,以便在主机或 Docker 上运行 AFL++:
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++
安全警告: afl-system-config 和 afl-persistent-config 脚本需要 root 权限并会禁用操作系统的安全功能。请勿在生产系统或您的开发环境中进行模糊测试。请改用专用的虚拟机。
每次重启后运行,每秒执行次数最多可提升 15%:
./afl++ <host/docker> afl-system-config
为了获得最佳性能,禁用内核安全缓解措施(需要 grub 引导加载程序,Docker 不支持):
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ <host/docker> afl-system-config
使用 cat /proc/cmdline 验证 - 输出应包含 mitigations=off。
AFL++ 支持 libFuzzer 风格的测试驱动:
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. 如果需要,验证输入大小
if (size < MIN_SIZE || size > MAX_SIZE) return 0;
// 2. 使用模糊测试数据调用目标函数
target_function(data, size);
// 3. 返回 0(非零值保留供将来使用)
return 0;
}
| 应该做 | 不应该做 |
|---|---|
| 在每次运行之间重置全局状态 | 依赖之前运行的状态 |
| 优雅地处理边缘情况 | 在无效输入时退出 |
| 保持测试驱动的确定性 | 使用随机数生成器 |
| 释放已分配的内存 | 造成内存泄漏 |
| 验证输入大小 | 处理无限制的输入 |
另请参阅: 关于详细的测试驱动编写技术、处理复杂输入的模式以及高级策略,请参阅 fuzz-harness-writing 技术技能。
AFL++ 提供多种编译模式,各有不同的权衡。
选择您的编译模式:
afl-clang-lto):最佳性能和插桩。首先尝试此模式。afl-clang-fast):如果 LTO 编译失败,则回退到此模式。afl-gcc-fast):适用于需要 GCC 的项目。./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
./afl++ <host/docker> afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
重要提示: GCC 版本必须与编译 AFL++ GCC 插件时使用的版本匹配。
./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 技术技能。
请注意,-g 不是必需的,它默认由 AFL++ 编译器添加。
| 标志 | 用途 |
|---|---|
-DNO_MAIN=1 | 使用 libFuzzer 测试驱动时跳过主函数 |
-O2 | 生产优化级别(推荐用于模糊测试) |
-fsanitize=fuzzer | 启用 libFuzzer 兼容模式,并在链接可执行文件时添加模糊测试器运行时 |
-fsanitize=fuzzer-no-link | 插桩但不链接模糊测试器运行时(用于静态库和目标文件) |
AFL++ 至少需要一个非空的种子文件:
mkdir seeds
echo "aaaa" > seeds/minimal_seed
对于实际项目,收集有代表性的输入:
活动结束后,最小化语料库以仅保留唯一的覆盖率:
./afl++ <host/docker> afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzz
另请参阅: 关于语料库创建策略、字典和种子选择,请参阅 fuzzing-corpus 技术技能。
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz
AFL++ UI 显示实时模糊测试统计信息:
| 输出 | 含义 |
|---|---|
| execs/sec | 执行速度 - 越高越好 |
| cycles done | 完成的队列遍历次数 |
| corpus count | 队列中唯一的测试用例数量 |
| saved crashes | 发现的唯一崩溃数量 |
| stability | 稳定边的百分比(应接近 100%) |
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 # 用于绘图的数据
查看实时活动统计信息:
./afl++ <host/docker> afl-whatsup out
创建覆盖率图表:
apt install gnuplot
./afl++ <host/docker> afl-plot out/default out_graph/
./afl++ <host/docker> ./fuzz out/default/crashes/<test_case>
| 选项 | 用途 |
|---|---|
-G 4000 | 最大测试输入长度(默认:1048576 字节) |
-t 1000 | 每个测试用例的超时时间(毫秒)(默认:1000ms) |
-m 1000 | 内存限制(兆字节)(默认:0 = 无限制) |
-x ./dict.dict | 使用字典文件指导变异 |
AFL++ 在多核模糊测试方面表现出色,具有两大优势:
启动主模糊测试器(在后台):
./afl++ <host/docker> afl-fuzz -M primary -i seeds -o state -- ./fuzz 1>primary.log 2>primary.error &
启动辅助模糊测试器(数量与您的核心数相同):
./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 &
列出所有正在运行的任务:
jobs
查看实时统计信息(每秒更新):
./afl++ <host/docker> watch -n1 --color afl-whatsup state/
kill $(jobs -p)
AFL++ 通过边插桩自动跟踪覆盖率。覆盖率信息存储在 fuzzer_stats 和 plot_data 中。
使用 afl-plot 可视化随时间变化的覆盖率:
./afl++ <host/docker> afl-plot out/default out_graph/
另请参阅: 关于详细的覆盖率分析技术、识别覆盖率差距以及系统性地提高覆盖率,请参阅 coverage-analysis 技术技能。
CMPLOG/RedQueen 是所有模糊测试工具中可用的最佳路径约束解决机制。要启用它,需要为模糊测试目标进行相应的插桩。在构建模糊测试目标之前,设置环境变量:
./afl++ <host/docker> AFL_LLVM_CMPLOG=1 make
编译和链接测试驱动时无需特殊操作。
要使用 CMPLOG 插桩的模糊测试目标运行模糊测试器实例,请在命令参数中添加 -c0:
./afl++ <host/docker> afl-fuzz -c0 -S cmplog -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &
Sanitizers 对于发现不会导致立即崩溃的内存损坏错误至关重要。
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
注意: 由于 20TB 的虚拟内存预留,ASan 不支持内存限制 (-m)。
./afl++ <host/docker> AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzz
| 问题 | 解决方案 |
|---|---|
| ASan 减慢模糊测试速度 | 在多核设置中仅使用 1 个 ASan 任务 |
| 堆栈耗尽 | 使用 ASAN_OPTIONS=stack_size=... 增加堆栈大小 |
| GCC 版本不匹配 | 确保系统 GCC 与 AFL++ 插件版本匹配 |
另请参阅: 关于全面的 sanitizer 配置和故障排除,请参阅 address-sanitizer 技术技能。
| 技巧 | 为何有帮助 |
|---|---|
| 尽可能使用 LLVMFuzzerTestOneInput 测试驱动 | 如果模糊测试活动的稳定性至少达到 85%,那么这是最高效的模糊测试风格。否则,尝试标准输入或文件输入模糊测试 |
| 使用字典 | 帮助模糊测试器发现特定格式的关键字和魔术字节 |
| 设置合理的超时时间 | 防止系统负载导致的误报 |
| 限制输入大小 | 更大的输入不一定能探索更多空间 |
| 监控稳定性 | 低稳定性表明存在非确定性行为 |
AFL++ 可以模糊测试从 stdin 读取的程序,而无需 libFuzzer 测试驱动:
./afl++ <host/docker> afl-clang-fast++ -O2 main_stdin.c -o fuzz_stdin
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_stdin
这比持久模式慢,但不需要测试驱动代码。
对于读取文件的程序,使用 @@ 占位符:
./afl++ <host/docker> afl-clang-fast++ -O2 main_file.c -o fuzz_file
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_file @@
为了获得更好的性能,使用 fmemopen 从内存创建文件描述符。
使用 argv-fuzz-inl.h 模糊测试命令行参数:
#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;
}
下载头文件:
curl -O https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/argv_fuzzing/argv-fuzz-inl.h
编译并运行:
./afl++ <host/docker> afl-clang-fast++ -O2 main_arg.c -o fuzz_arg
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_arg
| 设置 | 影响 |
|---|---|
| CPU 核心数量 | 随物理核心数量线性扩展 |
| 持久模式 | 比 fork 服务器快 10-20 倍 |
-G 输入大小限制 | 越小越快,但可能错过错误 |
| ASan 比例 | 每 4-8 个非 ASan 任务对应 1 个 ASan 任务 |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 低 exec/sec (<1k) | 未使用持久模式 | 创建一个 LLVMFuzzerTestOneInput 风格的测试驱动 |
| 低稳定性 (<85%) | 非确定性代码 | 通过 stdin 或文件输入对程序进行模糊测试,或创建此类测试驱动 |
| GCC 插件错误 | GCC 版本不匹配 | 确保系统 GCC 与 AFL++ 构建版本匹配,并安装 gcc-$GCC_VERSION-plugin-dev |
| 未发现崩溃 | 需要 sanitizers | 使用 AFL_USE_ASAN=1 重新编译 |
| 超出内存限制 | ASan 使用 20TB 虚拟内存 | 使用 ASan 时移除 -m 标志 |
| Docker 性能损失 | 虚拟化开销 | 对于生产环境模糊测试,使用裸机或虚拟机 |
| 技能 | 用例 |
|---|---|
| fuzz-harness-writing | 编写有效测试驱动的详细指南 |
| address-sanitizer | 模糊测试期间的内存错误检测 |
| undefined-behavior-sanitizer | 检测未定义行为错误 |
| fuzzing-corpus | 构建和管理种子语料库 |
| fuzzing-dictionaries | 为格式感知模糊测试创建字典 |
| 技能 | 何时考虑 |
|---|---|
| libfuzzer | 快速原型设计,单线程模糊测试足够 |
| libafl | 需要自定义变异器或研究级功能 |
AFL++ GitHub 仓库 官方仓库,包含全面的文档、示例和问题跟踪器。
深入模糊测试 AFL++ 团队提供的高级文档,涵盖插桩模式、优化技术和高级用例。
AFL++ 内部机制 对 AFL++ 内部机制、变异策略和覆盖率跟踪机制的技术深度解析。
AFL++:结合模糊测试研究的增量步骤 描述 AFL++ 架构以及相对于原始 AFL 的性能改进的研究论文。
每周安装量
1.1K
仓库
GitHub 星标数
3.9K
首次出现
Jan 19, 2026
安全审计
安装于
claude-code990
opencode940
gemini-cli923
codex918
cursor895
github-copilot865
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.
| 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:
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:
# 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
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 13Debian 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 LLVM_CONFIG env var |
Prior to installing afl++, check the clang version dependency of the packge with apt-cache show afl++, and install the matching lld version (e.g., lld-17).
apt install afl++ lld-17
docker pull aflplusplus/aflplusplus:stable
git clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .
Refer to the Dockerfile for Ubuntu version requirements and dependencies. Set LLVM_CONFIG to specify Clang version (e.g., llvm-config-18).
Create a wrapper script to run AFL++ on host or Docker:
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 afl-system-config and afl-persistent-config scripts require root privileges and disable OS security features. Do not fuzz on production systems or your development environment. Use a dedicated VM instead.
Run after each reboot for up to 15% more executions per second:
./afl++ <host/docker> afl-system-config
For maximum performance, disable kernel security mitigations (requires grub bootloader, not supported in Docker):
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ <host/docker> afl-system-config
Verify with cat /proc/cmdline - output should include mitigations=off.
AFL++ supports libFuzzer-style harnesses:
#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;
}
| 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.
AFL++ offers multiple compilation modes with different trade-offs.
Choose your compilation mode:
afl-clang-lto): Best performance and instrumentation. Try this first.afl-clang-fast): Fall back if LTO fails to compile.afl-gcc-fast): For projects requiring GCC../afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
./afl++ <host/docker> afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
Important: GCC version must match the version used to compile the AFL++ GCC plugin.
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
See Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
Note that -g is not necessary, it is added by default by the AFL++ compilers.
| Flag | Purpose |
|---|---|
-DNO_MAIN=1 | Skip main function when using libFuzzer harness |
-O2 | Production optimization level (recommended for fuzzing) |
-fsanitize=fuzzer | Enable libFuzzer compatibility mode and adds the fuzzer runtime when linking executable |
-fsanitize=fuzzer-no-link | Instrument without linking fuzzer runtime (for static libraries and object files) |
AFL++ requires at least one non-empty seed file:
mkdir seeds
echo "aaaa" > seeds/minimal_seed
For real projects, gather representative inputs:
After a campaign, minimize the corpus to keep only unique coverage:
./afl++ <host/docker> afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzz
See Also: For corpus creation strategies, dictionaries, and seed selection, see the fuzzing-corpus technique skill.
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz
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%) |
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 plotting
View live campaign statistics:
./afl++ <host/docker> afl-whatsup out
Create coverage plots:
apt install gnuplot
./afl++ <host/docker> afl-plot out/default out_graph/
./afl++ <host/docker> ./fuzz out/default/crashes/<test_case>
| Option | Purpose |
|---|---|
-G 4000 | Maximum test input length (default: 1048576 bytes) |
-t 1000 | Timeout in milliseconds for each test case (default: 1000ms) |
-m 1000 | Memory limit in megabytes (default: 0 = unlimited) |
-x ./dict.dict | Use dictionary file to guide mutations |
AFL++ excels at multi-core fuzzing with two major advantages:
Start the primary fuzzer (in background):
./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):
./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 &
List all running jobs:
jobs
View live statistics (updates every second):
./afl++ <host/docker> watch -n1 --color afl-whatsup state/
kill $(jobs -p)
AFL++ automatically tracks coverage through edge instrumentation. Coverage information is stored in fuzzer_stats and plot_data.
Use afl-plot to visualize coverage over time:
./afl++ <host/docker> afl-plot out/default out_graph/
See Also: For detailed coverage analysis techniques, identifying coverage gaps, and systematic coverage improvement, see the coverage-analysis technique skill.
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:
./afl++ <host/docker> AFL_LLVM_CMPLOG=1 make
No special action is needed for compiling and linking the harness.
To run a fuzzer instance with a CMPLOG instrumented fuzzing target, add -c0 to the command like arguments:
./afl++ <host/docker> afl-fuzz -c0 -S cmplog -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error &
Sanitizers are essential for finding memory corruption bugs that don't cause immediate crashes.
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
Note: Memory limit (-m) is not supported with ASan due to 20TB virtual memory reservation.
./afl++ <host/docker> AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzz
| Issue | Solution |
|---|---|
| ASan slows fuzzing | Use only 1 ASan job in multi-core setup |
| Stack exhaustion | Increase stack with ASAN_OPTIONS=stack_size=... |
| GCC version mismatch | Ensure system GCC matches AFL++ plugin version |
See Also: For comprehensive sanitizer configuration and troubleshooting, see the address-sanitizer technique skill.
| 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 |
AFL++ can fuzz programs reading from stdin without a libFuzzer harness:
./afl++ <host/docker> afl-clang-fast++ -O2 main_stdin.c -o fuzz_stdin
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_stdin
This is slower than persistent mode but requires no harness code.
For programs that read files, use @@ placeholder:
./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 fmemopen to create file descriptors from memory.
Fuzz command-line arguments using argv-fuzz-inl.h:
#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:
curl -O https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/argv_fuzzing/argv-fuzz-inl.h
Compile and run:
./afl++ <host/docker> afl-clang-fast++ -O2 main_arg.c -o fuzz_arg
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz_arg
| Setting | Impact |
|---|---|
| CPU core count | Linear scaling with physical cores |
| Persistent mode | 10-20x faster than fork server |
-G input size limit | Smaller = faster, but may miss bugs |
| ASan ratio | 1 ASan job per 4-8 non-ASan jobs |
| 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 AFL_USE_ASAN=1 |
| Memory limit exceeded | ASan uses 20TB virtual | Remove -m flag when using ASan |
| Docker performance loss | Virtualization overhead | Use bare metal or VM for production fuzzing |
| 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 |
| Skill | When to Consider |
|---|---|
| libfuzzer | Quick prototyping, single-threaded fuzzing is sufficient |
| libafl | Need custom mutators or research-grade features |
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.
Weekly Installs
1.1K
Repository
GitHub Stars
3.9K
First Seen
Jan 19, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code990
opencode940
gemini-cli923
codex918
cursor895
github-copilot865
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装