UnTracer-AFL
This repository contains an implementation of our prototype coverage-guided tracing framework UnTracer in the popular coverage-guided fuzzer AFL. Coverage-guided tracing employs two versions of the target binary: (1) a forkserver-only oracle
binary modified with basic block-level software interrupts on unseen basic blocks for quickly identifying coverage-increasing testcases and (2) a fully-instrumented tracer
binary for tracing the coverage of all coverage-increasing testcases.
In UnTracer, both the oracle and tracer binaries use the AFL-inspired forkserver execution model. For oracle
instrumentation we require all target binaries be compiled with untracer-cc
-- our "forkserver-only" modification of AFL's assembly-time instrumenter afl-cc
. For tracer
binary instrumentation we utilize Dyninst with much of our code based-off AFL-Dyninst. We plan to incorporate a purely binary-only ("black-box") instrumentation approach in the near future. Our current implementation of UnTracer supports basic block coverage.
Presented in our paper Full-speed Fuzzing: Reducing Fuzzing Overhead through Coverage-guided Tracing
(2019 IEEE Symposium on Security and Privacy). |
|
Citing this repository: | @inproceedings{nagy:fullspeedfuzzing, title = {Full-speed Fuzzing: Reducing Fuzzing Overhead through Coverage-guided Tracing}, author = {Stefan Nagy and Matthew Hicks}, booktitle = {{IEEE} Symposium on Security and Privacy (Oakland)}, year = {2019},} |
Developers: | Stefan Nagy ([email protected]) and Matthew Hicks ([email protected]) |
License: | MIT License |
Disclaimer: | This software is strictly a research prototype. |
INSTALLATION
1. Download and build Dyninst (we used v9.3.2)
sudo apt-get install cmake m4 zlib1g-dev libboost-all-dev libiberty-dev
wget https://github.com/dyninst/dyninst/archive/v9.3.2.tar.gz
tar -xf v9.3.2.tar.gz dyninst-9.3.2/
mkdir dynBuildDir
cd dynBuildDir
cmake ../dyninst-9.3.2/ -DCMAKE_INSTALL_PREFIX=`pwd`
make
make install
2. Download UnTracer-AFL (this repo)
git clone https://github.com/FoRTE-Research/UnTracer-AFL
3. Configure environment variables
export DYNINST_INSTALL=/path/to/dynBuildDir
export UNTRACER_AFL_PATH=/path/to/Untracer-AFL
export DYNINSTAPI_RT_LIB=$DYNINST_INSTALL/lib/libdyninstAPI_RT.so
export LD_LIBRARY_PATH=$DYNINST_INSTALL/lib:$UNTRACER_AFL_PATH
export PATH=$PATH:$UNTRACER_AFL_PATH
4. Build UnTracer-AFL
Update DYN_ROOT
in UnTracer-AFL/Makefile
to your Dyninst install directory. Then, run the following commands:
make clean && make all
USAGE
First, compile all target binaries using "forkserver-only" instrumentation. As with AFL, you will need to manually set the C compiler (untracer-clang
or untracer-gcc
) and/or C++ compiler (untracer-clang++
or untracer-g++
). Note that only non-position-independent target binaries are supported, so compile all target binaries with CFLAG -no-pie
(unnecessary for Clang). For example:
NOTE: We provide a set of fuzzing-ready benchmarks available here: https://github.com/FoRTE-Research/FoRTE-FuzzBench.
$ CC=/path/to/afl/untracer-clang ./configure --disable-shared
$ CXX=/path/to/afl/untracer-clang++.
$ make clean all
Instrumenting in forkserver-only mode...
Then, run untracer-afl
as follows:
untracer-afl -i [/path/to/seed/dir] -o [/path/to/out/dir] [optional_args] -- [/path/to/target] [target_args]
Status Screen
calib execs
andtrim execs
- Number of testcase calibration and trimming executions, respectively. Tracing is done for both.block coverage
- Percentage of total blocks found (left) and the number of total blocks (right).traced / queued
- Ratio of traced versus queued testcases. This ratio should (ideally) be 1:1 but will increase as trace timeouts occur.trace tmouts (discarded)
- Number of testcases which timed out during tracing. Like AFL, we do not queue these.no new bits (discarded)
- Number of testcases which were marked coverage-increasing by the oracle but did not actually increase coverage. This should (ideally) be 0.