Skip to content
Snippets Groups Projects

Zafl (Zipr-based AFL)

Welcome to Zafl, a project to fuzz X86 64-bit binary programs.

Key features of Zafl:

  • Uses Zipr, a fast, space-efficient binary rewriter to inline AFL-style instrumentations
  • 100% AFL compatible
  • Platform for experimenting with other instrumentation to guide afl, e.g., add calling context to the edge-profile function (a la Angora)

Installation

The instructions that follow assume that:

  • you have access to both the Zipr and ZAFL repo
  • you have sudo privileges
  • you are installing in your home directory
  • you are using a recent version of Linux, e.g., Ubuntu 18.04

First install the Zipr static binary rewriting infrastructure

cd ~
git clone --recurse-submodules git@git.zephyr-software.com:allnp/peasoup_umbrella.git
cd peasoup_umbrella
. set_env_vars
./get-peasoup-packages.sh
scons -j3

Setting up local postgres tables

Next we need to setup the proper tables in a local copy of the postgres database.

cd ~/peasoup_umbrella
./postgres_setup.sh

If all goes well with the postgres setup, you should be able to login into the database by typing: psql The output of psql should look something like this:

psql (9.3.22)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

peasoup_XXX=> 

Testing Zipr

Test the binary rewriting infrastructure by rewriting /bin/ls

cd /tmp
$PSZ /bin/ls ls.zipr -c rida

Your terminal's output should look like this:

Using Zipr backend.
Detected ELF file.
Performing step gather_libraries [dependencies=mandatory] ...Done. Successful.
Performing step meds_static [dependencies=mandatory] ...Done. Successful.
Performing step pdb_register [dependencies=mandatory] ...Done. Successful.
Performing step fill_in_cfg [dependencies=mandatory] ...Done. Successful.
Performing step fill_in_indtargs [dependencies=mandatory] ...Done. Successful.
Performing step clone [dependencies=mandatory] ...Done. Successful.
Performing step fix_calls [dependencies=mandatory] ...Done. Successful.
Program not detected in signature database.
Performing step zipr [dependencies=clone,fill_in_indtargs,fill_in_cfg,pdb_register] ...Done. Successful.

Invoke the rewritten version of /bin/ls and make sure it runs normally:

./ls.zipr

Installing ZAFL

Once Zipr has been installed, clone the repo for ZAFL and build.

cd ~
git clone --recurse-submodules git@git.zephyr-software.com:allnp/zafl_umbrella.git
cd zafl_umbrella
. set_env_vars
scons -j3

Testing Zafl

Before running Zafl, always make sure to have the proper environment variables set

cd ~/peasoup_umbrella
. set_env_vars

cd ~/zafl_umbrella
. set_env_vars

Running Zafl smoke tests

cd $ZAFL_HOME/test/bc
./test_bc.sh

The test will run afl on bc, instrumented with the proper instrumentation inlined. You will see several fuzzing run, each of which should take on the order of 30 seconds.

Once done, the output should end with something like:

unique_crashes    : 0
unique_hangs      : 0
last_path         : 0
last_crash        : 0
last_hang         : 0
execs_since_crash : 30242
exec_timeout      : 20
afl_banner        : bc
afl_version       : 2.52b
target_mode       : default
command_line      : afl-fuzz -i zafl_in -o zafl_out -- /usr/bin/bc
TEST PASS: /usr/bin/bc: execs_per_sec     : 1904.76
~/zafl_umbrella/test/bc

Final sanity check

cd /tmp
zafl.sh /bin/ls ls.zafl

zafl.sh is the primary script for adding afl instrumentation to binaries. You should see:

zafl.sh /bin/ls ls.zafl
Zafl: Transforming input binary /bin/ls into ls.zafl
Zafl: Issuing command: /home/zafl_guest/zafl_umbrella/install/zipr_umbrella/peasoup_examples/tools/ps_zipr.sh /bin/ls ls.zafl -c move_globals=on -c zafl=on -o move_globals:--elftables -o zipr:--traceplacement:on -o zipr:true -o zafl:--stars 
Using Zipr backend.
Detected ELF file.
Performing step gather_libraries [dependencies=mandatory] ...Done. Successful.
Performing step meds_static [dependencies=mandatory] ...Done. Successful.
Performing step pdb_register [dependencies=mandatory] ...Done. Successful.
Performing step fill_in_cfg [dependencies=mandatory] ...Done. Successful.
Performing step fill_in_indtargs [dependencies=mandatory] ...Done. Successful.
Performing step clone [dependencies=mandatory] ...Done. Successful.
Performing step fix_calls [dependencies=mandatory] ...Done. Successful.
Program not detected in signature database.
Performing step move_globals [dependencies=none] ...Done. Successful.
Performing step zafl [dependencies=none] ...Done. Successful.
Performing step zipr [dependencies=clone,fill_in_indtargs,fill_in_cfg,pdb_register] ...Done. Successful.

You can run ls.zafl as you would ls: ./ls.zafl

Zafl'd binaries can be run normally. There is no extra output.

To make sure the binary has been instrumented properly: ZAFL_DEBUG=1 ./ls.zafl

The output should start with:

Error getting shm environment variable - fake allocate AFL trace map
Success at mmap!
libautozafl: auto-initialize fork server

Let's prep for fuzzing:

mkdir input_seeds
echo "hello" > input_seeds/hello.seed

Let's now run the Zafl'd binary with afl:

afl-fuzz -i input_seeds -o out -- ./ls.zafl @@

If afl complains about missing instrumentation, you'll need to set the following environment variable:

export AFL_SKIP_BIN_CHECK=1

You can also run the usual afl utilities, e.g:

afl-showmap -o map.out -- ./ls.zafl
afl-cmin -i out/queue/ -o out.cmin -- ./ls.zafl @@

Et voila!

TL;DR

Once everything is installed properly, you can prep a binary for fuzzing with the simple command:

zafl.sh <target_binary> <zafl_output_binary>