Integrates AFL++ coverage-guided fuzz testing into CI/CD pipelines for C/C++ and compiled apps to detect memory corruption, input handling, and logic vulnerabilities.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
AFL++(American Fuzzy Lop Plus Plus)是 AFL 的社区维护分支,为发现编译型应用中的漏洞提供最先进的覆盖率引导模糊测试。AFL++ 使用遗传算法变异输入,跟踪代码覆盖率以寻找触发崩溃、挂起和未定义行为的新执行路径。在 CI/CD 环境中,AFL++ 可以集成到持续测试解析器、协议处理程序、文件格式处理器以及任何处理不受信任输入的代码中。AFL++ 支持持久模式以实现高速模糊测试(每秒超过 100,000 次执行)、自定义变异器、用于纯二进制模糊测试的 QEMU 模式以及用于自动字典提取的 CmpLog/RedQueen。
Integrates AFL++ coverage-guided fuzz testing into CI/CD pipelines to discover memory corruption, input handling, and logic vulnerabilities in C/C++ and compiled applications.
Integrates AFL++ coverage-guided fuzz testing into CI/CD pipelines for C/C++ and compiled apps to detect memory corruption, input handling, and logic vulnerabilities.
Executes coverage-guided fuzzing with AFL++ on compiled binaries to discover memory corruption, crashes, and security vulnerabilities. Covers instrumentation with afl-cc, corpus management via afl-cmin/afl-tmin, parallel fuzzing, and crash triage using CASR/GDB.
Share bugs, ideas, or general feedback.
AFL++(American Fuzzy Lop Plus Plus)是 AFL 的社区维护分支,为发现编译型应用中的漏洞提供最先进的覆盖率引导模糊测试。AFL++ 使用遗传算法变异输入,跟踪代码覆盖率以寻找触发崩溃、挂起和未定义行为的新执行路径。在 CI/CD 环境中,AFL++ 可以集成到持续测试解析器、协议处理程序、文件格式处理器以及任何处理不受信任输入的代码中。AFL++ 支持持久模式以实现高速模糊测试(每秒超过 100,000 次执行)、自定义变异器、用于纯二进制模糊测试的 QEMU 模式以及用于自动字典提取的 CmpLog/RedQueen。
apt install aflplusplus 或从源码构建)AFL++ 在编译时(或通过 QEMU/Frida 对纯二进制目标)对目标二进制文件进行插桩,以跟踪每个输入执行了哪些代码路径。当变异输入触发新的代码路径时,它会被保存到语料库中以供进一步变异。这种反馈循环使 AFL++ 能够系统地探索程序状态空间。
| 模式 | 使用场景 | 性能 |
|---|---|---|
afl-clang-fast(LTO) | 有源码,最佳性能 | 最高 |
afl-clang-fast | 有源码,标准 | 高 |
afl-gcc-fast | GCC 项目 | 高 |
QEMU 模式 | 纯二进制,无源码 | 中 |
Frida 模式 | 纯二进制,跨平台 | 中 |
Unicorn 模式 | 固件,嵌入式 | 低 |
持久模式通过在循环中进行模糊测试来避免 fork 开销:
#include <unistd.h>
__AFL_FUZZ_INIT();
int main() {
__AFL_INIT();
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(10000)) {
int len = __AFL_FUZZ_TESTCASE_LEN;
// Process buf[0..len-1]
parse_input(buf, len);
}
return 0;
}
创建一个将 AFL++ 输入传递给目标函数的测试线束:
// fuzz_harness.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "target_parser.h"
__AFL_FUZZ_INIT();
int main() {
__AFL_INIT();
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(10000)) {
int len = __AFL_FUZZ_TESTCASE_LEN;
if (len < 4) continue;
// Reset state between iterations
parser_context_t ctx;
parser_init(&ctx);
parser_process(&ctx, buf, len);
parser_cleanup(&ctx);
}
return 0;
}
# 标准插桩
export CC=afl-clang-fast
export CXX=afl-clang-fast++
# 启用 AddressSanitizer 以更好地检测崩溃
export AFL_USE_ASAN=1
# 使用插桩构建目标
$CC -o fuzz_harness fuzz_harness.c -ltarget_parser -fsanitize=address
# 构建 CmpLog 二进制文件以获得更好的覆盖率
$CC -o fuzz_harness_cmplog fuzz_harness.c -ltarget_parser \
-fsanitize=address -DCMPLOG
mkdir -p corpus/
# 添加有效输入样本
cp test_inputs/* corpus/
# 最小化语料库
afl-cmin -i corpus/ -o corpus_min/ -- ./fuzz_harness @@
# 进一步最小化单个输入
mkdir -p corpus_tmin/
for f in corpus_min/*; do
afl-tmin -i "$f" -o "corpus_tmin/$(basename $f)" -- ./fuzz_harness @@
done
GitHub Actions:
name: Fuzz Testing
on:
push:
branches: [main]
schedule:
- cron: '0 2 * * *' # 每夜模糊测试
jobs:
fuzz:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- name: Install AFL++
run: |
sudo apt-get update
sudo apt-get install -y aflplusplus
- name: Restore corpus cache
uses: actions/cache@v4
with:
path: corpus/
key: fuzz-corpus-${{ github.sha }}
restore-keys: fuzz-corpus-
- name: Build fuzzing harness
run: |
export CC=afl-clang-fast
export AFL_USE_ASAN=1
make fuzz_harness
- name: Run AFL++ fuzzing (CI mode)
env:
AFL_CMPLOG_ONLY_NEW: 1
AFL_FAST_CAL: 1
AFL_NO_STARTUP_CALIBRATION: 1
run: |
mkdir -p findings/
timeout 7200 afl-fuzz \
-S ci_fuzzer \
-i corpus/ \
-o findings/ \
-t 5000 \
-- ./fuzz_harness @@ || true
- name: Check for crashes
run: |
CRASHES=$(find findings/ -path "*/crashes/*" -not -name "README.txt" | wc -l)
echo "Found $CRASHES unique crashes"
if [ "$CRASHES" -gt 0 ]; then
echo "::error::AFL++ found $CRASHES crashes"
for crash in findings/*/crashes/*; do
[ -f "$crash" ] && echo "Crash: $crash ($(wc -c < $crash) bytes)"
done
exit 1
fi
- name: Update corpus cache
if: always()
run: |
afl-cmin -i findings/ci_fuzzer/queue/ -o corpus/ -- ./fuzz_harness @@
# 启动多个次级实例以获得更好的覆盖率
for i in $(seq 1 $(nproc)); do
afl-fuzz -S fuzzer_$i \
-i corpus/ \
-o findings/ \
-- ./fuzz_harness @@ &
done
# 等待所有模糊测试器
wait
# 合并和最小化语料库
afl-cmin -i findings/*/queue/ -o corpus_merged/ -- ./fuzz_harness @@
# 重现和分类崩溃
for crash in findings/*/crashes/*; do
echo "=== Testing: $crash ==="
timeout 5 ./fuzz_harness_asan "$crash" 2>&1 | head -20
echo "---"
done
# 按堆栈跟踪去重崩溃
afl-collect findings/ crashes_deduped/ -- ./fuzz_harness @@
| 设置 | CI 短时运行 | 夜间长时运行 |
|---|---|---|
| 时长 | 30-60 分钟 | 4-24 小时 |
| 模式 | -S(仅次级) | -S(CI 不用 -M) |
AFL_CMPLOG_ONLY_NEW | 1 | 1 |
AFL_FAST_CAL | 1 | 0 |
AFL_NO_STARTUP_CALIBRATION | 1 | 0 |
| 语料库缓存 | 必需 | 必需 |
| 并行实例 | 1-2 | nproc |
# 查看模糊测试统计
afl-whatsup findings/
# 需要跟踪的关键指标:
# - 找到的路径总数(代码覆盖率指标)
# - 唯一崩溃数 / 唯一挂起数
# - 稳定性百分比(应 >90%)
# - 执行速度(次/秒)
# - 完成的循环数(完整语料库循环次数)