aflpp

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AFL++

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

适用场景

FuzzerBest ForComplexity
AFL++Multi-core fuzzing, diverse mutations, mature projectsMedium
libFuzzerQuick setup, single-threaded, simple harnessesLow
LibAFLCustom fuzzers, research, advanced use casesHigh
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
undefined
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;
}
编译并运行:
bash
undefined

Setup 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
undefined

Installation

安装

AFL++ has many dependencies including LLVM, Python, and Rust. We recommend using a current Debian or Ubuntu distribution for fuzzing with AFL++.
MethodWhen to UseSupported Compilers
Ubuntu/Debian reposRecent Ubuntu, basic features onlyUbuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12
Docker (from Docker Hub)Specific AFL++ version, Apple Silicon supportAs of 4.35c: Clang 19 & GCC 11
Docker (from source)Test unreleased features, apply patchesConfigurable in Dockerfile
From sourceAvoid Docker, need specific patchesAdjustable via
LLVM_CONFIG
env var
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、需要特定补丁通过
LLVM_CONFIG
环境变量调整

Ubuntu/Debian

Ubuntu/Debian

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
).
bash
apt install afl++ lld-17
在安装afl++之前,使用
apt-cache show afl++
检查软件包的Clang版本依赖,并安装匹配的
lld
版本(例如
lld-17
)。
bash
apt install afl++ lld-17

Docker (from Docker Hub)

Docker(来自Docker Hub)

bash
docker pull aflplusplus/aflplusplus:stable
bash
docker pull aflplusplus/aflplusplus:stable

Docker (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
LLVM_CONFIG
to specify Clang version (e.g.,
llvm-config-18
).
参考Dockerfile了解Ubuntu版本要求和依赖项。设置
LLVM_CONFIG
以指定Clang版本(例如
llvm-config-18
)。

Wrapper 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
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.
创建一个包装器脚本以在主机或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++
安全警告:
afl-system-config
afl-persistent-config
脚本需要root权限,并且会禁用操作系统安全功能。不要在生产系统或开发环境中进行模糊测试,请使用专用虚拟机替代。

System Configuration

系统配置

Run after each reboot for up to 15% more executions per second:
bash
./afl++ <host/docker> afl-system-config
For 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-config
Verify with
cat /proc/cmdline
- output should include
mitigations=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/cmdline
验证 - 输出应包含
mitigations=off

Writing 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

测试套规则

DoDon't
Reset global state between runsRely on state from previous runs
Handle edge cases gracefullyExit on invalid input
Keep harness deterministicUse random number generators
Free allocated memoryCreate memory leaks
Validate input sizesProcess 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 (
    afl-clang-lto
    ): Best performance and instrumentation. Try this first.
  • LLVM mode (
    afl-clang-fast
    ): Fall back if LTO fails to compile.
  • GCC plugin (
    afl-gcc-fast
    ): For projects requiring GCC.
选择你的编译模式:
  • LTO模式 (
    afl-clang-lto
    ): 最佳性能和插桩效果,优先尝试此模式。
  • LLVM模式 (
    afl-clang-fast
    ): 如果LTO编译失败,可回退到此模式。
  • GCC插件模式 (
    afl-gcc-fast
    ): 适用于需要GCC编译的项目。

Basic Compilation (LLVM mode)

基础编译(LLVM模式)

bash
./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
bash
./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz

GCC Compilation

GCC编译

bash
./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.
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 fuzz
See 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-sanitizerundefined-behavior-sanitizer技术文档。

Build Flags

构建标志

Note that
-g
is not necessary, it is added by default by the AFL++ compilers.
FlagPurpose
-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)
注意
-g
不是必需的,AFL++编译器会默认添加此标志。
标志用途
-DNO_MAIN=1
使用libFuzzer测试套时跳过main函数
-O2
生产环境优化级别(推荐用于模糊测试)
-fsanitize=fuzzer
启用libFuzzer兼容模式,并在链接可执行文件时添加模糊测试运行时
-fsanitize=fuzzer-no-link
插桩但不链接模糊测试运行时(适用于静态库和目标文件)

Corpus Management

测试用例库管理

Creating Initial Corpus

创建初始测试用例库

AFL++ requires at least one non-empty seed file:
bash
mkdir seeds
echo "aaaa" > seeds/minimal_seed
For 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 -- ./fuzz
See 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 -- ./fuzz
bash
./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz

Setting Environment Variables

设置环境变量

bash
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz
bash
./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz

Interpreting Output

输出解读

The AFL++ UI shows real-time fuzzing statistics:
OutputMeaning
execs/secExecution speed - higher is better
cycles doneNumber of queue passes completed
corpus countNumber of unique test cases in queue
saved crashesNumber 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 plotting
text
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 out
Create 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

模糊测试工具选项

OptionPurpose
-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
选项用途
-G 4000
测试输入的最大长度(默认:1048576字节)
-t 1000
每个测试用例的超时时间(毫秒,默认:1000ms)
-m 1000
内存限制(兆字节,默认:0=无限制)
-x ./dict.dict
使用字典文件指导变异操作

Multi-Core Fuzzing

多核模糊测试

AFL++ excels at multi-core fuzzing with two major advantages:
  1. More executions per second (scales linearly with physical cores)
  2. Asymmetrical fuzzing (e.g., one ASan job, rest without sanitizers)
