Overview
Anti-fuzzing is one of three security applications built on top of the Examiner system (the other two being emulator detection and anti-emulation). It refers to the adversarial use of inconsistent instructions — instructions whose execution result differs between a CPU emulator (e.g., QEMU) and a real ARM device — to interfere with the operation of fuzzers that rely on software emulation.
Motivation: Emulator-Based Fuzzing
Many widely used fuzzing tools instrument and execute target programs inside CPU emulators rather than on bare-metal hardware, because emulation provides whole-program tracing, runtime instrumentation APIs, and cross-OS/architecture portability. Fuzzers that operate in this mode include the QEMU mode of AFL, Unicornfuzz, FirmAFL, P2IM, HALucinator, and TriforceAFL.
The implicit assumption underlying these tools is that an instruction executed inside the emulator produces the same result as it would on the real device. The Examiner paper questions this assumption by systematically locating instruction-level deviations between real ARM devices (spanning ARMv5, ARMv6, ARMv7-a, and ARMv8-a) and emulators (QEMU), generating 155,642 inconsistent instruction streams that cover roughly 30% of all instruction encodings and 47.8% of the instructions.
How Anti-Fuzzing Works
In the Examiner framework, anti-fuzzing is realized by (ab)using inconsistent instructions inside a target program so that, when the program is executed under a fuzzer running on an emulator:
- The inconsistent instructions cause the emulator's behavior to diverge from real hardware.
- The divergent behavior can include emulator crashes (some of the 12 confirmed bugs in the paper affect commonly used instructions such as
BLX) or unexpected control flow. - As a result, the coverage of the program being fuzzed inside an emulator can be highly decreased, undermining the fuzzer's ability to explore the program's state space.
This effectively turns the fuzzer's reliance on faithful emulation into an attack surface: a program can be crafted (or augmented) with inconsistent-instruction sequences that are reachable during fuzzing and that sabotage the emulation environment, making the fuzzer report low or misleading coverage.
Relationship to Inconsistent Instructions
Anti-fuzzing is a direct downstream consumer of the set of inconsistent instructions identified by Examiner. The same primitive set of deviations that enables emulator detection (distinguishing a real device from an emulator) and anti-emulation (evading dynamic analysis) also enables anti-fuzzing (degrading emulation-based fuzzing). The Examiner authors note that these three applications are demonstrated use cases, and that other applications of the inconsistent-instruction findings may exist.
Root Causes Enabling Anti-Fuzzing
The Examiner paper attributes the instruction-level inconsistencies — and therefore the viability of anti-fuzzing — primarily to two causes:
- Undefined implementation in the ARM architecture manual (i.e., behavior the specification leaves to the implementer).
- Implementation bugs in emulators (12 such bugs were discovered and confirmed by upstream developers, including bugs affecting commonly used instructions such as
BLX).
Limitations Noted by the Authors
The Examiner paper presents anti-fuzzing (along with emulator detection and anti-emulation) as a demonstration of the security relevance of inconsistent instructions, not as a comprehensive study of fuzzing-evasion techniques. Other anti-fuzzing strategies and applications of the same findings likely exist beyond what the paper enumerates.
Source
The concept of anti-fuzzing as a security application over inconsistent ARM instructions was introduced in the ASPLOS '22 paper Examiner: Automatically Locating Inconsistent Instructions between Real Devices and CPU Emulators for ARM. The source code of the system is released at https://github.com/valour01/examiner.