计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
re-fuzzing【效率与协作】覆盖率引导模糊测试:AFL++/libFuzzer/honggfuzz、插桩与语料初始化、 afl-fuzz 运行参数、覆盖率(afl-cov)、字典/结构化输入。 触发词:fuzz、模糊测试、AFL、afl-fuzz、libFuzzer、honggfuzz、 覆盖率、corpus、语料、dictionary、挖洞、fuzzing。
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
所有工具先验证再使用。fuzz 是动态执行,一律在沙箱内跑([[re-analyze/platform-tips]] 最高原则,见 [[re-sandbox]])。
sudo apt install afl++sudo dnf install american-fuzzy-lop american-fuzzy-lop-clang(包即 AFL++ fork);或源码编译拿最新版(见下)sudo pacman -S afl++brew install afl++sudo apt install afl++(AFL++ 官方支持 WSL;Windows 本机不可直接跑)git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
make distrib # 需要 clang/LLVM 工具链
sudo make install
afl-fuzz -h(打印 usage 即 OK);afl-clang-fast --versionsudo apt install clangsudo dnf install clangsudo pacman -S clangxcode-select --install 补命令行工具),或 brew install llvm/fsanitize=fuzzer)clang --version-fsanitize=fuzzer 即启用clang -fsanitize=fuzzer -x c /dev/null -o /tmp/fztest && /tmp/fztest -runs=1
输出含 INFO: libFuzzer 即 OK(/tmp/fztest 用完可删)sudo apt install build-essential binutils-dev libunwind-dev libblocksruntime-dev clang
git clone https://github.com/google/honggfuzz && cd honggfuzz && make
sudo dnf install honggfuzzsudo pacman -S honggfuzz(或 AUR 包 honggfuzz)honggfuzz --helpsudo apt install lcov / sudo dnf install lcov / sudo pacman -S lcov(gcov 随 gcc 自带)git clone https://github.com/mrash/afl-cov && cd afl-cov
./afl-cov -Vgcc -fprofile-arcs -ftest-coverage),与 AFL 插桩不兼容——同一份代码编两次:一次 afl+ASAN 版跑 fuzz,一次 gcov 版测覆盖率按顺序执行;每步产物(harness 源码、语料目录、fuzz 输出目录)记录路径,供 [[re-crash-triage]] / 报告引用。
CC=afl-clang-fast CXX=afl-clang-fast++ AFL_USE_ASAN=1 ./configure && make
# 简单单文件目标:
afl-clang-fast -fsanitize=address -g -O1 -o target target.c
-Q QEMU 模式(afl-fuzz -Q ...),无需插桩但慢 2-5 倍/* fuzz_target.c —— 以 libpng 的 png_read 入口为例 */
#include <stdint.h>
extern int my_parse(const char *data, size_t len); /* 目标解析入口 */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
my_parse((const char *)data, size);
return 0;
}
libFuzzer 编译:clang -fsanitize=fuzzer,address -g -O1 -o fuzz_target fuzz_target.c target_lib.c
AFL++ 编译同一 harness:afl-clang-fast -fsanitize=fuzzer,address -o fuzz_target_afl fuzz_target.c(afl-clang-fast 拦截 -fsanitize=fuzzer 并链接自带 driver),运行 afl-fuzz -i in -o out -- ./fuzz_target_afl @@mkdir in out
# 每个种子是目标可正常解析的最小有效输入(别拿空文件起步)
cp seed_sample.bin in/
afl-cmin -i in -o in_min -- ./target @@ # 去重:只留覆盖不同路径的种子
afl-fuzz -i in_min -o out -m none -t 1000+ -x dict.txt -- ./target @@
-m none:ASAN 程序默认内存限制会误杀,必加(见坑 4)-t 1000+:初始超时给足(+ 号表示随路径增长自适应)@@ 占位符 = fuzz 生成的文件路径;输入走 stdin 则去掉 @@-M main 主实例 + -S secondary1 等从实例(共享同一 out 目录);afl-whatsup out 看汇总afl-fuzz -i - -o out ...(-i - 复用已有输出目录)afl-tmin 在 out/crashes 上工作)afl-whatsup out——paths_total 增长 + execs_done 高 = 正常gcc -fprofile-arcs -ftest-coverage -g -O0 -o target_gcov target.c
./afl-cov -d out --live --coverage-cmd "cat AFL_FILE | ./target_gcov" --code-dir .
产出在 out/cov/,HTML 报告 out/cov/web/(lcov/genhtml 生成)afl-showmap -o /tmp/map -- ./target @@ 看单输入覆盖哪些块;对比两个输入的 map 判断是否覆盖新路径-x dict.txt:关键词(魔数、分隔符、关键字)降低跨格式变异成本;AFL++ 自带大量格式字典(AFLplusplus/dictionaries/ 含 png/pdf/jpeg/tiff 等,直接 -x 引用)AFL_CUSTOM_MUTATOR_LIBRARY,Python 示例在 utils/python_mutators/),维护校验和/长度的一致性out/crashes/)交其分析;最小化/去重(cmin/tmin)在其流程内完成afl-fuzz 跑起来 execs 暴涨但 paths 数不动、从不出崩溃;原因——目标没被插桩(release 二进制 / 编译器不是 afl-* 包装器 / @@ 传参错误 fuzz 了无关程序);对策——开跑前 afl-showmap -o /tmp/map -- ./target @@ 验证覆盖率有变化;afl-fuzz 启动输出会警告 instrumentation 缺失;无源码改用 -Q QEMU 模式afl-cmin 去重到几十个覆盖不同分支的最小样本;不同格式变体各留一个代表out/crashes/ 堆积上万个文件,实际是同一个 bug;原因——fuzzer 对每个触发输入都存盘,未按崩溃点区分;对策——用 afl-tmin 逐个最小化(afl-tmin -i crash -o crash.min -- ./target @@),再按 ASAN 报错类型 + 回溯栈合并同类项(见 [[re-crash-triage]])AFL_USE_ASAN=1 / -fsanitize=address)、-m none 未设导致 ASAN 内存限制被杀、ASAN 与老版本 glibc 冲突;对策——统一 AFL_USE_ASAN=1 + -m none;-t 给足;先手工跑一个已知崩溃输入确认 ASAN 能报@@ 文件根本喂不进解析逻辑,覆盖率恒为 0;原因——网络程序读 fd 不读文件,fuzz 通道错位;对策——写 harness 把文件内容直接喂给解析函数(fuzz 的是解析器不是网络栈);真实流量用 [[re-netcap]] 抓包做种子