AFL++在多核模糊测试方面表现出色,具有两大优势:
  1. 更高的每秒执行次数(与物理核心数线性扩展)
  2. 非对称模糊测试(例如,一个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
jobs
View 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
fuzzer_stats
and
plot_data
.
AFL++通过边插桩自动跟踪覆盖范围,覆盖范围信息存储在
fuzzer_stats
plot_data
中。

Measuring Coverage

测量覆盖范围

Use
afl-plot
to visualize coverage over time:
bash
./afl++ <host/docker> afl-plot out/default out_graph/
使用
afl-plot
可视化随时间变化的覆盖范围:
bash
./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 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:
bash
./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插桩的模糊测试目标实例,在命令参数中添加
-c0
bash
./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 fuzz
Note: Memory limit (
-m
) is not supported with ASan due to 20TB virtual memory reservation.
bash
./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
**注意:**由于ASan会保留20TB的虚拟内存,因此内存限制(
-m
)在使用ASan时不被支持。

UndefinedBehaviorSanitizer (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 fuzz
bash
./afl++ <host/docker> AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzz

Common Sanitizer Issues

Sanitizer常见问题

IssueSolution
ASan slows fuzzingUse only 1 ASan job in multi-core setup
Stack exhaustionIncrease stack with
ASAN_OPTIONS=stack_size=...
GCC version mismatchEnsure system GCC matches AFL++ plugin version
See Also: For comprehensive sanitizer configuration and troubleshooting, see the address-sanitizer technique skill.
问题解决方案
ASan降低模糊测试速度在多核设置中仅使用1个ASan任务
栈溢出使用
ASAN_OPTIONS=stack_size=...
增加栈大小
GCC版本不匹配确保系统GCC版本与AFL++插件版本一致
另请参阅: 有关Sanitizer的全面配置和故障排除,请查看address-sanitizer技术文档。

Advanced Usage

高级用法

Tips and Tricks

技巧与窍门

TipWhy It Helps
Use LLVMFuzzerTestOneInput harnesses where possibleIf 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 dictionariesHelps fuzzer discover format-specific keywords and magic bytes
Set realistic timeoutsPrevents false positives from system load
Limit input sizeLarger inputs don't necessarily explore more space
Monitor stabilityLow 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_stdin
This 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
fmemopen
to create file descriptors from memory.
对于读取文件的程序,使用
@@
占位符:
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 @@
为了获得更好的性能,使用
fmemopen
从内存创建文件描述符。

Argument Fuzzing

命令行参数模糊测试

Fuzz command-line arguments using
argv-fuzz-inl.h
:
c
#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.h
Compile 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.h
对命令行参数进行模糊测试:
c
#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_arg

Performance Tuning

性能调优

SettingImpact
CPU core countLinear scaling with physical cores
Persistent mode10-20x faster than fork server
-G
input size limit
Smaller = faster, but may miss bugs
ASan ratio1 ASan job per 4-8 non-ASan jobs
设置影响
CPU核心数与物理核心数线性扩展
持久模式比fork服务器快10-20倍
-G
输入大小限制
越小=越快,但可能遗漏漏洞
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
undefined

Get 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
undefined

Example: 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
undefined
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)
构建并模糊测试:
bash
undefined

Build 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
undefined

Troubleshooting

故障排除

ProblemCauseSolution
Low exec/sec (<1k)Not using persistent modeCreate a LLVMFuzzerTestOneInput style harness
Low stability (<85%)Non-deterministic codeFuzz a program via stdin or file inputs, or create such a harness
GCC plugin errorGCC version mismatchEnsure system GCC matches AFL++ build and install gcc-$GCC_VERSION-plugin-dev
No crashes foundNeed sanitizersRecompile with
AFL_USE_ASAN=1
Memory limit exceededASan uses 20TB virtualRemove
-m
flag when using ASan
Docker performance lossVirtualization overheadUse bare metal or VM for production fuzzing
问题原因解决方案
低执行速度(<1k次/秒)未使用持久模式创建LLVMFuzzerTestOneInput风格的测试套
低稳定性(<85%)代码存在非确定性通过标准输入或文件输入对程序进行模糊测试,或创建此类测试套
GCC插件错误GCC版本不匹配确保系统GCC版本与AFL++构建版本一致,并安装gcc-$GCC_VERSION-plugin-dev
未发现崩溃需要使用Sanitizers使用
AFL_USE_ASAN=1
重新编译
超出内存限制ASan使用20TB虚拟内存使用ASan时移除
-m
标志
Docker性能损失虚拟化开销使用裸机或虚拟机进行生产环境模糊测试

Related Skills

相关技术文档

Technique Skills

技术技巧文档

SkillUse Case
fuzz-harness-writingDetailed guidance on writing effective harnesses
address-sanitizerMemory error detection during fuzzing
undefined-behavior-sanitizerDetect undefined behavior bugs
fuzzing-corpusBuilding and managing seed corpora
fuzzing-dictionariesCreating dictionaries for format-aware fuzzing
文档适用场景
fuzz-harness-writing编写高效测试套的详细指南
address-sanitizer模糊测试期间的内存错误检测
undefined-behavior-sanitizer检测未定义行为漏洞
fuzzing-corpus构建和管理种子测试用例库
fuzzing-dictionaries创建格式感知的模糊测试字典

Related Fuzzers

相关模糊测试工具

SkillWhen to Consider
libfuzzerQuick prototyping, single-threaded fuzzing is sufficient
libaflNeed 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

视频资源