Chapter 21 Fuzzing with afl-fuzz

21.1 Overview

American fuzzy lop (“afl-fuzz”) is a fuzzer, a tool fortesting software by providing randomly-generated inputs, searching forthose inputs which cause the program to crash.

Unlike most fuzzers, afl-fuzz observes the internal behaviour of theprogram being tested, and adjusts the test cases it generates totrigger unexplored execution paths. As a result, test cases generatedby afl-fuzz cover more of the possible behaviours of the testedprogram than other fuzzers.

This requires that programs to be tested are instrumented tocommunicate with afl-fuzz. The native-code compiler “ocamlopt” cangenerate such instrumentation, allowing afl-fuzz to be used againstprograms written in OCaml.

For more information on afl-fuzz, see the website athttp://lcamtuf.coredump.cx/afl/.

21.2 Generating instrumentation

The instrumentation that afl-fuzz requires is not generated bydefault, and must be explicitly enabled, by passing the -afl-instrument option to ocamlopt.

To fuzz a large system without modifying build tools, OCaml’s configure script also accepts the afl-instrument option. IfOCaml is configured with afl-instrument, then all programscompiled by ocamlopt will be instrumented.

21.2.1 Advanced options

In rare cases, it is useful to control the amount of instrumentationgenerated. By passing the -afl-inst-ratio N argument to ocamlopt with N less than 100, instrumentation can begenerated for only N% of branches. (See the afl-fuzz documentation onthe parameter AFL_INST_RATIO for the precise effect of this).

21.3 Example

As an example, we fuzz-test the following program, readline.ml:

  1. let _ =
  2. let s = read_line () in
  3. match Array.to_list (Array.init (String.length s) (String.get s)) with
  4. ['s'; 'e'; 'c'; 'r'; 'e'; 't'; ' '; 'c'; 'o'; 'd'; 'e'] -> failwith "uh oh"
  5. | _ -> ()

There is a single input (the string “secret code”) which causes thisprogram to crash, but finding it by blind random search is infeasible.

Instead, we compile with afl-fuzz instrumentation enabled:

  1. ocamlopt -afl-instrument readline.ml -o readline

Next, we run the program under afl-fuzz:

  1. mkdir input
  2. echo asdf > input/testcase
  3. mkdir output
  4. afl-fuzz -i input -o output ./readline

By inspecting instrumentation output, the fuzzer finds the crashing input quickly.