Firmware Fuzzing
Overview
Firmware fuzzing is a dynamic analysis technique that exercises firmware binaries—typically those running on resource-constrained IoT or embedded devices—with generated or mutated inputs to discover crashes, memory corruptions, and other vulnerabilities. Because firmware images frequently lack source code, target unfamiliar instruction set architectures (ISAs), and depend on peripherals and hardware behavior that are difficult to model, firmware fuzzing has evolved into a distinct subfield of binary fuzzing.
Key characteristics that distinguish firmware fuzzing from general binary fuzzing include:
- Closed-source / no-symbol binaries: Firmware is typically shipped as stripped images, so instrumentation often cannot rely on debug metadata.
- Diverse ISAs: Firmware targets x86-64, ARM/AArch64, RISC-V, MIPS, and microcontroller-specific ISAs such as MSP430, while state-of-the-art coverage-guided fuzzers have historically focused on a small subset of ISAs.
- Hardware dependence: Firmware interacts with memory-mapped I/O (MMIO) peripherals whose behavior must be emulated or modeled for the fuzzer to make progress beyond the firmware's initialization code.
- Reused third-party components: Many IoT firmware images reuse open-source libraries (e.g., parsing libraries, network stacks), making them vulnerable to known upstream CVEs.
Main Approaches
Emulation-based Grey-Box Fuzzing
Grey-box firmware fuzzers typically run the firmware inside an ISA emulator that has been instrumented to collect coverage feedback (e.g., branch or edge hit counts) used to guide input mutation. A representative example is Fuzzware, which combines a fuzzing engine with a precise MMIO access model: the fuzzer generates a raw input file, and chunks of that file are consumed by per-peripheral MMIO access models that translate them into hardware-realistic responses served to the emulated firmware. Coverage feedback is reported back to the engine once the input is exhausted.
Icicle: A Re-Designed Emulator for Grey-Box Firmware Fuzzing
Icicle argues that modern emulation-based fuzzers have evolved by re-purposing general-purpose emulators, which forces instrumentation techniques to be added in an ad-hoc, ISA-specific manner and limits state-of-the-art fuzzing to a few ISAs. Icicle instead proposes a fuzzing-specific, multi-architecture emulation framework in which instrumentation is implemented once in an architecture-agnostic way with low execution overhead. Key reported results from the Icicle paper:
- Reuse as the emulator for the Fuzzware ARM firmware fuzzer while replicating Fuzzware's results.
- The new instrumentation enabled by Icicle led to the discovery of new bugs not previously found by Fuzzware.
- Reproduction of LAVA-M benchmark bugs across diverse ISAs (x86-64, ARM/AArch64, RISC-V, MIPS) using the same architecture-agnostic instrumentation.
- Discovery of 7 new bugs in real-world MSP430 firmware binaries during a fuzzing campaign on an ISA that was not previously supported by emulation-based fuzzers.
Directed Grey-Box Fuzzing (DGF)
DGF targets specific binary locations rather than maximizing overall coverage, which is useful when a known vulnerability or reused vulnerable component must be reached quickly. Until recently, DGF had only been applied to firmware at function granularity, which is too coarse to aim directly at the vulnerable basic block.
BullsEye
BullsEye is described as the first Directed Grey-Box Fuzzing framework to schedule closed-source Linux-based firmware fuzzing by basic-block-level distance to user-specified targets. It combines static and dynamic analysis to enable DGF in the firmware domain, focusing on vulnerabilities introduced by reused third-party components, and introduces novel DGF heuristics that address limitations of traditional approaches.
Reported evaluation against four greybox-fuzzing baselines sharing its execution back-end (including reimplementations of AFLGO and WINDRANGER) on 40 vulnerability sites across 32 firmware images:
- BullsEye reproduced every target within the time budget.
- The strongest of the four baselines reproduced 35 of the 40 targets.
- BullsEye reduced Time-to-Exposure by a geometric mean of 9.5× to 72.5× over the baselines.
Against GREENHOUSE (a state-of-the-art firmware re-hosting framework) on the 18 targets its pipeline supports, BullsEye was faster by a geometric mean of 9.8×.
Side-Channel Black-Box Fuzzing
When firmware or its binaries are unavailable (e.g., only the running device is accessible), grey-box coverage feedback cannot be obtained. PowerFuzz introduces a statistical black-box fuzzing framework that uses power side-channel measurements as a substitute for binary instrumentation, requiring no internal visibility into the target firmware. It uses power traces to identify executed branches via a sliding-window followed by a growing-window full-trace correlation method, and uses the recovered branch information to construct a high-level control-flow graph that drives the fuzzer toward unexplored execution paths. On three embedded hardware platforms and ten firmware benchmarks, PowerFuzz reports branch coverage within 13.5% of grey-box fuzzers while outperforming state-of-the-art black-box fuzzers by up to 22%.
Practical Considerations
Evidence from industrial fuzzing experience on nRF52 devices using Fuzzware highlights common operational hurdles:
- Fuzzware's automatic configuration tool did not produce a valid memory map for the target binary, omitting FICR (factory configuration memory) and UICR (user configuration memory) MMIO sections, which prevented emulation.
- Manual configuration made emulation possible but produced slow execution, crashes hard to attribute within the emulator, and difficulties continuing without deep expertise.
- Useful configuration refinements reported in practice include adding static/constant MMIO reads in the bootloader to reach "user code" faster, patching delay functions to improve speed, and patching "wait-for-flag" conditions.
- Tooling around Fuzzware has been developed to automate configuration (e.g., the Aurora-Fuzz configuration script for nRF52 binaries), with features such as printing and modifying the memory map, loading UICR/FICR state from hex files or directly from a USB-connected chip, filtering Softdevice MMIO reads, modifying boot, interrupt, and exit behavior, saving configurations, testing them, and starting fuzzing sessions.
A structured fuzzing workflow typically iterates through:
- Start with a configuration (built automatically or from a template).
- Attempt emulation; if it fails, refine the configuration.
- Run a fuzzing session; if coverage is not meaningful, iterate on the configuration.
- Analyze crashes when found, distinguishing crashes caused by configuration errors from those caused by the firmware itself.
Related Techniques and Systems
- Fuzzware: Emulation-based grey-box firmware fuzzer with precise MMIO modeling, commonly used as a baseline execution back-end in firmware fuzzing research.
- Icicle: Multi-architecture, fuzzing-specific emulator that implements instrumentation once in an architecture-agnostic way.
- BullsEye: First DGF framework targeting basic-block-level distance in closed-source Linux-based firmware, focused on reused third-party components.
- PowerFuzz: Black-box firmware fuzzer that derives coverage from power side-channel traces rather than binary instrumentation.
- GREENHOUSE: State-of-the-art firmware re-hosting framework used as a comparison point for BullsEye.
- AFLGO, WINDRANGER: DGF approaches reimplemented as baselines in the BullsEye evaluation.
- LAVA-M: A standard corpus of synthetic bugs used to benchmark firmware/binary fuzzers across ISAs.
References
See the Citations section for the underlying sources.