Fuzzing binary-only targets

When source code is NOT available, AFL++ offers various support for fast, on-the-fly instrumentation of black-box binaries.

If you do not have to use Unicorn the following setup is recommended to use qemu_mode:

  • run 1 afl-fuzz -Q instance with CMPLOG (-c 0 + AFL_COMPCOV_LEVEL=2)
  • run 1 afl-fuzz -Q instance with QASAN (AFL_USE_QASAN=1)
  • run 1 afl-fuzz -Q instance with LAF (AFL_PRELOAD=libcmpcov.so + AFL_COMPCOV_LEVEL=2) Alternatively you can use frida_mode, just switch -Q with -O and remove the LAF instance.

Then run as many instances as you have cores left with either -Q mode or - better - use a binary rewriter like afl-dyninst, retrowrite, zafl, etc.

For Qemu and Frida mode, check out the persistent mode, it gives a huge speed improvement if it is possible to use.

QEMU

For linux programs and its libraries this is accomplished with a version of QEMU running in the lesser-known “user space emulation” mode. QEMU is a project separate from AFL, but you can conveniently build the feature by doing:

cd qemu_mode
./build_qemu_support.sh

For additional instructions and caveats, see qemu_mode/README.md. If possible you should use the persistent mode, see qemu_mode/README.persistent.md. The mode is approximately 2-5x slower than compile-time instrumentation, and is less conducive to parallelization.

If afl-dyninst works for your binary, then you can use afl-fuzz normally and it will have twice the speed compared to qemu_mode (but slower than qemu persistent mode). Note that several other binary rewriters exist, all with their advantages and caveats.

Frida

Frida mode is sometimes faster and sometimes slower than Qemu mode. It is also newer, lacks COMPCOV, but supports MacOS.

cd frida_mode
make

For additional instructions and caveats, see frida_mode/README.md. If possible you should use the persistent mode, see qemu_frida/README.md. The mode is approximately 2-5x slower than compile-time instrumentation, and is less conducive to parallelization.

Unicorn

For non-Linux binaries you can use AFL++'s unicorn mode which can emulate anything you want - for the price of speed and user written scripts. See unicorn_mode/README.md.

It can be easily built by:

cd unicorn_mode
./build_unicorn_support.sh

Shared libraries

If the goal is to fuzz a dynamic library then there are two options available. For both you need to write a small harness that loads and calls the library. Then you fuzz this with either frida_mode or qemu_mode, and either use AFL_INST_LIBS=1 or AFL_QEMU/FRIDA_INST_RANGES.

Another, less precise and slower option is using ptrace with debugger interrupt instrumentation: utils/afl_untracer/README.md.

More

A more comprehensive description of these and other options can be found in binaryonly_fuzzing.md.