一句话:用 LLVM pass 精细恢复测试用例状态,使持久化 fuzzing 兼顾高吞吐与语义正确性。
持久化 fuzzing 通过复用单个进程避免反复创建、初始化和销毁,从而显著提高吞吐;但跨测试用例残留的进程状态会导致语义不一致,造成漏报崩溃、误报崩溃并削弱 fuzzer 有效性。作者将现有执行机制视为状态恢复连续谱,提出 ClosureX:仅重置与测试用例执行相关的状态,以获得接近持久化 fuzzing 的性能和重量级状态恢复的正确性。ClosureX 实现为一组 LLVM pass 并集成到 AFL++。在十个流行开源模糊测试目标上,ClosureX 保持语义正确,测试用例执行率较 AFL++ 平均提升超过 3.5 倍,发现 bug 更稳定且快 1.9 倍,并发现 15 个 0-day 漏洞(4 个 CVE)。
Fuzzing is a widely adopted and pragmatic methodology for bug hunting as a means of software hardening. Research reveals that increasing fuzzing throughput directly increases bug discovery rate. The highest performance fuzzing strategy is persistent fuzzing, which reuses a single process for all test cases by looping back to the start upon completion, instead of exiting. This eliminates all process creation, initialization, and tear-down costs---which are on-par with execution cost. Unfortunately, persistent fuzzing leads to semantically inconsistent program states because process state changes from one test case remain for subsequent test cases. This semantic inconsistency results in missed crashes, false crashes, and overall incorrectness that undermines fuzzer effectiveness. We observe that existing fuzzing execution mechanisms exist on a continuum, based on the amount of state that gets discarded and restored between test cases. We present ClosureX, a fuzzing execution mechanism that sits at a new spot on this state restoration continuum, where only test-case-execution-specific state is reset. This fine-grain state restoration provides near-persistent performance with the correctness of heavyweight state restoration. We construct ClosureX as a set of LLVM passes that integrate with AFL++. Our evaluation on ten popular open-source fuzzing targets show that ClosureX maintains semantic correctness, while increasing test case execution rate by over 3.5x, on average, compared to AFL++. ClosureX also finds bugs more consistently and 1.9x faster than AFL++, with ClosureX discovering 15 0-day bugs (4 CVEs).