# Implementing Fuzz Testing In Cicd With Aflplusplus

> 将 AFL++ 覆盖率引导的模糊测试集成到 CI/CD 管道中，以发现 C/C++ 和编译型应用中的内存损坏、输入处理和逻辑漏洞。

- Skill: `killvxk/implementing-fuzz-testing-in-cicd-with-aflplusplus` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add killvxk/implementing-fuzz-testing-in-cicd-with-aflplusplus`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/implementing-fuzz-testing-in-cicd-with-aflplusplus/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/implementing-fuzz-testing-in-cicd-with-aflplusplus

---


# 在 CI/CD 中使用 AFL++ 实施模糊测试

## 概述

AFL++（American Fuzzy Lop Plus Plus）是 AFL 的社区维护分支，为发现编译型应用中的漏洞提供最先进的覆盖率引导模糊测试。AFL++ 使用遗传算法变异输入，跟踪代码覆盖率以寻找触发崩溃、挂起和未定义行为的新执行路径。在 CI/CD 环境中，AFL++ 可以集成到持续测试解析器、协议处理程序、文件格式处理器以及任何处理不受信任输入的代码中。AFL++ 支持持久模式以实现高速模糊测试（每秒超过 100,000 次执行）、自定义变异器、用于纯二进制模糊测试的 QEMU 模式以及用于自动字典提取的 CmpLog/RedQueen。

## 前置条件

- 基于 Linux 的 CI Runner（AFL++ 原生不支持 Windows）
- GCC 或 Clang 编译器工具链
- 已安装 AFL++（`apt install aflplusplus` 或从源码构建）
- 带有隔离输入处理的测试线束函数的目标应用
- 有效输入样本的种子语料库

## 核心概念

### 覆盖率引导模糊测试

AFL++ 在编译时（或通过 QEMU/Frida 对纯二进制目标）对目标二进制文件进行插桩，以跟踪每个输入执行了哪些代码路径。当变异输入触发新的代码路径时，它会被保存到语料库中以供进一步变异。这种反馈循环使 AFL++ 能够系统地探索程序状态空间。

### 插桩模式

| 模式 | 使用场景 | 性能 |
|------|----------|------|
| `afl-clang-fast`（LTO） | 有源码，最佳性能 | 最高 |
| `afl-clang-fast` | 有源码，标准 | 高 |
| `afl-gcc-fast` | GCC 项目 | 高 |
| `QEMU 模式` | 纯二进制，无源码 | 中 |
| `Frida 模式` | 纯二进制，跨平台 | 中 |
| `Unicorn 模式` | 固件，嵌入式 | 低 |

### 持久模式

持久模式通过在循环中进行模糊测试来避免 fork 开销：

```c
#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;
}
```

## 实施步骤

### 步骤 1 — 构建模糊测试线束

创建一个将 AFL++ 输入传递给目标函数的测试线束：

```c
// 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;
}
```

### 步骤 2 — 使用 AFL++ 插桩编译

```bash
# 标准插桩
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
```

### 步骤 3 — 准备种子语料库

```bash
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
```

### 步骤 4 — 配置 CI/CD 集成

**GitHub Actions：**

```yaml
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 @@
```

### 步骤 5 — 夜间运行的并行模糊测试

```bash
# 启动多个次级实例以获得更好的覆盖率
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 @@
```

### 步骤 6 — 崩溃分析

```bash
# 重现和分类崩溃
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 @@
```

## AFL++ CI/CD 最佳实践

| 设置 | 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 |

## 监控模糊测试活动

```bash
# 查看模糊测试统计
afl-whatsup findings/

# 需要跟踪的关键指标：
# - 找到的路径总数（代码覆盖率指标）
# - 唯一崩溃数 / 唯一挂起数
# - 稳定性百分比（应 >90%）
# - 执行速度（次/秒）
# - 完成的循环数（完整语料库循环次数）
```

## 参考资料

- [AFL++ Documentation](https://aflplus.plus/docs/)
- [AFL++ GitHub Repository](https://github.com/AFLplusplus/AFLplusplus)
- [AFL++ Fuzzing in Depth Guide](https://aflplus.plus/docs/fuzzing_in_depth/)
- [Google Testing Handbook - AFL++](https://appsec.guide/docs/fuzzing/c-cpp/aflpp/)
- [OWASP Fuzzing Guide](https://owasp.org/www-community/Fuzzing)

