blob: 707e47bb910f911d3ecb090c6c784297238ae66c [file] [log] [blame]
#!/bin/sh
#
# american fuzzy lop++ - unicorn mode build script
# ------------------------------------------------
#
# Originally written by Nathan Voss <njvoss99@gmail.com>
#
# Adapted from code by Andrew Griffiths <agriffiths@google.com> and
# Michal Zalewski
#
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
#
# CompareCoverage and NeverZero counters by Andrea Fioraldi
# <andreafioraldi@gmail.com>
#
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
# Copyright 2019 AFLplusplus Project. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# This script downloads, patches, and builds a version of Unicorn with
# minor tweaks to allow Unicorn-emulated binaries to be run under
# afl-fuzz.
#
# The modifications reside in patches/*. The standalone Unicorn library
# will be written to /usr/lib/libunicornafl.so, and the Python bindings
# will be installed system-wide.
#
# You must make sure that Unicorn Engine is not already installed before
# running this script. If it is, please uninstall it first.
echo "================================================="
echo "Unicorn-AFL build script"
echo "================================================="
echo
echo "[*] Performing basic sanity checks..."
PLT=`uname -s`
if [ ! "$PLT" = "Linux" ] && [ ! "$PLT" = "Darwin" ] && [ ! "$PLT" = "FreeBSD" ] && [ ! "$PLT" = "NetBSD" ] && [ ! "$PLT" = "OpenBSD" ]; then
echo "[-] Error: Unicorn instrumentation is unsupported on $PLT."
exit 1
fi
if [ ! -f "../config.h" ]; then
echo "[-] Error: key files not found - wrong working directory?"
exit 1
fi
if [ ! -f "../afl-showmap" ]; then
echo "[-] Error: ../afl-showmap not found - compile AFL first!"
exit 1
fi
PYTHONBIN=python
MAKECMD=make
EASY_INSTALL='easy_install'
TARCMD=tar
if [ "$PLT" = "Linux" ]; then
CORES=`nproc`
fi
if [ "$PLT" = "Darwin" ]; then
CORES=`sysctl hw.ncpu | cut -d' ' -f2`
TARCMD=tar
fi
if [ "$PLT" = "FreeBSD" ]; then
MAKECMD=gmake
CORES=`sysctl hw.ncpu | cut -d' ' -f2`
TARCMD=gtar
fi
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
MAKECMD=gmake
CORES=`sysctl hw.ncpu | cut -d'=' -f2`
TARCMD=gtar
fi
for i in wget $PYTHONBIN automake autoconf $MAKECMD $TARCMD; do
T=`which "$i" 2>/dev/null`
if [ "$T" = "" ]; then
echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
exit 1
fi
done
if ! which $EASY_INSTALL > /dev/null; then
# work around for unusual installs
if [ '!' -e /usr/lib/python2.7/dist-packages/easy_install.py ] && [ '!' -e /usr/local/lib/python2.7/dist-packages/easy_install.py ] && [ '!' -e /usr/pkg/lib/python2.7/dist-packages/easy_install.py ]; then
echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'."
exit 1
fi
fi
if echo "$CC" | grep -qF /afl-; then
echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
exit 1
fi
echo "[+] All checks passed!"
echo "[*] Making sure unicornafl is checked out"
git submodule init || exit 1
git submodule update || exit 1
echo "[+] Got unicornafl."
echo "[*] making sure config.h matches"
cp "../config.h" "./unicorn/" || exit 1
echo "[*] Configuring Unicorn build..."
cd "unicorn" || exit 1
echo "[+] Configuration complete."
echo "[*] Attempting to build unicornafl (fingers crossed!)..."
$MAKECMD clean # make doesn't seem to work for unicorn
UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD -j$CORES || exit 1
echo "[+] Build process successful!"
echo "[*] Installing Unicorn python bindings..."
cd bindings/python || exit 1
if [ -z "$VIRTUAL_ENV" ]; then
echo "[*] Info: Installing python unicornafl using --user"
$PYTHONBIN setup.py install --user --force --prefix=|| exit 1
else
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
$PYTHONBIN setup.py install --force || exit 1
fi
# export LIBUNICORN_PATH='$(pwd)' # in theory, this allows to switch between afl-unicorn and unicorn so files.
echo '[*] If needed, you can (re)install the bindigns from `./unicorn/bindings/python` using `python setup.py install`'
cd ../../ || exit 1
echo "[*] Unicornafl bindings installed successfully."
# Compile the sample, run it, verify that it works!
echo "[*] Testing unicornafl python functionality by running a sample test harness"
cd ../samples/simple || exit 1
# Run afl-showmap on the sample application. If anything comes out then it must have worked!
unset AFL_INST_RATIO
echo 0 | ../../../afl-showmap -U -m none -q -o .test-instr0 -- $PYTHONBIN simple_test_harness.py ./sample_inputs/sample1.bin || exit 1
if [ -s .test-instr0 ]
then
echo "[+] Instrumentation tests passed. "
echo '[+] Make sure to adapt older scripts to `import unicornafl` and use `uc.afl_forkserver_start`'
echo ' or `uc.afl_fuzz` to kick off fuzzing.'
echo "[+] All set, you can now use Unicorn mode (-U) in afl-fuzz!"
RETVAL=0
else
echo "[-] Error: Unicorn mode doesn't seem to work!"
RETVAL=1
fi
rm -f .test-instr0
exit $RETVAL