Directed Greybox Fuzzing with AFL
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 26 commits ahead, 3 commits behind mirrorer:master.
mboehme Update afl-clang-fast.c
Removed compiler optimization (-O3). Otherwise, the instrumentation may miss some target locations. 
See Issue #34 . Thanks @z1w (Zi Wang).
Latest commit d98ad65 Aug 16, 2018
Failed to load latest commit information.
dictionaries 2.46b Jul 29, 2017
docs 2.49b Jul 29, 2017
experimental 2.48b Jul 29, 2017
libdislocator 2.46b Jul 29, 2017
libtokencap 2.46b Jul 29, 2017
llvm_mode Update afl-clang-fast.c Aug 16, 2018
qemu_mode 2.37b Feb 6, 2017
scripts Execute script with Python3 Aug 18, 2017
testcases 2.28b Aug 7, 2016
.gitignore Make afl-tmin compatible with aflgo. May 28, 2018
Makefile AFLGo initial commit Aug 14, 2017
QuickStartGuide.txt 1.87b Aug 26, 2015
README 0.47b Dec 2, 2014 Typo spotted by @yyyyxf. Closes Issue #10. Nov 24, 2017
afl-analyze.c 2.48b Jul 29, 2017
afl-as.c 2.44b Jul 2, 2017
afl-as.h 2.19b Jul 24, 2016
afl-cmin 2.48b Jul 29, 2017
afl-fuzz.c AFLGo initial commit Aug 14, 2017
afl-gcc.c 2.45b Jul 29, 2017
afl-gotcpu.c 2.11b May 21, 2016
afl-plot 2.48b Jul 29, 2017
afl-showmap.c 2.45b Jul 29, 2017
afl-tmin.c Make afl-tmin compatible with aflgo. May 28, 2018
afl-whatsup 2.36b Jan 16, 2017
alloc-inl.h 1.94b Sep 12, 2015
config.h Update config.h Aug 19, 2017
debug.h 2.03b Mar 2, 2016
hash.h 2.15b Jul 24, 2016
hashset.h Adding hashset.h as per Issue #7 Oct 11, 2017
test-instr.c 0.47b Dec 2, 2014
types.h 2.42b Jun 18, 2017

AFLGo: Directed Greybox Fuzzing

AFLGo is an extension of American Fuzzy Lop (AFL). Given a set of target locations (e.g., folder/file.c:582), AFLGo generates inputs specifically with the objective to exercise these target locations.

Unlike AFL, AFLGo spends most of its time budget on reaching specific target locations without wasting resources stressing unrelated program components. This is particularly interesting in the context of

  • patch testing by setting changed statements as targets. When a critical component is changed, we would like to check whether this introduced any vulnerabilities. AFLGo, a fuzzer that can focus on those changes, has a higher chance of exposing the regression.
  • static analysis report verification by setting statements as targets that a static analysis reports as potentially dangerous or vulnerability-inducing. When assessing the security of a program, static analysis tools might identify dangerous locations, such as critical system calls. AFLGo can generate inputs that actually show that this is indeed no false positive.
  • information flow detection by setting sensitive sources and sinks as targets. To expose data leakage vulnerabilities, a security researcher would like to generate executions that exercise sensitive sources containing private information and sensitive sinks where data becomes visible to the outside world. A directed fuzzer can be used to generate such executions efficiently.
  • crash reproduction by setting method calls in the stack-trace as targets. When in-field crashes are reported, only the stack-trace and some environmental parameters are sent to the in-house development team. To preserve the user's privacy, the specific crashing input is often not available. AFLGo could help the in-house team to swiftly reproduce these crashes.

AFLGo is based on AFL from Michał Zaleski <>.

Integration into OSS-Fuzz

The easiest way to use AFLGo is as patch testing tool in OSS-Fuzz. Here is our integration:

Environment Variables

  • AFLGO_INST_RATIO -- The proportion of basic blocks instrumented with distance values (default: 100).
  • AFLGO_SELECTIVE -- Add AFL-trampoline only to basic blocks with distance values? (default: off).
  • AFLGO_PROFILING_FILE -- When CFG-tracing is enabled, the data will be stored here.

How to instrument a Binary with AFLGo

  1. Install LLVM with Gold-plugin. You can also follow these instructions.
  2. Install other prerequisite
sudo apt-get update
sudo apt-get install python3
sudo apt-get install python3-dev
sudo apt-get install python3-pip
sudo pip3 install --upgrade pip
sudo pip3 install networkx
sudo pip3 install pydot
sudo pip3 install pydotplus
  1. Compile AFLGo fuzzer and LLVM-instrumentation pass
