大模型应用
当 fuzzer 卡在校验/哈希/时间种子等障碍时…
在 fuzzing 构建中通过条件编译绕过校验和、哈希、魔法值、时间种子等阻碍 fuzzer 前进的检查,同时保持生产代码不变。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
当 fuzzer 卡在校验/哈希/时间种通用
解决思路
- 运行 fuzzer 并分析覆盖率,找出不可达代码:查找深层处理前的校验和/哈希验证、对 rand()/time()/srand() 的调用、拒绝大多数输入的验证函数、跨运行不同的全局状态初始化;可用覆盖率报告、-fprofile-instr-generate 剖析、手动检查入口点。
- 用条件编译修改障碍以在 fuzzing 构建中绕过:C/C++ 用 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 包裹 return -1;,Rust 用 if !cfg!(fuzzing) { return Err(...) }。
- 打补丁后验证覆盖率提升:用 fuzzing 插桩重新构建,短时间运行 fuzzer,与未打补丁版本对比覆盖率,确认新代码路径被探索。
- 评估误报风险:检查检查之后的代码是否假设已验证属性、跳过验证是否会导致生产中不可能发生的崩溃、是否存在隐式状态依赖;若误报可能性高则采用更针对性的补丁。
- 模式:绕过校验和验证——将校验失败分支用 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 包裹,使 fuzzer 可继续处理数据(误报风险低,前提是数据处理不依赖校验和正确性)。
- 模式:确定性 PRNG 种子——在 fuzzing 构建中用固定种子(如 srand(12345)),生产构建保留 srand(time(NULL)),使行为可复现且能探索所有代码路径。
- 模式:谨慎跳过验证——不要直接跳过验证(可能导致除零等崩溃),而是在 fuzzing 构建中为验证失败的配置提供安全默认值(如 config.x = 1; config.y = 1;)。
- 模式:绕过复杂格式验证——保留廉价检查(如魔法字节),在 !cfg!(fuzzing) 时才执行结构、校验和、加密签名等昂贵验证,再反序列化(误报风险中等,反序列化须能优雅处理畸形数据)。
- 技巧:保留廉价验证(魔法字节和大小检查)以低成本引导 fuzzer。
- 技巧:为 PRNG 使用固定种子,使行为确定且能探索所有代码路径。
- 技巧:增量打补丁,一次只跳过一个障碍并测量覆盖率影响。
- 技巧:跳过验证时添加防御性默认值,提供安全回退值。
- 技巧:记录所有补丁,用注释说明为何补丁安全,便于后续维护者理解 fuzzing 与生产的差异。
- 测量补丁效果:用 llvm-cov 或 cargo-cov 看行覆盖率、基本块覆盖率、函数覆盖率、语料库大小;有效补丁通常提升覆盖率 10-50% 或更多。
- 与其他技术结合:语料库播种提供能通过初始解析的有效输入、字典帮助学习魔法字节和常见值、结构感知 fuzzing 用 protobuf 或语法定义处理复杂格式、改进 harness 有时可直接避开障碍。
- libFuzzer:编译时自动定义 FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION,用 #ifdef 检查该宏,结合 sanitizer 检测新可达代码中的 bug。
- AFL++:使用 afl-clang-fast 或 afl-clang-lto 编译包装器自动定义该宏,持久模式 harness 受益最大,可考虑 AFL_LLVM_LAF_ALL 做额外输入到状态变换。
- honggfuzz:使用 hfuzz-clang 或 hfuzz-clang++ 包装器,该宏可用于条件编译,结合其反馈驱动 fuzzing。
- cargo-fuzz:构建时自动设置 fuzzing cfg,用 cfg!(fuzzing) 做运行时检查、#[cfg(fuzzing)] 做编译时条件编译;该 cfg 仅在 cargo fuzz 构建时设置,可用 RUSTFLAGS="--cfg fuzzing" 手动启用测试。
- LibAFL:对 C/C++ 目标手动定义宏或使用编译标志 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION,用法与 libFuzzer 相同。
- 排障:覆盖率未提升说明识别错障碍,需剖析执行找真正瓶颈;大量误报崩溃说明下游代码有假设,需加防御性默认值或部分验证;编译差异说明宏未在所有构建配置中定义,需检查所有源文件和依赖;补丁代码中发现 bug 说明补丁引入无效状态,需审查状态不变量;无法复现生产 bug 说明构建差异过大,需最小化补丁并保留状态关键检查。
适用边界 · 注意事项
- 当障碍可通过良好的种子语料库或字典克服时
- 当验证足够简单(如魔法字节)fuzzer 能自行学习时
- 当进行基于语法或结构感知的 fuzzing 已能处理验证时
- 当跳过检查会引入过多误报时
- 当代码本身已经对 fuzzing 友好时