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:
- let _ =
- let s = read_line () in
- match Array.to_list (Array.init (String.length s) (String.get s)) with
- ['s'; 'e'; 'c'; 'r'; 'e'; 't'; ' '; 'c'; 'o'; 'd'; 'e'] -> failwith "uh oh"
- | _ -> ()
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:
- ocamlopt -afl-instrument readline.ml -o readline
Next, we run the program under afl-fuzz:
- mkdir input
- echo asdf > input/testcase
- mkdir output
- afl-fuzz -i input -o output ./readline
By inspecting instrumentation output, the fuzzer finds the crashing input quickly.