//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. //===----------------------------------------------------------------------===// /* This file allows to fuzz libFuzzer-style target functions (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. Usage: ################################################################################ cat << EOF > test_fuzzer.cc #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 0 && data[0] == 'H') if (size > 1 && data[1] == 'I') if (size > 2 && data[2] == '!') __builtin_trap(); return 0; } EOF # Build your target with -fsanitize-coverage=trace-pc using fresh clang. clang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c # Build afl-llvm-rt.o.c from the AFL distribution. clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c # Build this file, link it with afl-llvm-rt.o.o and the target code. clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o # Run AFL: rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out ################################################################################ */ #include #include #include #include #include #include // libFuzzer interface is thin, so we don't include any libFuzzer headers. extern "C" { int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); } // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; extern "C" int __afl_persistent_loop(unsigned int); static volatile char suppress_warning2 = AFL_PERSISTENT[0]; // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; extern "C" void __afl_manual_init(); static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; // Input buffer. static const size_t kMaxAflInputSize = 1 << 20; static uint8_t AflInputBuf[kMaxAflInputSize]; int main(int argc, char **argv) { fprintf(stderr, "Running in AFl-fuzz mode\nUsage:\n" "afl-fuzz [afl-flags] %s [N] " "-- run N fuzzing iterations before " "re-spawning the process (default: 1000)\n", argv[0]); if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv); // Do any other expensive one-time initialization here. __afl_manual_init(); int N = 1000; if (argc >= 2) N = atoi(argv[1]); assert(N > 0); while (__afl_persistent_loop(N)) { ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); if (n_read > 0) { // Copy AflInputBuf into a separate buffer to let asan find buffer // overflows. Don't use unique_ptr/etc to avoid extra dependencies. uint8_t *copy = new uint8_t[n_read]; memcpy(copy, AflInputBuf, n_read); LLVMFuzzerTestOneInput(copy, n_read); delete[] copy; } } }