[env] PROJECT_DIR = { script = ["pwd"] } CARGO_TARGET_DIR = { value = "${PROJECT_DIR}/target", condition = { env_not_set = [ "CARGO_TARGET_DIR", ] } } PROFILE = { value = "release", condition = { env_not_set = ["PROFILE"] } } PROFILE_DIR = { source = "${PROFILE}", default_value = "release", mapping = { "release" = "release", "dev" = "debug" }, condition = { env_not_set = [ "PROFILE_DIR", ] } } FUZZER_NAME = 'libafl-fuzz' FUZZER = '${CARGO_TARGET_DIR}/${PROFILE_DIR}/${FUZZER_NAME}' LLVM_CONFIG = { value = "llvm-config-18", condition = { env_not_set = [ "LLVM_CONFIG", ] } } AFL_VERSION = "5777ceaf23f48ae4ceae60e4f3a79263802633c6" AFL_DIR = { value = "${PROJECT_DIR}/AFLplusplus" } AFL_CC_PATH = { value = "${AFL_DIR}/afl-clang-fast" } CC = { value = "clang" } [tasks.build_afl] script_runner = "@shell" script = ''' if [ ! -d "$AFL_DIR" ]; then git clone https://github.com/AFLplusplus/AFLplusplus.git cd ${AFL_DIR} git checkout ${AFL_VERSION} LLVM_CONFIG=${LLVM_CONFIG} make fi ''' [tasks.build_frida_mode] script_runner = '@shell' script = ''' cd ${AFL_DIR} cd frida_mode LLVM_CONFIG=${LLVM_CONFIG} make cd ../.. ''' [tasks.build_qemuafl] script_runner = "@shell" script = ''' cd ${AFL_DIR}/qemu_mode ./build_qemu_support.sh cd ../.. ''' dependencies = ["build_afl"] [tasks.build_unicorn_mode] script_runner = "@shell" script = ''' cd ${AFL_DIR}/unicorn_mode ./build_unicorn_support.sh cd ../.. ''' dependencies = ["build_afl"] # Test [tasks.test] linux_alias = "test_unix" mac_alias = "test_unix" windows_alias = "unsupported" [tasks.test_unix] script_runner = "@shell" script = "echo done" dependencies = [ "build_afl", "test_instr", "test_cmplog", "test_frida", "test_qemu", "test_unicorn_mode", # nyx # since we cannot test nyx mode on CI, let's build it # "build_nyx_mode", # fuzzbench "test_instr_fuzzbench", ] [tasks.build_libafl_fuzz] script_runner = "@shell" script = "cargo build --profile ${PROFILE}" [tasks.build_libafl_fuzz_fuzzbench] script_runner = "@shell" script = "cargo build --profile ${PROFILE} --features fuzzbench" [tasks.test_instr] script_runner = "@shell" script = ''' AFL_PATH=${AFL_DIR} ${AFL_CC_PATH} ./test/test-instr.c -o ./test/out-instr export LIBAFL_DEBUG_OUTPUT=1 export AFL_CORES=0 export AFL_STATS_INTERVAL=1 timeout 5 ${FUZZER} -i ./test/seeds -o ./test/output ./test/out-instr || true test -n "$( ls ./test/output/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found" exit 1 } test -n "$( ls ./test/output/fuzzer_main/fuzzer_stats 2>/dev/null )" || { echo "No fuzzer_stats file found" exit 1 } test -n "$( ls ./test/output/fuzzer_main/plot_data 2>/dev/null )" || { echo "No plot_data found" exit 1 } test -d "./test/output/fuzzer_main/hangs" || { echo "No hangs directory found" exit 1 } test -d "./test/output/fuzzer_main/crashes" || { echo "No crashes directory found" exit 1 } ''' dependencies = ["build_afl", "build_libafl_fuzz"] [tasks.test_instr_fuzzbench] script_runner = "@shell" script = ''' AFL_PATH=${AFL_DIR} ${AFL_CC_PATH} ./test/test-instr.c -o ./test/out-instr export LIBAFL_DEBUG_OUTPUT=1 export AFL_CORES=0 export AFL_STATS_INTERVAL=1 timeout 5 ${FUZZER} -i ./test/seeds -o ./test/output-fuzzbench ./test/out-instr || true test -n "$( ls ./test/output-fuzzbench/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found" exit 1 } test -n "$( ls ./test/output-fuzzbench/fuzzer_main/fuzzer_stats 2>/dev/null )" || { echo "No fuzzer_stats file found" exit 1 } test -n "$( ls ./test/output-fuzzbench/fuzzer_main/plot_data 2>/dev/null )" || { echo "No plot_data found" exit 1 } test -d "./test/output-fuzzbench/fuzzer_main/hangs" || { echo "No hangs directory found" exit 1 } test -d "./test/output-fuzzbench/fuzzer_main/crashes" || { echo "No crashes directory found" exit 1 } ''' dependencies = ["build_afl", "build_libafl_fuzz_fuzzbench"] [tasks.test_cmplog] script_runner = "@shell" script = ''' # cmplog TODO: AFL_BENCH_UNTIL_CRASH=1 instead of timeout 15s AFL_LLVM_CMPLOG=1 AFL_PATH=${AFL_DIR} ${AFL_CC_PATH} ./test/test-cmplog.c -o ./test/out-cmplog LIBAFL_DEBUG_OUTPUT=1 AFL_CORES=0 timeout 15 ${FUZZER} -Z -l 3 -m 0 -V30 -i ./test/seeds_cmplog -o ./test/output-cmplog -c 0 ./test/out-cmplog || true test -n "$( ls ${PROJECT_DIR}/test/output-cmplog/fuzzer_main/hangs/id:0000* ${PROJECT_DIR}/test/output-cmplog/fuzzer_main/crashes/id:0000*)" || { echo "No crashes found" exit 1 } ''' dependencies = ["build_afl", "build_libafl_fuzz"] [tasks.test_frida] script_runner = "@shell" script = ''' ${CC} -no-pie ./test/test-instr.c -o ./test/out-frida export AFL_PATH=${AFL_DIR} export AFL_CORES=0 export AFL_STATS_INTERVAL=1 timeout 15 ${FUZZER} -m 0 -O -i ./test/seeds_frida -o ./test/output-frida -- ./test/out-frida || true test -n "$( ls ./test/output-frida/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for FRIDA mode" exit 1 } ${CC} ./test/test-cmpcov.c -o ./test/out-frida-cmpcov AFL_FRIDA_VERBOSE=1 timeout 15 ${FUZZER} -m 0 -O -c 0 -l 3 -i ./test/seeds_frida -o ./test/output-frida-cmpcov -- ./test/out-frida-cmpcov || true test -n "$( ls ./test/output-frida-cmpcov/fuzzer_main/queue/id:000003* 2>/dev/null )" || { echo "No new corpus entries found for FRIDA cmplog mode" exit 1 } export AFL_FRIDA_PERSISTENT_ADDR=0x`nm ./test/out-frida | grep -Ei "T _main|T main" | awk '{print $1}'` timeout 15 ${FUZZER} -m 0 -O -i ./test/seeds_frida -o ./test/output-frida-persistent -- ./test/out-frida || true test -n "$( ls ./test/output-frida-persistent/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for FRIDA persistent mode" exit 1 } RUNTIME_PERSISTENT=`grep execs_done ./test/output-frida-persistent/fuzzer_main/fuzzer_stats | awk '{print$3}'` RUNTIME=`grep execs_done ./test/output-frida/fuzzer_main/fuzzer_stats | awk '{print$3}'` test -n "$RUNTIME" -a -n "$RUNTIME_PERSISTENT" && { DIFF=`expr $RUNTIME_PERSISTENT / $RUNTIME` test "$DIFF" -gt 1 && { # must be at least twice as fast echo "persistent frida_mode was noticeably faster than standard frida_mode" } || { echo "persistent frida_mode" $RUNTIME_PERSISTENT "was not noticeably faster than standard frida_mode" $RUNTIME exit 1 } } || { echo "we got no data on executions performed? weird!" } unset AFL_FRIDA_PERSISTENT_ADDR ''' dependencies = ["build_afl", "build_frida_mode", "build_libafl_fuzz"] [tasks.test_qemu] script_runner = "@shell" script = ''' ${CC} -pie -fPIE ./test/test-instr.c -o ./test/out-qemu ${CC} -o ./test/out-qemu-cmpcov ./test/test-cmpcov.c export AFL_PATH=${AFL_DIR} export AFL_CORES=0 export AFL_STATS_INTERVAL=1 timeout 15 ${FUZZER} -m 0 -Q -i ./test/seeds_qemu -o ./test/output-qemu -- ./test/out-qemu || true test -n "$( ls ./test/output-qemu/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for QEMU mode" exit 1 } export AFL_ENTRYPOINT=`printf 1 | AFL_DEBUG=1 ${AFL_DIR}/afl-qemu-trace ./test/out-qemu 2>&1 >/dev/null | awk '/forkserver/{print $4; exit}'` timeout 15 ${FUZZER} -m 0 -Q -i ./test/seeds_qemu -o ./test/output-qemu-entrypoint -- ./test/out-qemu || true test -n "$( ls ./test/output-qemu-entrypoint/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for QEMU mode with AFL_ENTRYPOINT" exit 1 } unset AFL_ENTRYPOINT export AFL_PRELOAD=${AFL_DIR}/libcompcov.so export AFL_COMPCOV_LEVEL=2 timeout 15 ${FUZZER} -Q -i ./test/seeds_qemu -o ./test/output-qemu-cmpcov -- ./test/out-qemu-cmpcov || true test -n "$( ls ./test/output-qemu-cmpcov/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for QEMU mode" exit 1 } ''' dependencies = ["build_afl", "build_qemuafl", "build_libafl_fuzz"] [tasks.test_unicorn_mode] script_runner = "@shell" script = ''' export AFL_PATH=${AFL_DIR} export AFL_CORES=0 export AFL_STATS_INTERVAL=1 # TODO: test unicorn persistent mode once it's fixed on AFL++ LIBAFL_DEBUG_OUTPUT=1 AFL_DEBUG=1 AFL_DEBUG_CHILD=1 timeout 15s ${FUZZER} -m 0 -U -i ./test/seeds_unicorn -o ./test/output-unicorn-python -- python3 ${AFL_DIR}/unicorn_mode/samples/python_simple/simple_test_harness.py @@ || true test -n "$( ls ./test/output-unicorn-python/fuzzer_main/queue/id:000003* 2>/dev/null )" || { echo "No new corpus entries found for Unicorn python3 mode" exit 1 } export AFL_COMPCOV_LEVEL=2 LIBAFL_DEBUG_OUTPUT=1 AFL_DEBUG=1 AFL_DEBUG_CHILD=1 timeout 15s ${FUZZER} -m 0 -U -i ./test/seeds_unicorn_cmpcov -o ./test/output-unicorn-cmpcov -- python3 ${AFL_DIR}/unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ || true test -n "$( ls ./test/output-unicorn-cmpcov/fuzzer_main/queue/id:000002* 2>/dev/null )" || { echo "No new corpus entries found for Unicorn cmpcov mode" exit 1 } ''' dependencies = ["build_libafl_fuzz", "build_afl", "build_unicorn_mode"] [tasks.test_nyx_mode] script_runner = "@shell" script = ''' export AFL_PATH=${AFL_DIR} export AFL_CORES=0 export AFL_STATS_INTERVAL=1 export AFL_DEBUG=1 export LIBAFL_DEBUG_OUTPUT=1 AFL_PATH=${AFL_DIR} ${AFL_CC_PATH} ./test/test-instr.c -o ./test/out-instr rm -rf ./test/nyx-test cd ../../../libafl_nyx rm -rf packer git clone https://github.com/nyx-fuzz/packer.git python3 packer/packer/nyx_packer.py \ ../fuzzers/forkserver/libafl-fuzz/test/out-instr \ ../fuzzers/forkserver/libafl-fuzz/test/out-nyx \ afl \ instrumentation \ --fast_reload_mode \ --purge python3 packer/packer/nyx_config_gen.py ../fuzzers/forkserver/libafl-fuzz/test/out-nyx Kernel cd ../fuzzers/forkserver/libafl-fuzz/ timeout 15s ${FUZZER} -i ./test/seeds_nyx -o ./test/output-nyx -X -- ./test/out-nyx test -n "$( ls ./test/output-nyx/fuzzer_main/queue/id:000003* 2>/dev/null )" || { echo "No new corpus entries found for Nyx mode!" exit 1 } ''' dependencies = ["build_afl", "build_libafl_fuzz"] # since we cannot test nyx mode on CI, let's build it [tasks.build_nyx_mode] script_runner = "@shell" script = "cargo build --profile ${PROFILE} --features nyx" [tasks.clean] linux_alias = "clean_unix" mac_alias = "clean_unix" windows_alias = "unsupported" [tasks.clean_unix] script_runner = "@shell" script = ''' rm -rf AFLplusplus rm -rf ./test/output rm -rf ./test/cmplog-output rm -rf ./test/output-frida* rm -rf ./test/output-cmplog rm -rf ./test/output-qemu* rm -rf ./test/output-unicorn* rm ./test/out-* '''