GUSTAVE is a fuzzing platform for embedded OS kernels. It is based on QEMU and AFL (and all of its forkserver siblings). It allows to fuzz OS kernels like simple applications.
(c) Airbus 2021, sduverger
Thanks to QEMU, it is multi-platform. One can see GUSTAVE as a AFL forkserver implementation inside QEMU, with fine grain target inspection.
GUSTAVE has mainly been designed to target embedded OS kernels. It might not be the best tool to fuzz large and complex kernels as found in Windows, Linux or MACOS.
However if you have a target under the hood which can be prepared with one or two applications to boot without any user interaction, it might be interesting to give GUSTAVE a try.
afl-fuzztool, from the AFL project, is used to automatically fuzz your target. However, AFL can't directly fuzz an OS kernel and expects its target to directly parse the generated test cases.
To make it short,
afl-fuzzwill run QEMU with GUSTAVE integration as its target. In turn, GUSTAVE will handle : - forkserver synchronization - generated test cases translation to target system calls - target kernel monitoring (execution coverage and memory accesses)
As AFL/QEMU-user mode found in AFL++ project, GUSTAVE implements QEMU TCG IR level binary instrumentation for code coverage.
However, you can choose to disable it and rebuild your target kernel code with only specific parts being subject to code coverage analysis. You will have to inject AFL shims at build time to update the trace bitmaps though. That was our initial approach (see Publications).
Less prevalent in existing solutions, GUSTAVE does not care about monitoring
kernel panics. We consider them managed errors, and want to discover illegal behaviors that did not trigger any alarm.
For that purpose GUSTAVE relies on a O(1) byte oriented memory filtering bitmap to detect illegal accesses from the kernel. There might be large debate about defining what could be considered illegal from the kernel point of view. But in restricted embedded, highly deterministic environments you might find yourself comfortable defining legitimate memory areas for your firmware and tracking out-of-bound accesses.
GUSTAVE design choices imply the following differences: - really target agnostic (OS, architecture), as long as QEMU offers support - covers all system calls implemented in the target kernel - no specific devs are needed inside the target
However, you still need to tell GUSTAVE: - how your target handles system calls - what is your target legitimate memory layout
For now only x86 host is supported, as many working environments are based upon this architecture we don't consider it a prohibiting limitation.
The restriction comes from the way we initially implemented memory filtering backend at
tcg-targetlevel for the QEMU load/store fast-path. The recent
TCGPluginmemory callbacks architecture might be an alternative approach to support any host.
We have implemented and tested Intel x86 and PowerPC support. The GUSTAVE implementation is architecture independent. If you can run your target with QEMU, you can fuzz it with GUSTAVE with little effort.
MACHINE_INITfunction for a given architecture.
We also added support for x86 and PowerPC GUSTAVE instrumentation shims to
afl-gcc, in case you don't want to proceed with TCG binary instrumentation.
We provide POK micro-kernel specific developments:
You will need to: - build AFL - build QEMU with GUSTAVE integration - create or generate the filtering bitmap - write a JSON configuration file for your target - run it in a terminal
Read the manual for the POK target.
Material from different talks on GUSTAVE can be found at https://airbus-seclab.github.io/.