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