Trumpetpitcher
We use a framework we call Trumpetpitcher (named after a group of carnivorous plants native to North America) to engage in heavier duty fuzzing campaigns. It combines our full-system-emulator with the open source library LibAFL. We leverage LibAFL’s mature out-of-the-box support for the parts of fuzzers we find “boring”, like managing the test corpus, recording outcomes, and divying up work across multiple cores (to be clear, this isn’t a knock on those parts of fuzzing, they’re valuable important!). This lets us spend all of our time working on the “exciting” parts of fuzzing, like ways to use feedback and mutation, to find deeper bugs.
There’s a huge body of academic research focusing on fuzzers that we hope to incorporate into Trumpetpitcher as time goes on. To start off, Trumpetpitcher currently supports:
- “blind” fuzzing: just generating or mutating data sent to the guest
- AFL-style fuzzing: mutational fuzzing that can determine if a mutation leads to new paths
Stay tuned, we’re hoping to expand this list as time goes on!
Trumpetpitcher versus Fuzzing Physical Devices
Fuzzing with Trumpetpitcher scales much more effectively than fuzzing the physical device itself. On a consumer desktop we can fuzz thousands to tens of thousands of cases per second, which can be orders of magnitude more than is physically possible with some targets.
Not only does Trumpetpitcher fuzz more testcases than hardware, but each testcase is more targeted. Trumpetpitcher peeks at the internal state of the target in ways that aren’t possible with physical hardware, such as code coverage, that let the fuzzer evaluate how good of a testcase it just threw.
Trumpetpitcher also automatically detects and reports the exact root cause of a crash. On physical hardware, you’re lucky if you get a stacktrace, and it’s not always clear which packet crashed the device.
Trumpetpitcher versus Fuzzing with QEMU and co.
The above points are neat, but true for fuzzing with any emulator, like QEMU and its various forks. In fact, LibAFL already supports fuzzing with QEMU out of the box! Trumpetpitcher has a few advantages over those too.
Trumpetpitcher is a lot more flexible, because it’s powered by Cobralily. It makes it much easier to report outcomes that aren’t crashes but still interesting. Maybe you just need to figure out how to reach a vulnerable block of code, or monitor a target’s reply, or get a memory location to read 0x1337. Cobralily makes it much easier to catch these, which means that they can be fuzzed for with Trumpetpitcher too.
Additionally, state-of-the-art fuzzers typically operate by instrumenting source code, and don’t always include binary-only options that can be fuzzed in QEMU without source code, because it usually involves patching QEMU. We take the time to understand academic fuzzers and incorporate those features into Cobralily/Trumpetpitcher in a way that doesn’t require source code, because we generally assume source code is unavailable.