nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ lib, stdenv, stdenvNoCC, fetchFromGitHub, callPackage, makeWrapper
2, clang, llvm, gcc, which, libcgroup, python3, perl, gmp
3, file, wine ? null, fetchpatch
4, cmocka
5, llvmPackages
6}:
7
8# wine fuzzing is only known to work for win32 binaries, and using a mixture of
9# 32 and 64-bit libraries ... complicates things, so it's recommended to build
10# a full 32bit version of this package if you want to do wine fuzzing
11assert (wine != null) -> (stdenv.targetPlatform.system == "i686-linux");
12
13let
14 aflplusplus-qemu = callPackage ./qemu.nix { inherit aflplusplus; };
15 qemu-exe-name = if stdenv.targetPlatform.system == "x86_64-linux" then "qemu-x86_64"
16 else if stdenv.targetPlatform.system == "i686-linux" then "qemu-i386"
17 else throw "aflplusplus: no support for ${stdenv.targetPlatform.system}!";
18 libdislocator = callPackage ./libdislocator.nix { inherit aflplusplus; };
19 libtokencap = callPackage ./libtokencap.nix { inherit aflplusplus; };
20 aflplusplus = stdenvNoCC.mkDerivation rec {
21 pname = "aflplusplus";
22 version = "4.06c";
23
24 src = fetchFromGitHub {
25 owner = "AFLplusplus";
26 repo = "AFLplusplus";
27 rev = version;
28 sha256 = "sha256-Gb1nYDBnwLS+m8e1UD0WLIrnp8KRgliGQVvQD22JXrQ=";
29 };
30 enableParallelBuilding = true;
31
32 # Note: libcgroup isn't needed for building, just for the afl-cgroup
33 # script.
34 nativeBuildInputs = [ makeWrapper which clang gcc ];
35 buildInputs = [ llvm python3 gmp llvmPackages.bintools ]
36 ++ lib.optional (wine != null) python3.pkgs.wrapPython;
37
38 # Flag is already set by package and causes some compiler warnings.
39 # warning: "_FORTIFY_SOURCE" redefined
40 hardeningDisable = [ "fortify" ];
41
42 postPatch = ''
43 # Don't care about this.
44 rm Android.bp
45
46 # Replace the CLANG_BIN variables with the correct path.
47 # Replace "gcc" and friends with full paths in afl-gcc.
48 # Prevents afl-gcc picking up any (possibly incorrect) gcc from the path.
49 # Replace LLVM_BINDIR with a non-existing path to give a hard error when it's used.
50 substituteInPlace src/afl-cc.c \
51 --replace "CLANGPP_BIN" '"${clang}/bin/clang++"' \
52 --replace "CLANG_BIN" '"${clang}/bin/clang"' \
53 --replace '"gcc"' '"${gcc}/bin/gcc"' \
54 --replace '"g++"' '"${gcc}/bin/g++"' \
55 --replace 'getenv("AFL_PATH")' "(getenv(\"AFL_PATH\") ? getenv(\"AFL_PATH\") : \"$out/lib/afl\")"
56
57 substituteInPlace src/afl-ld-lto.c \
58 --replace 'LLVM_BINDIR' '"/nixpkgs-patched-does-not-exist"'
59
60 # Remove the rest of the line
61 sed -i 's|LLVM_BINDIR = .*|LLVM_BINDIR = |' utils/aflpp_driver/GNUmakefile
62 substituteInPlace utils/aflpp_driver/GNUmakefile \
63 --replace 'LLVM_BINDIR = ' 'LLVM_BINDIR = ${clang}/bin/'
64
65 substituteInPlace GNUmakefile.llvm \
66 --replace "\$(LLVM_BINDIR)/clang" "${clang}/bin/clang"
67 '';
68
69 env.NIX_CFLAGS_COMPILE = toString [
70 # Needed with GCC 12
71 "-Wno-error=use-after-free"
72 ];
73
74 makeFlags = [
75 "PREFIX=$(out)"
76 "USE_BINDIR=0"
77 ];
78 buildPhase = ''
79 runHook preBuild
80
81 common="$makeFlags -j$NIX_BUILD_CORES"
82 make distrib $common
83 make -C qemu_mode/libcompcov $common
84 make -C qemu_mode/unsigaction $common
85
86 runHook postBuild
87 '';
88
89 postInstall = ''
90 # remove afl-clang(++) which are just symlinks to afl-clang-fast
91 rm $out/bin/afl-clang $out/bin/afl-clang++
92
93 # the makefile neglects to install unsigaction
94 cp qemu_mode/unsigaction/unsigaction*.so $out/lib/afl/
95
96 # Install the custom QEMU emulator for binary blob fuzzing.
97 ln -s ${aflplusplus-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
98
99 # give user a convenient way of accessing libcompconv.so, libdislocator.so, libtokencap.so
100 cat > $out/bin/get-afl-qemu-libcompcov-so <<END
101 #!${stdenv.shell}
102 echo $out/lib/afl/libcompcov.so
103 END
104 chmod +x $out/bin/get-afl-qemu-libcompcov-so
105 ln -s ${libdislocator}/bin/get-libdislocator-so $out/bin/
106 ln -s ${libtokencap}/bin/get-libtokencap-so $out/bin/
107
108 # Install the cgroups wrapper for asan-based fuzzing.
109 cp utils/asan_cgroups/limit_memory.sh $out/bin/afl-cgroup
110 chmod +x $out/bin/afl-cgroup
111 substituteInPlace $out/bin/afl-cgroup \
112 --replace "cgcreate" "${libcgroup}/bin/cgcreate" \
113 --replace "cgexec" "${libcgroup}/bin/cgexec" \
114 --replace "cgdelete" "${libcgroup}/bin/cgdelete"
115
116 patchShebangs $out/bin
117
118 '' + lib.optionalString (wine != null) ''
119 substitute afl-wine-trace $out/bin/afl-wine-trace \
120 --replace "qemu_mode/unsigaction" "$out/lib/afl"
121 chmod +x $out/bin/afl-wine-trace
122
123 # qemu needs to be fed ELFs, not wrapper scripts, so we have to cheat a bit if we
124 # detect a wrapped wine
125 for winePath in ${wine}/bin/.wine ${wine}/bin/wine; do
126 if [ -x $winePath ]; then break; fi
127 done
128 makeWrapperArgs="--set-default 'AFL_WINE_PATH' '$winePath'" \
129 wrapPythonProgramsIn $out/bin ${python3.pkgs.pefile}
130 '';
131
132 nativeInstallCheckInputs = [ perl file cmocka ];
133 doInstallCheck = true;
134 installCheckPhase = ''
135 runHook preInstallCheck
136
137 # replace references to tools in build directory with references to installed locations
138 substituteInPlace test/test-qemu-mode.sh \
139 --replace '../libcompcov.so' '`$out/bin/get-afl-qemu-libcompcov-so`' \
140 --replace '../afl-qemu-trace' '$out/bin/afl-qemu-trace' \
141 --replace '../afl-fuzz' '$out/bin/afl-fuzz' \
142 --replace '../qemu_mode/unsigaction/unsigaction32.so' '$out/lib/afl/unsigaction32.so' \
143 --replace '../qemu_mode/unsigaction/unsigaction64.so' '$out/lib/afl/unsigaction64.so'
144
145 substituteInPlace test/test-libextensions.sh \
146 --replace '../libdislocator.so' '`$out/bin/get-libdislocator-so`' \
147 --replace '../libtokencap.so' '`$out/bin/get-libtokencap-so`'
148 substituteInPlace test/test-llvm.sh \
149 --replace '../afl-cmin.bash' '`$out/bin/afl-cmin.bash`'
150 # perl -pi -e 's|(?<!\.)(?<!-I)(\.\./)([^\s\/]+?)(?<!\.c)(?<!\.s?o)(?=\s)|\$out/bin/\2|g' test/test.sh
151 patchShebangs .
152 cd test && ./test-all.sh
153
154 runHook postInstallCheck
155 '';
156
157 passthru = {
158 inherit libdislocator libtokencap;
159 qemu = aflplusplus-qemu;
160 };
161
162 meta = {
163 description = ''
164 A heavily enhanced version of AFL, incorporating many features
165 and improvements from the community
166 '';
167 homepage = "https://aflplus.plus";
168 license = lib.licenses.asl20;
169 platforms = ["x86_64-linux" "i686-linux"];
170 maintainers = with lib.maintainers; [ ris mindavi ];
171 };
172 };
173in aflplusplus