# Checkout source code
git clone
export AFLGO=$PWD/aflgo

# Compile source code
pushd $AFLGO
make clean all 
cd llvm_mode
make clean all
  1. Download subject (e.g., libxml2)
# Clone subject repository
git clone git://
export SUBJECT=$PWD/libxml2
  1. Set targets (e.g., changed statements in commit ef709ce2). Writes BBtargets.txt.
# Setup directory containing all temporary files
mkdir temp
export TMP_DIR=$PWD/temp

# Download commit-analysis tool
chmod +x showlinenum.awk
mv showlinenum.awk $TMP_DIR

# Generate BBtargets from commit ef709ce2
pushd $SUBJECT
  git checkout ef709ce2
  git diff -U0 HEAD^ HEAD > $TMP_DIR/commit.diff
cat $TMP_DIR/commit.diff |  $TMP_DIR/showlinenum.awk show_header=0 path=1 | grep -e "\.[ch]:[0-9]*:+" -e "\.cpp:[0-9]*:+" -e "\.cc:[0-9]*:+" | cut -d+ -f1 | rev | cut -c2- | rev > $TMP_DIR/BBtargets.txt

# Print extracted targets. 
echo "Targets:"
cat $TMP_DIR/BBtargets.txt
  1. Note: If there are no targets, there is nothing to instrument!
  2. Generate CG and intra-procedural CFGs from subject (i.e., libxml2).
# Set aflgo-instrumenter
export CC=$AFLGO/afl-clang-fast
export CXX=$AFLGO/afl-clang-fast++

# Set aflgo-instrumentation flags
export ADDITIONAL="-targets=$TMP_DIR/BBtargets.txt -outdir=$TMP_DIR -flto -fuse-ld=gold -Wl,-plugin-opt=save-temps"

# Build libxml2 (in order to generate CG and CFGs).
# Meanwhile go have a coffee ☕️
export LDFLAGS=-lpthread
pushd $SUBJECT
  ./configure --disable-shared
  make -j$(nproc) clean
  make -j$(nproc) all
# * If the linker (CCLD) complains that you should run ranlib, make
#   sure that and (from building LLVM with Gold)
#   can be found in /usr/lib/bfd-plugins
# * If the compiler crashes, there is some problem with LLVM not 
#   supporting our instrumentation (
#   LLVM has changed the instrumentation-API very often :(
#   -> Check LLVM-version, fix problem, and prepare pull request.

# Test whether CG/CFG extraction was successful
$SUBJECT/xmllint --valid --recover $SUBJECT/test/dtd3
ls $TMP_DIR/dot-files
echo "Function targets"
cat $TMP_DIR/Ftargets.txt

# Clean up
cat $TMP_DIR/BBnames.txt | rev | cut -d: -f2- | rev | sort | uniq > $TMP_DIR/BBnames2.txt && mv $TMP_DIR/BBnames2.txt $TMP_DIR/BBnames.txt
cat $TMP_DIR/BBcalls.txt | sort | uniq > $TMP_DIR/BBcalls2.txt && mv $TMP_DIR/BBcalls2.txt $TMP_DIR/BBcalls.txt

# Generate distance ☕️
$AFLGO/scripts/ $SUBJECT $TMP_DIR xmllint

# Check distance file
echo "Distance values:"
head -n5 $TMP_DIR/distance.cfg.txt
echo "..."
tail -n5 $TMP_DIR/distance.cfg.txt
  1. Note: If distance.cfg.txt is empty, there was some problem computing the CG-level and BB-level target distance. See $TMP_DIR/step*.
  2. Instrument subject (i.e., libxml2)
export CFLAGS="$COPY_CFLAGS -distance=$TMP_DIR/distance.cfg.txt"
export CXXFLAGS="$COPY_CXXFLAGS -distance=$TMP_DIR/distance.cfg.txt"

# Clean and build subject with distance instrumentation ☕️
pushd $SUBJECT
  make clean
  ./configure --disable-shared
  make -j$(nproc) all

How to fuzz the instrumented binary

  • We set the exponential annealing-based power schedule (-z exp).
  • We set the time-to-exploitation to 45min (-c 45m), assuming the fuzzer is run for about an hour.
# Construct seed corpus
mkdir in
cp $SUBJECT/test/dtd* in
cp $SUBJECT/test/dtds/* in

$AFLGO/afl-fuzz -S ef709ce2 -z exp -c 45m -i in -o out $SUBJECT/xmllint --valid --recover @@
  • Tipp: Concurrently fuzz the most recent version as master with classical AFL :)
$AFL/afl-fuzz -M master -i in -o out $MASTER/xmllint --valid --recover @@