136 lines
5.4 KiB
Nix
136 lines
5.4 KiB
Nix
{ lib, stdenv, stdenvNoCC, fetchFromGitHub, callPackage, makeWrapper
|
|
, clang, llvm, gcc, which, libcgroup, python, perl, gmp
|
|
, file, wine ? null, fetchpatch
|
|
}:
|
|
|
|
# wine fuzzing is only known to work for win32 binaries, and using a mixture of
|
|
# 32 and 64-bit libraries ... complicates things, so it's recommended to build
|
|
# a full 32bit version of this package if you want to do wine fuzzing
|
|
assert (wine != null) -> (stdenv.targetPlatform.system == "i686-linux");
|
|
|
|
let
|
|
aflplusplus-qemu = callPackage ./qemu.nix { inherit aflplusplus; };
|
|
qemu-exe-name = if stdenv.targetPlatform.system == "x86_64-linux" then "qemu-x86_64"
|
|
else if stdenv.targetPlatform.system == "i686-linux" then "qemu-i386"
|
|
else throw "aflplusplus: no support for ${stdenv.targetPlatform.system}!";
|
|
libdislocator = callPackage ./libdislocator.nix { inherit aflplusplus; };
|
|
libtokencap = callPackage ./libtokencap.nix { inherit aflplusplus; };
|
|
aflplusplus = stdenvNoCC.mkDerivation rec {
|
|
pname = "aflplusplus";
|
|
version = "2.65c";
|
|
|
|
src = fetchFromGitHub {
|
|
owner = "AFLplusplus";
|
|
repo = "AFLplusplus";
|
|
rev = version;
|
|
sha256 = "1np2a3kypb2m8nyv6qnij18yzn41pl8619jzydci40br4vxial9l";
|
|
};
|
|
enableParallelBuilding = true;
|
|
|
|
# Note: libcgroup isn't needed for building, just for the afl-cgroup
|
|
# script.
|
|
nativeBuildInputs = [ makeWrapper which clang gcc ];
|
|
buildInputs = [ llvm python gmp ]
|
|
++ lib.optional (wine != null) python.pkgs.wrapPython;
|
|
|
|
|
|
postPatch = ''
|
|
# Replace the CLANG_BIN variables with the correct path
|
|
substituteInPlace llvm_mode/afl-clang-fast.c \
|
|
--replace "CLANGPP_BIN" '"${clang}/bin/clang++"' \
|
|
--replace "CLANG_BIN" '"${clang}/bin/clang"' \
|
|
--replace 'getenv("AFL_PATH")' "(getenv(\"AFL_PATH\") ? getenv(\"AFL_PATH\") : \"$out/lib/afl\")"
|
|
|
|
# Replace "gcc" and friends with full paths in afl-gcc
|
|
# Prevents afl-gcc picking up any (possibly incorrect) gcc from the path
|
|
substituteInPlace src/afl-gcc.c \
|
|
--replace '"gcc"' '"${gcc}/bin/gcc"' \
|
|
--replace '"g++"' '"${gcc}/bin/g++"' \
|
|
--replace '"gcj"' '"gcj-UNSUPPORTED"' \
|
|
--replace '"clang"' '"clang-UNSUPPORTED"' \
|
|
--replace '"clang++"' '"clang++-UNSUPPORTED"'
|
|
'';
|
|
|
|
makeFlags = [ "PREFIX=$(out)" ];
|
|
buildPhase = ''
|
|
common="$makeFlags -j$NIX_BUILD_CORES"
|
|
make all $common
|
|
make radamsa $common
|
|
make -C gcc_plugin CC=${gcc}/bin/gcc CXX=${gcc}/bin/g++ $common
|
|
make -C llvm_mode $common
|
|
make -C qemu_mode/libcompcov $common
|
|
make -C qemu_mode/unsigaction $common
|
|
'';
|
|
|
|
postInstall = ''
|
|
# remove afl-clang(++) which are just symlinks to afl-clang-fast
|
|
rm $out/bin/afl-clang $out/bin/afl-clang++
|
|
|
|
# the makefile neglects to install unsigaction
|
|
cp qemu_mode/unsigaction/unsigaction*.so $out/lib/afl/
|
|
|
|
# Install the custom QEMU emulator for binary blob fuzzing.
|
|
cp ${aflplusplus-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
|
|
|
|
# give user a convenient way of accessing libcompconv.so, libdislocator.so, libtokencap.so
|
|
cat > $out/bin/get-afl-qemu-libcompcov-so <<END
|
|
#!${stdenv.shell}
|
|
echo $out/lib/afl/libcompcov.so
|
|
END
|
|
chmod +x $out/bin/get-afl-qemu-libcompcov-so
|
|
cp ${libdislocator}/bin/get-libdislocator-so $out/bin/
|
|
cp ${libtokencap}/bin/get-libtokencap-so $out/bin/
|
|
|
|
# Install the cgroups wrapper for asan-based fuzzing.
|
|
cp examples/asan_cgroups/limit_memory.sh $out/bin/afl-cgroup
|
|
chmod +x $out/bin/afl-cgroup
|
|
substituteInPlace $out/bin/afl-cgroup \
|
|
--replace "cgcreate" "${libcgroup}/bin/cgcreate" \
|
|
--replace "cgexec" "${libcgroup}/bin/cgexec" \
|
|
--replace "cgdelete" "${libcgroup}/bin/cgdelete"
|
|
|
|
patchShebangs $out/bin
|
|
|
|
'' + lib.optionalString (wine != null) ''
|
|
substitute afl-wine-trace $out/bin/afl-wine-trace \
|
|
--replace "qemu_mode/unsigaction" "$out/lib/afl"
|
|
chmod +x $out/bin/afl-wine-trace
|
|
|
|
# qemu needs to be fed ELFs, not wrapper scripts, so we have to cheat a bit if we
|
|
# detect a wrapped wine
|
|
for winePath in ${wine}/bin/.wine ${wine}/bin/wine; do
|
|
if [ -x $winePath ]; then break; fi
|
|
done
|
|
makeWrapperArgs="--set-default 'AFL_WINE_PATH' '$winePath'" \
|
|
wrapPythonProgramsIn $out/bin ${python.pkgs.pefile}
|
|
'';
|
|
|
|
installCheckInputs = [ perl file ];
|
|
doInstallCheck = true;
|
|
installCheckPhase = ''
|
|
# replace references to tools in build directory with references to installed locations
|
|
substituteInPlace test/test.sh \
|
|
--replace '../libcompcov.so' '`$out/bin/get-afl-qemu-libcompcov-so`' \
|
|
--replace '../libdislocator.so' '`$out/bin/get-libdislocator-so`' \
|
|
--replace '../libtokencap.so' '`$out/bin/get-libtokencap-so`'
|
|
perl -pi -e 's|(?<!\.)(?<!-I)(\.\./)([^\s\/]+?)(?<!\.c)(?<!\.s?o)(?=\s)|\$out/bin/\2|g' test/test.sh
|
|
cd test && ./test.sh
|
|
'';
|
|
|
|
passthru = {
|
|
inherit libdislocator libtokencap;
|
|
qemu = aflplusplus-qemu;
|
|
};
|
|
|
|
meta = {
|
|
description = ''
|
|
A heavily enhanced version of AFL, incorporating many features
|
|
and improvements from the community
|
|
'';
|
|
homepage = "https://aflplus.plus";
|
|
license = lib.licenses.asl20;
|
|
platforms = ["x86_64-linux" "i686-linux"];
|
|
maintainers = with lib.maintainers; [ ris mindavi ];
|
|
};
|
|
};
|
|
in aflplusplus
|