Welcome to ZAFL, a project to fuzz binary programs directly. Salient features of ZAFL are:
no source code required. ZAFL lets you fuzz a binary even if you don't have the source code. Even when you have the source code, the build system can be so convoluted that it is easier to work with binaries directly.
AFL compatibility. ZAFL inlines the instrumentation that AFL expects directly into the target binary. Thus, ZAFL leverages the AFL ecosystem and lets you use standard AFL tools such as afl-fuzz or afl-showmap directly.
speed. ZAFL is fast as it uses efficient static binary rewriting techniques.
X86 64-bit on Linux is robust, support for other architectures/platforms coming soon.
ZAFL demonstration video
A picture is worth a 1000 words. A video is worth a 1000 pictures? Here's a short video of ZAFL demonstrating its ease-of-use and application in a DevOps pipeline.
Please see our current licensing terms. Our plan is to open-source ZAFL and its underlying infrastructure. If the current license does not fit your need, please contact us (contact: email@example.com). Our goal is to get ZAFL in use by the community and we will be glad to work with you.
Prepping your system
The following set of instructions will step you through using ZAFL on a to prep a binary for fuzzing, as well as running the prepped binary under the control of the standard AFL fuzzer.
We regularly test ZAFL on the following platforms: Ubuntu 18.04, Ubuntu 16.04 and CentOS 7.6.
Setting up Docker on your system is likely the trickiest part of the installation procedure.
We suggest you install Docker first before proceeding.
Once you've installed Docker, make sure you can run basic hello-world without any errors:
Then install it (you will need to have sudo privilege on your system):
sudo dpkg -i libzafl_latest_amd64.deb
If all goes well, you should have libzafl.so and libautozafl.so in /usr/lib. To verify:
ls /usr/lib/*zafl*The output should be:/usr/lib/libautozafl.so /usr/lib/libzafl.so
Transforming a binary with ZAFL
After installing dependencies, we are ready to transform a binary for fuzzing.
For convenience, we have setup a public Docker image that takes as input a binary and produces as output the same binary augmented with the required AFL-compatible instrumentation.
As an illustrative example, we will prep the Unix calculator utility bc for fuzzing.
# copy bc into /tmpcp $(which bc) /tmpcd /tmp# map the host's /tmp directory into the docker image's /io directory, # thus /tmp/bc corresponds to /io/bc inside of the Docker container# The output binary produced inside the container, /io/bc.zafl, maps to /tmp/bc.zafl on your local systemdocker run -v /tmp:/io -t git.zephyr-software.com:4567/opensrc/libzafl/zafl:latest /io/bc /io/bc.zafl
You should see output of the form:
This docker container is made available to the public by Zephyr Software(contact: firstname.lastname@example.org) under the Creative Commons Attribution- NonCommercial 4.0 International license (CC BY-NC 4.0).https://creativecommons.org/licenses/by-nc/4.0/legalcodeLinux, Gcc, and other relevant open source projects are licensed under theirown license and are exempt from this license statement.Zafl: main exec is PIE... use entry point address (0x27a0) for fork server Zafl: Transforming input binary /io/bc into /io/bc.zafl Zafl: Issuing command: /opt/ps_zipr/tools/ps_zipr.sh /io/bc /io/bc.zafl -c rida -s move_globals -c zax -o move_globals:--elftables-only -o move_globals:--no-use-stars -o zax:--stars -o zax:--enable-floating-instrumentation -o zax:'-e 0x27a0' Using Zipr backend.Detected ELF shared object.Performing step rida [dependencies=mandatory] ...Done. Successful.Performing step pdb_register [dependencies=mandatory] ...Done. Successful.Performing step fill_in_cfg [dependencies=unknown] ...Done. Successful.Performing step fill_in_indtargs [dependencies=unknown] ...Done. Successful.Performing step fix_calls [dependencies=unknown] ...Done. Successful.Performing step move_globals [dependencies=unknown] ...Done. Successful.Performing step zax [dependencies=none] ...Done. Successful.Performing step zipr [dependencies=none] ...Done. Successful.Zafl: success. Output file is: /io/bc.zafl BY USING THIS DOCKER IMAGE, YOU AGREE TO BE BOUND BY THECREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL 4.0 INTERNATIONAL LICENSE
The output binary, bc.zafl, should now have been created in /tmp.
Let's verify that it works.
Even though bc.zafl has been instrumented and ready to be used with the AFL fuzzer, it can still be used normally. To test:
echo "2 + 2" | ./bc.zafl
and you should see 4 as the answer.
Fuzzing ZAFL-processed binaries with AFL
We are now ready to fuzz the calculator utility program using AFL. Note that we assume that you are already familiar with AFL. If not, please refer to the AFL documentation.
We must first setup the following environment variables:
Let's create a seed directory with an input seed file:
A special thank you to Michal Zalewski for unleashing AFL to the world, thereby making fuzzing easily available to all. Thanks to Google for supporting Michal and continuing to make AFL widely available.
Special thanks to our government sponsors for supporting our work over the years.