
Distributed, code-coverage guided snapshot-based fuzzer for user and kernel-mode targets on Windows and Linux, with emulator and hypervisor backends.
what the fuzzA distributed, code-coverage guided, cross-platform snapshot-based fuzzer designed for attacking user and or kernel-mode targets running on Microsoft Windows and Linux user-mode (experimental!).
what the fuzz or wtf is a distributed, code-coverage guided, customizable, cross-platform snapshot-based fuzzer designed for attacking user and or kernel-mode targets running on Microsoft Windows or Linux (experimental, see linux_mode). Execution of the target can be done inside an emulator with bochscpu (slowest, most precise), inside a Windows VM with the Windows Hypervisor Platform APIs or inside a Linux VM with the KVM APIs (fastest).
It uncovered memory corruption vulnerabilities in a wide range of softwares: IDA Pro, a popular AAA game, the Windows kernel, the Microsoft RDP client, NVIDIA GPU Display driver, etc.
Compiled binaries are available from either the CI artifacts or from the Releases section for both Windows & Linux.
If you would like to read more about its history or how to use it on a real target, I recommend to take a look at those posts to get started 🔥
The best way to try the features out is to work with the fuzzer_hevd / fuzzer_tlv_server modules. You can grab the target-hevd.7z / target-tlv_server.7z archives and extract them into the targets/ directory. The archives contain the directory trees that are expected for every targets:
inputs is the folder where your input test-cases go into,outputs is the folder where the current minset files are saved into,coverage is the folder where the .cov files are expected to be in,crashes is where the crashes gets saved in,state is where the memory dump (mem.dmp) as well as the CPU state (regs.json) and the symbol store are stored in (symbol-store.json). The symbol store is a simple JSON file that is used on Linux systems to know where to put breakpoints as there is no support for symbols / dbgeng on those platforms. wtf generates this file at runtime everytime you run your target on Windows.What follows assume that you downloaded the target-hevd.7z file attached to the latest release, and extracted it in the targets directory of your clone of wtf. You should have wtf/targets/hevd in which you find the inputs / outputs, etc. directories.
The server is basically the brain and keeps track of all the state: the aggregated code-coverage, the corpus, it generates and distributes the test-cases to client.
This is how you might choose to launch a local server node:
wtf.exe master --name hevd --max_len=1028 --runs=10000000
The max_len option is used to limit the size of the generated test-case, runs is the number of test-cases it will generate, address specify where wtf needs to be listening on, target is a directory with the directory tree we described above (the user can also choose to override those directories with --input / --output / --crashes) and name specifies your fuzzing module name so that the master can invoke your generator function if you have defined one.
The client nodes run a test-case that has been generated and distributed by the server and communicates the result back to the server (code-coverage, result, etc.).
This is how you would start a client node that uses the bochscpu backend:
wtf.exe fuzz --name hevd --limit 10000000
The fuzz subcommand is used with the name option to specify which fuzzer module needs to be used, backend specifies the execution backend and limit the maximum number of instruction to execute per testcase (depending on the backend, this option has different meaning).
If you would like to run a test-case (or a folder filled with test-cases), you can use the run subcommand.
This is how you would would run the crash-0xfffff764b91c0000-0x0-0xffffbf84fb10e780-0x2-0x0 test-case:
wtf.exe run --name hevd --limit 10000000 --input crashes\crash-0xfffff764b91c0000-0x0-0xffffbf84fb10e780-0x2-0x0
To minset a corpus, you need to use a server node and as many client nodes as you need like you would for a fuzzing job. You can simply set the runs optins to 0.
This is how you would minset the corpus in outputs into the minset directory (also highlights how you can override the inputs and outputs directories):
wtf.exe master --name hevd --max_len=1028 --runs=0 --inputs=outputs --outputs=minset
The main mechanism available to instrospect in an execution backend is to generate an execution trace. bochscpu is the fastest backend to do that, because exiting VMX mode is very expensive on the other backends.
This is how you would generate an execution trace for the crash-0xfffff764b91c0000-0x0-0xffffbf84fb10e780-0x2-0x0 test-case: