ParmeSan: Sanitizer-guided Greybox Fuzzing
ParmeSan is a sanitizer-guided greybox fuzzer based on Angora.
Published Work
USENIX Security 2020: ParmeSan: Sanitizer-guided Greybox Fuzzing.
The paper can be found here: ParmeSan: Sanitizer-guided Greybox Fuzzing
Building ParmeSan
See the instructions for Angora.
Basically run the following scripts to install the dependencies and build ParmeSan:
build/install_rust.sh
PREFIX=/path/to/install/llvm build/install_llvm.sh
build/install_tools.sh
build/build.sh
ParmeSan also builds a tool bin/llvm-diff-parmesan
, which can be used for target
acquisition.
Building a target
First build your program into a bitcode file using clang
(e.g., base64.bc). Then build your target in the same way, but with your selected sanitizer enabled. To get a single bitcode file for larger projects, the easiest solution is to use gllvm.
# Build the bitcode files for target acquisition
USE_FAST=1 $(pwd)/bin/angora-clang -emit-llvm -o base64.fast.bc -c base64.bc
USE_FAST=1 $(pwd)/bin/angora-clang -fsanitize=address -emit-llvm -o base64.fast.asan.bc -c base64.bc
# Build the actual binaries to be fuzzed
USE_FAST=1 $(pwd)/bin/angora-clang -o base64.fast -c base64.bc
USE_TRACK=1 $(pwd)/bin/angora-clang -o base64.track -c base64.bc
Then acquire the targets using:
bin/llvm-diff-parmesan -json base64.fast.bc base64.fast.asan.bc
This will output a file targets.json
, which you provide to ParmeSan with the -c
flag.
For example:
$(pwd)/bin/fuzzer -c ./targets.json -i in -o out -t ./base64.track -- ./base64.fast -d @@
Options
ParmeSan's SanOpt option can speed up the fuzzing process by dynamically
switching over to a sanitized binary only once the fuzzer reaches one of the
targets specified in the targets.json
file.
Enable using the -s [SANITIZED_BIN]
option.
Build the sanitized binary in the following way:
USE_FAST=1 $(pwd)/bin/angora-clang -fsanitize=address -o base64.asan.fast -c base64.bc
Targets input file
The targets input file consisit of a JSON file with the following format:
{
"targets": [1,2,3,4],
"edges": [[1,2], [2,3]],
"callsite_dominators": {"1": [3,4,5]}
}
Where the targets denote the identify of the cmp instruction to target (i.e., the id assigned by the __angora_trace_cmp()
calls) and edges is the overlay graph of cmp ids (i.e., which cmps are connected to each other). The edges
filed can be empty, since ParmeSan will add newly discovered edges automatically, but note that the performance will be better if you provide the static CFG.
It is also possible to run ParmeSan in pure directed mode (-D
option),
meaning that it will only consider new seeds if the seed triggers coverage that
is on a direct path to one of the specified targets. Note that this requires a
somewhat complete static CFG to work (an incomplete CFG might contain no paths
to the targets at all, which would mean that no new coverage will be considered
at all).
How to get started
Have a look at BUILD_TARGET.md for a step-by-step tutorial on how to get started fuzzing with ParmeSan.
FAQ
- Q: I get a warning like
==1561377==WARNING: DataFlowSanitizer: call to uninstrumented function gettext
when running the (track) instrumented program. - A: In many cases you can ignore this, but it will lose the taint (meaning worse performance). You need to add the function to the abilist (e.g.,
llvm_mode/dfsan_rt/dfsan/done_abilist.txt
) and add a custom DFSan wrapper (inllvm_mode/dfsan_rt/dfsan/dfsan_custom.cc
). See the Angora documentation for more info. - Q: I get an compiler error when building the track binary.
- A: ParmeSan/ Angora uses DFSan for dynamic data-flow analysis. In certain cases building target applications can be a bit tricky (especially in the case of C++ targets). Make sure to disable as much inline assembly as possible and make sure that you link the correct libraries/ llvm libc++. Some programs also do weird stuff like an indirect call to a vararg function. This is not supported by DFSan at the moment, so the easy solution is to patch out these calls, or do something like indirect call promotion.
- Q:
llvm-diff-parmesan
generates too many targets! - A: You can do target pruning using the scripts in
tools/
(in particulartools/prune.py
) or use ASAP to generate a target bitcode file with fewer sanitizer targets.
Docker image
You can also get the pre-built docker image of ParmeSan.
docker pull vusec/parmesan
docker run --rm -it vusec/parmesan
# In the container you can build objdump
/parmesan/misc/build_objdump.sh