mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-06 23:31:33 +00:00
388 lines
9.6 KiB
Bash
Executable File
388 lines
9.6 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# american fuzzy lop++ - QEMU build script
|
|
# --------------------------------------
|
|
#
|
|
# Originally written by Andrew Griffiths <agriffiths@google.com> and
|
|
# Michal Zalewski
|
|
#
|
|
# TCG instrumentation and block chaining support by Andrea Biondo
|
|
# <andrea.biondo965@gmail.com>
|
|
#
|
|
# QEMU 5+ port, TCG thread-safety, CompareCoverage and NeverZero
|
|
# counters by Andrea Fioraldi <andreafioraldi@gmail.com>
|
|
#
|
|
# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
|
# Copyright 2019-2023 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:
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# This script downloads, patches, and builds a version of QEMU with
|
|
# minor tweaks to allow non-instrumented binaries to be run under
|
|
# afl-fuzz.
|
|
#
|
|
# The modifications reside in patches/*. The standalone QEMU binary
|
|
# will be written to ../afl-qemu-trace.
|
|
#
|
|
|
|
QEMUAFL_VERSION="$(cat ./QEMUAFL_VERSION)"
|
|
|
|
echo "================================================="
|
|
echo " QemuAFL build script"
|
|
echo "================================================="
|
|
echo
|
|
|
|
echo "[*] Performing basic sanity checks..."
|
|
|
|
if [ ! "`uname -s`" = "Linux" ]; then
|
|
|
|
echo "[-] Error: QEMU instrumentation is supported only on Linux."
|
|
exit 0
|
|
|
|
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
|
|
|
|
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 qemuafl is checked out"
|
|
|
|
git status 1>/dev/null 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
echo "[*] initializing qemuafl submodule"
|
|
git submodule init || exit 1
|
|
git submodule update ./qemuafl 2>/dev/null # ignore errors
|
|
else
|
|
echo "[*] cloning qemuafl"
|
|
test -d qemuafl/.git || {
|
|
CNT=1
|
|
while [ '!' -d qemuafl/.git -a "$CNT" -lt 4 ]; do
|
|
echo "Trying to clone qemuafl (attempt $CNT/3)"
|
|
git clone --depth 1 https://github.com/AFLplusplus/qemuafl
|
|
CNT=`expr "$CNT" + 1`
|
|
done
|
|
}
|
|
fi
|
|
|
|
test -e qemuafl/.git || { echo "[-] Not checked out, please install git or check your internet connection." ; exit 1 ; }
|
|
echo "[+] Got qemuafl."
|
|
|
|
cd "qemuafl" || exit 1
|
|
if [ -n "$NO_CHECKOUT" ]; then
|
|
echo "[*] Skipping checkout to $QEMUAFL_VERSION"
|
|
else
|
|
echo "[*] Checking out $QEMUAFL_VERSION"
|
|
sh -c 'git stash' 1>/dev/null 2>/dev/null
|
|
git pull
|
|
git checkout "$QEMUAFL_VERSION" || echo Warning: could not check out to commit $QEMUAFL_VERSION
|
|
fi
|
|
|
|
echo "[*] Making sure imported headers matches"
|
|
cp "../../include/config.h" "./qemuafl/imported/" || exit 1
|
|
cp "../../include/cmplog.h" "./qemuafl/imported/" || exit 1
|
|
cp "../../include/snapshot-inl.h" "./qemuafl/imported/" || exit 1
|
|
cp "../../include/types.h" "./qemuafl/imported/" || exit 1
|
|
|
|
if [ -n "$HOST" ]; then
|
|
echo "[+] Configuring host architecture to $HOST..."
|
|
CROSS_PREFIX=$HOST-
|
|
else
|
|
CROSS_PREFIX=
|
|
fi
|
|
|
|
echo "[*] Configuring QEMU for $CPU_TARGET..."
|
|
|
|
ORIG_CPU_TARGET="$CPU_TARGET"
|
|
|
|
if [ "$ORIG_CPU_TARGET" = "" ]; then
|
|
CPU_TARGET="`uname -m`"
|
|
test "$CPU_TARGET" = "i686" && CPU_TARGET="i386"
|
|
test "$CPU_TARGET" = "arm64v8" && CPU_TARGET="aarch64"
|
|
case "$CPU_TARGET" in
|
|
*arm*)
|
|
CPU_TARGET="arm"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
echo "Building for CPU target $CPU_TARGET"
|
|
|
|
# --enable-pie seems to give a couple of exec's a second performance
|
|
# improvement, much to my surprise. Not sure how universal this is..
|
|
QEMU_CONF_FLAGS=" \
|
|
--audio-drv-list= \
|
|
--disable-blobs \
|
|
--disable-bochs \
|
|
--disable-brlapi \
|
|
--disable-bsd-user \
|
|
--disable-bzip2 \
|
|
--disable-cap-ng \
|
|
--disable-cloop \
|
|
--disable-curl \
|
|
--disable-curses \
|
|
--disable-dmg \
|
|
--disable-fdt \
|
|
--disable-gcrypt \
|
|
--disable-glusterfs \
|
|
--disable-gnutls \
|
|
--disable-gtk \
|
|
--disable-guest-agent \
|
|
--disable-iconv \
|
|
--disable-libiscsi \
|
|
--disable-libnfs \
|
|
--disable-libssh \
|
|
--disable-libusb \
|
|
--disable-linux-aio \
|
|
--disable-live-block-migration \
|
|
--disable-lzo \
|
|
--disable-nettle \
|
|
--disable-numa \
|
|
--disable-opengl \
|
|
--disable-parallels \
|
|
--disable-plugins \
|
|
--disable-qcow1 \
|
|
--disable-qed \
|
|
--disable-rbd \
|
|
--disable-rdma \
|
|
--disable-replication \
|
|
--disable-sdl \
|
|
--disable-seccomp \
|
|
--disable-sheepdog \
|
|
--disable-smartcard \
|
|
--disable-snappy \
|
|
--disable-spice \
|
|
--disable-system \
|
|
--disable-tools \
|
|
--disable-tpm \
|
|
--disable-usb-redir \
|
|
--disable-vde \
|
|
--disable-vdi \
|
|
--disable-vhost-crypto \
|
|
--disable-vhost-kernel \
|
|
--disable-vhost-net \
|
|
--disable-vhost-scsi \
|
|
--disable-vhost-user \
|
|
--disable-vhost-vdpa \
|
|
--disable-vhost-vsock \
|
|
--disable-virglrenderer \
|
|
--disable-virtfs \
|
|
--disable-vnc \
|
|
--disable-vnc-jpeg \
|
|
--disable-vnc-png \
|
|
--disable-vnc-sasl \
|
|
--disable-vte \
|
|
--disable-vvfat \
|
|
--disable-xen \
|
|
--disable-xen-pci-passthrough \
|
|
--disable-xfsctl \
|
|
--target-list="${CPU_TARGET}-linux-user" \
|
|
--without-default-devices \
|
|
"
|
|
|
|
if [ -n "${CROSS_PREFIX}" ]; then
|
|
|
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS --cross-prefix=$CROSS_PREFIX"
|
|
|
|
fi
|
|
|
|
if [ "$STATIC" = "1" ]; then
|
|
|
|
echo Building STATIC binary
|
|
|
|
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
|
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
|
--static --disable-pie \
|
|
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
|
|
"
|
|
|
|
else
|
|
|
|
QEMU_CONF_FLAGS="${QEMU_CONF_FLAGS} --enable-pie "
|
|
|
|
fi
|
|
|
|
if [ "$DEBUG" = "1" ]; then
|
|
|
|
echo Building DEBUG binary
|
|
|
|
# --enable-gcov might go here but incurs a mesonbuild error on meson
|
|
# versions prior to 0.56:
|
|
# https://github.com/qemu/meson/commit/903d5dd8a7dc1d6f8bef79e66d6ebc07c
|
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
|
--disable-strip \
|
|
--enable-debug \
|
|
--enable-debug-info \
|
|
--enable-debug-mutex \
|
|
--enable-debug-stack-usage \
|
|
--enable-debug-tcg \
|
|
--enable-qom-cast-debug \
|
|
--enable-werror \
|
|
"
|
|
|
|
else
|
|
|
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
|
--disable-debug-info \
|
|
--disable-debug-mutex \
|
|
--disable-debug-tcg \
|
|
--disable-qom-cast-debug \
|
|
--disable-stack-protector \
|
|
--disable-werror \
|
|
--disable-docs \
|
|
"
|
|
|
|
fi
|
|
|
|
if [ "$PROFILING" = "1" ]; then
|
|
|
|
echo Building PROFILED binary
|
|
|
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
|
--enable-gprof \
|
|
--enable-profiler \
|
|
"
|
|
|
|
fi
|
|
|
|
# shellcheck disable=SC2086
|
|
./configure $QEMU_CONF_FLAGS || exit 1
|
|
|
|
echo "[+] Configuration complete."
|
|
|
|
echo "[*] Attempting to build QEMU (fingers crossed!)..."
|
|
|
|
make -j$(nproc) || exit 1
|
|
|
|
echo "[+] Build process successful!"
|
|
|
|
echo "[*] Copying binary..."
|
|
|
|
cp -f "build/${CPU_TARGET}-linux-user/qemu-${CPU_TARGET}" "../../afl-qemu-trace" || exit 1
|
|
|
|
cd ..
|
|
ls -l ../afl-qemu-trace || exit 1
|
|
|
|
echo "[+] Successfully created '../afl-qemu-trace'."
|
|
|
|
if [ "$ORIG_CPU_TARGET" = "" ]; then
|
|
|
|
echo "[*] Testing the build..."
|
|
|
|
cd ..
|
|
|
|
make >/dev/null || exit 1
|
|
|
|
cc test-instr.c -o test-instr || exit 1
|
|
|
|
unset AFL_INST_RATIO
|
|
export ASAN_OPTIONS=detect_leaks=0
|
|
|
|
echo "[*] Comparing two afl-showmap -Q outputs..."
|
|
echo 0 | ./afl-showmap -m none -Q -q -o .test-instr0 ./test-instr || exit 1
|
|
echo 1 | ./afl-showmap -m none -Q -q -o .test-instr1 ./test-instr || exit 1
|
|
|
|
rm -f test-instr
|
|
|
|
cmp -s .test-instr0 .test-instr1
|
|
DR="$?"
|
|
|
|
rm -f .test-instr0 .test-instr1
|
|
|
|
if [ "$DR" = "0" ]; then
|
|
|
|
echo "[-] Error: afl-qemu-trace instrumentation doesn't seem to work!"
|
|
exit 1
|
|
|
|
fi
|
|
|
|
echo "[+] Instrumentation tests passed. "
|
|
echo "[+] All set, you can now use the -Q mode in afl-fuzz!"
|
|
|
|
cd qemu_mode || exit 1
|
|
|
|
else
|
|
|
|
echo "[!] Note: can't test instrumentation when CPU_TARGET set."
|
|
echo "[+] All set, you can now (hopefully) use the -Q mode in afl-fuzz!"
|
|
|
|
fi
|
|
|
|
ORIG_CROSS="$CROSS"
|
|
|
|
if [ "$ORIG_CROSS" = "" ]; then
|
|
CROSS=$CPU_TARGET-linux-gnu-gcc
|
|
if ! command -v "$CROSS" > /dev/null
|
|
then # works on Arch Linux
|
|
CROSS=$CPU_TARGET-pc-linux-gnu-gcc
|
|
fi
|
|
if ! command -v "$CROSS" > /dev/null && [ "$CPU_TARGET" = "i386" ]
|
|
then
|
|
CROSS=i686-linux-gnu-gcc
|
|
if ! command -v "$CROSS" > /dev/null
|
|
then # works on Arch Linux
|
|
CROSS=i686-pc-linux-gnu-gcc
|
|
fi
|
|
if ! command -v "$CROSS" > /dev/null && [ "`uname -m`" = "x86_64" ]
|
|
then # set -m32
|
|
test "$CC" = "" && CC="gcc"
|
|
CROSS="$CC"
|
|
CROSS_FLAGS=-m32
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if ! command -v "$CROSS" > /dev/null ; then
|
|
if [ "$CPU_TARGET" = "$(uname -m)" ] ; then
|
|
echo "[+] Building AFL++ qemu support libraries with CC=$CC"
|
|
echo "[+] Building libcompcov ..."
|
|
make -C libcompcov && echo "[+] libcompcov ready"
|
|
echo "[+] Building unsigaction ..."
|
|
make -C unsigaction && echo "[+] unsigaction ready"
|
|
echo "[+] Building fastexit ..."
|
|
make -C fastexit && echo "[+] fastexit ready"
|
|
echo "[+] Building libqasan ..."
|
|
make -C libqasan && echo "[+] libqasan ready"
|
|
echo "[+] Building qemu libfuzzer helpers ..."
|
|
make -C ../utils/aflpp_driver
|
|
else
|
|
echo "[!] Cross compiler $CROSS could not be found, cannot compile libcompcov libqasan and unsigaction"
|
|
fi
|
|
else
|
|
echo "[+] Building AFL++ qemu support libraries with CC=\"$CROSS $CROSS_FLAGS\""
|
|
echo "[+] Building libcompcov ..."
|
|
make -C libcompcov CC="$CROSS $CROSS_FLAGS" && echo "[+] libcompcov ready"
|
|
echo "[+] Building unsigaction ..."
|
|
make -C unsigaction CC="$CROSS $CROSS_FLAGS" && echo "[+] unsigaction ready"
|
|
echo "[+] Building fastexit ..."
|
|
make -C fastexit CC="$CROSS $CROSS_FLAGS" && echo "[+] fastexit ready"
|
|
echo "[+] Building libqasan ..."
|
|
make -C libqasan CC="$CROSS $CROSS_FLAGS" && echo "[+] libqasan ready"
|
|
fi
|
|
|
|
echo "[+] All done for qemu_mode, enjoy!"
|
|
|
|
exit 0
|