├── Makefile ├── QuickStartGuide.txt ├── README ├── afl-analyze.c ├── afl-as.c ├── afl-as.h ├── afl-cmin ├── afl-fuzz.c ├── afl-gcc.c ├── afl-gotcpu.c ├── afl-plot ├── afl-showmap.c ├── afl-tmin.c ├── afl-whatsup ├── alloc-inl.h ├── config.h ├── debug.h ├── docs ├── COPYING ├── ChangeLog ├── INSTALL ├── QuickStartGuide.txt ├── README ├── env_variables.txt ├── historical_notes.txt ├── notes_for_asan.txt ├── parallel_fuzzing.txt ├── perf_tips.txt ├── sister_projects.txt ├── status_screen.txt ├── technical_details.txt ├── visualization │ └── afl_gzip.png └── vuln_samples │ ├── bash-cmd-exec.var │ ├── bash-uninit-mem.var │ ├── ffmpeg-h264-bad-ptr-800m.mp4 │ ├── ffmpeg-h264-bad-read.mp4 │ ├── ffmpeg-h264-call-stack-overflow.mp4 │ ├── file-fpu-exception.elf │ ├── firefox-bmp-leak.bmp │ ├── firefox-chrome-leak.jpg │ ├── firefox-gif-leak.gif │ ├── firefox-gif-leak2.gif │ ├── jxrlib-crash.jxr │ ├── jxrlib-crash2.jxr │ ├── jxrlib-crash3.jxr │ ├── jxrlib-crash4.jxr │ ├── lesspipe-cpio-bad-write.cpio │ ├── libjpeg-sos-leak.jpg │ ├── libjpeg-turbo-dht-leak.jpg │ ├── libtiff-bad-write.tif │ ├── libtiff-uninit-mem.tif │ ├── libtiff-uninit-mem2.tif │ ├── libtiff-uninit-mem3.tif │ ├── libtiff-uninit-mem4.tif │ ├── libxml2-bad-read.xml │ ├── msie-dht-leak.jpg │ ├── msie-jxr-mem-leak.jxr │ ├── msie-png-mem-leak.png │ ├── msie-tiff-mem-leak.tif │ ├── msie-zlib-dos.png │ ├── openssl-null-ptr.der │ ├── openssl-null-ptr2.der │ ├── photoshop-mem-leak.jpg │ ├── sqlite-bad-free.sql │ ├── sqlite-bad-ptr.sql │ ├── sqlite-bad-ptr2.sql │ ├── sqlite-bad-ptr3.sql │ ├── sqlite-heap-overflow.sql │ ├── sqlite-heap-overwrite.sql │ ├── sqlite-negative-memset.sql │ ├── sqlite-null-ptr1.sql │ ├── sqlite-null-ptr10.sql │ ├── sqlite-null-ptr11.sql │ ├── sqlite-null-ptr12.sql │ ├── sqlite-null-ptr13.sql │ ├── sqlite-null-ptr14.sql │ ├── sqlite-null-ptr15.sql │ ├── sqlite-null-ptr2.sql │ ├── sqlite-null-ptr3.sql │ ├── sqlite-null-ptr4.sql │ ├── sqlite-null-ptr5.sql │ ├── sqlite-null-ptr6.sql │ ├── sqlite-null-ptr7.sql │ ├── sqlite-null-ptr8.sql │ ├── sqlite-null-ptr9.sql │ ├── sqlite-oob-read.sql │ ├── sqlite-oob-write.sql │ ├── sqlite-stack-buf-overflow.sql │ ├── sqlite-stack-exhaustion.sql │ ├── sqlite-unint-mem.sql │ ├── sqlite-use-after-free.sql │ ├── strings-bfd-badptr.elf │ ├── strings-bfd-badptr2.elf │ ├── strings-stack-overflow │ ├── strings-unchecked-ctr.elf │ ├── tcpdump-arp-crash.pcap │ ├── tcpdump-ppp-crash.pcap │ ├── unrtf-arbitrary-read.rtf │ └── unzip-t-mem-corruption.zip ├── experimental ├── README.experiments ├── argv_fuzzing │ └── argv-fuzz-inl.h ├── asan_cgroups │ └── limit_memory.sh ├── bash_shellshock │ └── shellshock-fuzz.diff ├── canvas_harness │ └── canvas_harness.html ├── clang_asm_normalize │ └── as ├── crash_triage │ └── triage_crashes.sh ├── distributed_fuzzing │ └── sync_script.sh ├── instrumented_cmp │ └── instrumented_cmp.c ├── libpng_no_checksum │ └── libpng-nocrc.patch ├── persistent_demo │ └── persistent_demo.c └── post_library │ ├── post_library.so.c │ └── post_library_png.so.c ├── hash.h ├── libdislocator.so.c ├── llvm_mode ├── Makefile ├── README.llvm ├── afl-clang-fast.c ├── afl-llvm-pass.so.cc └── afl-llvm-rt.o.c ├── qemu_mode ├── README.qemu ├── build_qemu_support.sh └── patches │ ├── afl-qemu-cpu-inl.h │ ├── cpu-exec.diff │ ├── elfload.diff │ ├── syscall.diff │ └── translate-all.diff ├── test-instr.c ├── testcases ├── README.testcases ├── _extras │ ├── gif.dict │ ├── html_tags.dict │ ├── jpeg.dict │ ├── js.dict │ ├── pdf.dict │ ├── png.dict │ ├── sql.dict │ ├── tiff.dict │ ├── webp.dict │ └── xml.dict ├── archives │ ├── common │ │ ├── ar │ │ │ └── small_archive.a │ │ ├── bzip2 │ │ │ └── small_archive.bz2 │ │ ├── cab │ │ │ └── small_archive.cab │ │ ├── compress │ │ │ └── small_archive.Z │ │ ├── cpio │ │ │ └── small_archive.cpio │ │ ├── gzip │ │ │ └── small_archive.gz │ │ ├── lzo │ │ │ └── small_archive.lzo │ │ ├── rar │ │ │ └── small_archive.rar │ │ ├── tar │ │ │ └── small_archive.tar │ │ ├── xz │ │ │ └── small_archive.xz │ │ └── zip │ │ │ └── small_archive.zip │ └── exotic │ │ ├── arj │ │ └── small_archive.arj │ │ ├── lha │ │ └── small_archive.lha │ │ ├── lrzip │ │ └── small_archive.lrz │ │ ├── lzip │ │ └── small_archive.lz │ │ ├── lzma │ │ └── small_archive.lzma │ │ ├── rzip │ │ └── small_archive.rz │ │ └── zoo │ │ └── small_archive.zoo ├── images │ ├── bmp │ │ └── not_kitty.bmp │ ├── gif │ │ └── not_kitty.gif │ ├── ico │ │ └── not_kitty.ico │ ├── jp2 │ │ └── not_kitty.jp2 │ ├── jpeg │ │ └── not_kitty.jpg │ ├── jxr │ │ └── not_kitty.jxr │ ├── png │ │ ├── not_kitty.png │ │ ├── not_kitty_alpha.png │ │ ├── not_kitty_gamma.png │ │ └── not_kitty_icc.png │ ├── tiff │ │ └── not_kitty.tiff │ └── webp │ │ └── not_kitty.webp ├── multimedia │ └── h264 │ │ └── small_movie.mp4 └── others │ ├── elf │ └── small_exec.elf │ ├── js │ └── small_script.js │ ├── pcap │ └── small_capture.pcap │ ├── pdf │ └── small.pdf │ ├── rtf │ └── small_document.rtf │ ├── sql │ └── simple_queries.sql │ ├── text │ └── hello_world.txt │ └── xml │ └── small_document.xml └── types.h /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # american fuzzy lop - makefile 3 | # ----------------------------- 4 | # 5 | # Written and maintained by Michal Zalewski 6 | # 7 | # Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at: 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | 16 | PROGNAME = afl 17 | VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) 18 | 19 | PREFIX ?= /usr/local 20 | BIN_PATH = $(PREFIX)/bin 21 | HELPER_PATH = $(PREFIX)/lib/afl 22 | DOC_PATH = $(PREFIX)/share/doc/afl 23 | MISC_PATH = $(PREFIX)/share/afl 24 | 25 | # PROGS intentionally omit afl-as and libdislocator.so, which get installed 26 | # to a different location. 27 | 28 | PROGS = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze 29 | SH_PROGS = afl-plot afl-cmin afl-whatsup 30 | 31 | CFLAGS ?= -O3 -funroll-loops 32 | CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ 33 | -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ 34 | -DBIN_PATH=\"$(BIN_PATH)\" 35 | 36 | ifneq "$(filter Linux GNU%,$(shell uname))" "" 37 | LDFLAGS += -ldl 38 | endif 39 | 40 | ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" 41 | TEST_CC = afl-gcc 42 | else 43 | TEST_CC = afl-clang 44 | endif 45 | 46 | COMM_HDR = alloc-inl.h config.h debug.h types.h 47 | 48 | all: test_x86 $(PROGS) afl-as libdislocator.so test_build all_done 49 | 50 | ifndef AFL_NO_X86 51 | 52 | test_x86: 53 | @echo "[*] Checking for the ability to compile x86 code..." 54 | @echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) 55 | @rm -f .test 56 | @echo "[+] Everything seems to be working, ready to compile." 57 | 58 | else 59 | 60 | test_x86: 61 | @echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)." 62 | 63 | endif 64 | 65 | afl-gcc: afl-gcc.c $(COMM_HDR) | test_x86 66 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 67 | set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done 68 | 69 | afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86 70 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 71 | ln -sf afl-as as 72 | 73 | afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86 74 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 75 | 76 | afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86 77 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 78 | 79 | afl-tmin: afl-tmin.c $(COMM_HDR) | test_x86 80 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 81 | 82 | afl-analyze: afl-analyze.c $(COMM_HDR) | test_x86 83 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 84 | 85 | afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86 86 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) 87 | 88 | libdislocator.so: libdislocator.so.c $(COMM_HDR) | test_x86 89 | $(CC) $(CFLAGS) -shared -fPIC $@.c -o $@ $(LDFLAGS) 90 | 91 | ifndef AFL_NO_X86 92 | 93 | test_build: afl-gcc afl-as afl-showmap 94 | @echo "[*] Testing the CC wrapper and instrumentation output..." 95 | unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 96 | echo 0 | ./afl-showmap -m none -q -o .test-instr0 ./test-instr 97 | echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr 98 | @rm -f test-instr 99 | @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping to troubleshoot the issue."; echo; exit 1; fi 100 | @echo "[+] All right, the instrumentation seems to be working!" 101 | 102 | else 103 | 104 | test_build: afl-gcc afl-as afl-showmap 105 | @echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)." 106 | 107 | endif 108 | 109 | all_done: test_build 110 | @if [ ! "`which clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.llvm for a faster alternative to afl-gcc."; fi 111 | @echo "[+] All done! Be sure to review README - it's pretty short and useful." 112 | @if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi 113 | @! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.txt for advice.\033[0m\n" 2>/dev/null 114 | 115 | .NOTPARALLEL: clean 116 | 117 | clean: 118 | rm -f $(PROGS) libdislocator.so afl-as as afl-g++ afl-clang afl-clang++ *.o *~ a.out core core.[1-9][0-9]* *.stackdump test .test test-instr .test-instr0 .test-instr1 qemu_mode/qemu-2.3.0.tar.bz2 afl-qemu-trace 119 | rm -rf out_dir qemu_mode/qemu-2.3.0 120 | $(MAKE) -C llvm_mode clean 121 | 122 | install: all 123 | mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) 124 | rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh 125 | install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) 126 | rm -f $${DESTDIR}$(BIN_PATH)/afl-as 127 | if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi 128 | if [ -f afl-clang-fast -a -f afl-llvm-pass.so -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-pass.so afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi 129 | if [ -f afl-llvm-rt-32.o ]; then set -e; install -m 755 afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi 130 | if [ -f afl-llvm-rt-64.o ]; then set -e; install -m 755 afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi 131 | set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/$$i; done 132 | install -m 755 afl-as $${DESTDIR}$(HELPER_PATH) 133 | install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH) 134 | ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as 135 | install -m 644 docs/README docs/ChangeLog docs/*.txt $${DESTDIR}$(DOC_PATH) 136 | cp -r testcases/ $${DESTDIR}$(MISC_PATH) 137 | 138 | publish: clean 139 | test "`basename $$PWD`" = "afl" || exit 1 140 | test -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz; if [ "$$?" = "0" ]; then echo; echo "Change program version in config.h, mmkay?"; echo; exit 1; fi 141 | cd ..; rm -rf $(PROGNAME)-$(VERSION); cp -pr $(PROGNAME) $(PROGNAME)-$(VERSION); \ 142 | tar -cvz -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz $(PROGNAME)-$(VERSION) 143 | chmod 644 ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz 144 | ( cd ~/www/afl/releases/; ln -s -f $(PROGNAME)-$(VERSION).tgz $(PROGNAME)-latest.tgz ) 145 | cat docs/README >~/www/afl/README.txt 146 | cat docs/status_screen.txt >~/www/afl/status_screen.txt 147 | cat docs/historical_notes.txt >~/www/afl/historical_notes.txt 148 | cat docs/technical_details.txt >~/www/afl/technical_details.txt 149 | cat docs/ChangeLog >~/www/afl/ChangeLog.txt 150 | cat docs/QuickStartGuide.txt >~/www/afl/QuickStartGuide.txt 151 | echo -n "$(VERSION)" >~/www/afl/version.txt 152 | -------------------------------------------------------------------------------- /QuickStartGuide.txt: -------------------------------------------------------------------------------- 1 | docs/QuickStartGuide.txt -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | docs/README -------------------------------------------------------------------------------- /afl-gcc.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - wrapper for GCC and clang 3 | ---------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | This program is a drop-in replacement for GCC or clang. The most common way 16 | of using it is to pass the path to afl-gcc or afl-clang via CC when invoking 17 | ./configure. 18 | 19 | (Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.) 20 | 21 | The wrapper needs to know the path to afl-as (renamed to 'as'). The default 22 | is /usr/local/lib/afl/. A convenient way to specify alternative directories 23 | would be to set AFL_PATH. 24 | 25 | If AFL_HARDEN is set, the wrapper will compile the target app with various 26 | hardening options that may help detect memory management issues more 27 | reliably. You can also specify AFL_USE_ASAN to enable ASAN. 28 | 29 | If you want to call a non-default compiler as a next step of the chain, 30 | specify its location via AFL_CC or AFL_CXX. 31 | 32 | */ 33 | 34 | #define AFL_MAIN 35 | 36 | #include "config.h" 37 | #include "types.h" 38 | #include "debug.h" 39 | #include "alloc-inl.h" 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | static u8* as_path; /* Path to the AFL 'as' wrapper */ 47 | static u8** cc_params; /* Parameters passed to the real CC */ 48 | static u32 cc_par_cnt = 1; /* Param count, including argv0 */ 49 | static u8 be_quiet, /* Quiet mode */ 50 | clang_mode; /* Invoked as afl-clang*? */ 51 | 52 | 53 | /* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived 54 | from argv[0]. If that fails, abort. */ 55 | 56 | static void find_as(u8* argv0) { 57 | 58 | u8 *afl_path = getenv("AFL_PATH"); 59 | u8 *slash, *tmp; 60 | 61 | if (afl_path) { 62 | 63 | tmp = alloc_printf("%s/as", afl_path); 64 | 65 | if (!access(tmp, X_OK)) { 66 | as_path = afl_path; 67 | ck_free(tmp); 68 | return; 69 | } 70 | 71 | ck_free(tmp); 72 | 73 | } 74 | 75 | slash = strrchr(argv0, '/'); 76 | 77 | if (slash) { 78 | 79 | u8 *dir; 80 | 81 | *slash = 0; 82 | dir = ck_strdup(argv0); 83 | *slash = '/'; 84 | 85 | tmp = alloc_printf("%s/afl-as", dir); 86 | 87 | if (!access(tmp, X_OK)) { 88 | as_path = dir; 89 | ck_free(tmp); 90 | return; 91 | } 92 | 93 | ck_free(tmp); 94 | ck_free(dir); 95 | 96 | } 97 | 98 | if (!access(AFL_PATH "/as", X_OK)) { 99 | as_path = AFL_PATH; 100 | return; 101 | } 102 | 103 | FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH"); 104 | 105 | } 106 | 107 | 108 | /* Copy argv to cc_params, making the necessary edits. */ 109 | 110 | static void edit_params(u32 argc, char** argv) { 111 | 112 | u8 fortify_set = 0, asan_set = 0; 113 | u8 *name; 114 | 115 | #if defined(__FreeBSD__) && defined(__x86_64__) 116 | u8 m32_set = 0; 117 | #endif 118 | 119 | cc_params = ck_alloc((argc + 64) * sizeof(u8*)); 120 | 121 | name = strrchr(argv[0], '/'); 122 | if (!name) name = argv[0]; else name++; 123 | 124 | if (!strncmp(name, "afl-clang", 9)) { 125 | 126 | clang_mode = 1; 127 | 128 | setenv(CLANG_ENV_VAR, "1", 1); 129 | 130 | if (!strcmp(name, "afl-clang++")) { 131 | u8* alt_cxx = getenv("AFL_CXX"); 132 | cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; 133 | } else { 134 | u8* alt_cc = getenv("AFL_CC"); 135 | cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; 136 | } 137 | 138 | } else { 139 | 140 | /* With GCJ and Eclipse installed, you can actually compile Java! The 141 | instrumentation will work (amazingly). Alas, unhandled exceptions do 142 | not call abort(), so afl-fuzz would need to be modified to equate 143 | non-zero exit codes with crash conditions when working with Java 144 | binaries. Meh. */ 145 | 146 | #ifdef __APPLE__ 147 | 148 | if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX"); 149 | else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ"); 150 | else cc_params[0] = getenv("AFL_CC"); 151 | 152 | if (!cc_params[0]) { 153 | 154 | SAYF("\n" cLRD "[-] " cRST 155 | "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n" 156 | " 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n" 157 | " set AFL_CC or AFL_CXX to specify the correct path to that compiler.\n"); 158 | 159 | FATAL("AFL_CC or AFL_CXX required on MacOS X"); 160 | 161 | } 162 | 163 | #else 164 | 165 | if (!strcmp(name, "afl-g++")) { 166 | u8* alt_cxx = getenv("AFL_CXX"); 167 | cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++"; 168 | } else if (!strcmp(name, "afl-gcj")) { 169 | u8* alt_cc = getenv("AFL_GCJ"); 170 | cc_params[0] = alt_cc ? alt_cc : (u8*)"gcj"; 171 | } else { 172 | u8* alt_cc = getenv("AFL_CC"); 173 | cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc"; 174 | } 175 | 176 | #endif /* __APPLE__ */ 177 | 178 | } 179 | 180 | while (--argc) { 181 | u8* cur = *(++argv); 182 | 183 | if (!strncmp(cur, "-B", 2)) { 184 | 185 | if (!be_quiet) WARNF("-B is already set, overriding"); 186 | 187 | if (!cur[2] && argc > 1) { argc--; argv++; } 188 | continue; 189 | 190 | } 191 | 192 | if (!strcmp(cur, "-integrated-as")) continue; 193 | 194 | if (!strcmp(cur, "-pipe")) continue; 195 | 196 | #if defined(__FreeBSD__) && defined(__x86_64__) 197 | if (!strcmp(cur, "-m32")) m32_set = 1; 198 | #endif 199 | 200 | if (!strcmp(cur, "-fsanitize=address") || 201 | !strcmp(cur, "-fsanitize=memory")) asan_set = 1; 202 | 203 | if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; 204 | 205 | cc_params[cc_par_cnt++] = cur; 206 | 207 | } 208 | 209 | cc_params[cc_par_cnt++] = "-B"; 210 | cc_params[cc_par_cnt++] = as_path; 211 | 212 | if (clang_mode) 213 | cc_params[cc_par_cnt++] = "-no-integrated-as"; 214 | 215 | if (getenv("AFL_HARDEN")) { 216 | 217 | cc_params[cc_par_cnt++] = "-fstack-protector-all"; 218 | 219 | if (!fortify_set) 220 | cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; 221 | 222 | } 223 | 224 | if (asan_set) { 225 | 226 | /* Pass this on to afl-as to adjust map density. */ 227 | 228 | setenv("AFL_USE_ASAN", "1", 1); 229 | 230 | } else if (getenv("AFL_USE_ASAN")) { 231 | 232 | cc_params[cc_par_cnt++] = "-fsanitize=address"; 233 | 234 | if (getenv("AFL_USE_MSAN")) 235 | FATAL("ASAN and MSAN are mutually exclusive"); 236 | 237 | } else if (getenv("AFL_USE_MSAN")) { 238 | 239 | cc_params[cc_par_cnt++] = "-fsanitize=memory"; 240 | 241 | if (getenv("AFL_USE_ASAN")) 242 | FATAL("ASAN and MSAN are mutually exclusive"); 243 | 244 | } 245 | 246 | if (!getenv("AFL_DONT_OPTIMIZE")) { 247 | 248 | #if defined(__FreeBSD__) && defined(__x86_64__) 249 | 250 | /* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself 251 | works OK. This has nothing to do with us, but let's avoid triggering 252 | that bug. */ 253 | 254 | if (!clang_mode || !m32_set) 255 | cc_params[cc_par_cnt++] = "-g"; 256 | 257 | #else 258 | 259 | cc_params[cc_par_cnt++] = "-g"; 260 | 261 | #endif 262 | 263 | cc_params[cc_par_cnt++] = "-O3"; 264 | cc_params[cc_par_cnt++] = "-funroll-loops"; 265 | 266 | /* Two indicators that you're building for fuzzing; one of them is 267 | AFL-specific, the other is shared with libfuzzer. */ 268 | 269 | cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; 270 | cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; 271 | 272 | } 273 | 274 | cc_params[cc_par_cnt] = NULL; 275 | 276 | } 277 | 278 | 279 | /* Main entry point */ 280 | 281 | int main(int argc, char** argv) { 282 | 283 | if (isatty(2) && !getenv("AFL_QUIET")) { 284 | 285 | SAYF(cCYA "afl-cc " cBRI VERSION cRST " by \n"); 286 | 287 | } else be_quiet = 1; 288 | 289 | if (argc < 2) { 290 | 291 | SAYF("\n" 292 | "This is a helper application for afl-fuzz. It serves as a drop-in replacement\n" 293 | "for gcc or clang, letting you recompile third-party code with the required\n" 294 | "runtime instrumentation. A common use pattern would be one of the following:\n\n" 295 | 296 | " CC=%s/afl-gcc ./configure\n" 297 | " CXX=%s/afl-g++ ./configure\n\n" 298 | 299 | "You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n" 300 | "Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n", 301 | BIN_PATH, BIN_PATH); 302 | 303 | exit(1); 304 | 305 | } 306 | 307 | 308 | find_as(argv[0]); 309 | 310 | edit_params(argc, argv); 311 | 312 | execvp(cc_params[0], (char**)cc_params); 313 | 314 | FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); 315 | 316 | return 0; 317 | 318 | } 319 | -------------------------------------------------------------------------------- /afl-gotcpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - free CPU gizmo 3 | ----------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2015, 2016 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | This tool provides a fairly accurate measurement of CPU preemption rate. 16 | It is meant to complement the quick-and-dirty load average widget shown 17 | in the afl-fuzz UI. See docs/parallel_fuzzing.txt for more info. 18 | 19 | For some work loads, the tool may actually suggest running more instances 20 | than you have CPU cores. This can happen if the tested program is spending 21 | a portion of its run time waiting for I/O, rather than being 100% 22 | CPU-bound. 23 | 24 | The idea for the getrusage()-based approach comes from Jakub Wilk. 25 | 26 | */ 27 | 28 | #define AFL_MAIN 29 | #define _GNU_SOURCE 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "types.h" 43 | #include "debug.h" 44 | 45 | #ifdef __linux__ 46 | # define HAVE_AFFINITY 1 47 | #endif /* __linux__ */ 48 | 49 | 50 | /* Get unix time in microseconds. */ 51 | 52 | static u64 get_cur_time_us(void) { 53 | 54 | struct timeval tv; 55 | struct timezone tz; 56 | 57 | gettimeofday(&tv, &tz); 58 | 59 | return (tv.tv_sec * 1000000ULL) + tv.tv_usec; 60 | 61 | } 62 | 63 | 64 | /* Get CPU usage in microseconds. */ 65 | 66 | static u64 get_cpu_usage_us(void) { 67 | 68 | struct rusage u; 69 | 70 | getrusage(RUSAGE_SELF, &u); 71 | 72 | return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec + 73 | (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec; 74 | 75 | } 76 | 77 | 78 | /* Measure preemption rate. */ 79 | 80 | static u32 measure_preemption(u32 target_ms) { 81 | 82 | static volatile u32 v1, v2; 83 | 84 | u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; 85 | s32 loop_repeats = 0; 86 | 87 | st_t = get_cur_time_us(); 88 | st_c = get_cpu_usage_us(); 89 | 90 | repeat_loop: 91 | 92 | v1 = CTEST_BUSY_CYCLES; 93 | 94 | while (v1--) v2++; 95 | sched_yield(); 96 | 97 | en_t = get_cur_time_us(); 98 | 99 | if (en_t - st_t < target_ms * 1000) { 100 | loop_repeats++; 101 | goto repeat_loop; 102 | } 103 | 104 | /* Let's see what percentage of this time we actually had a chance to 105 | run, and how much time was spent in the penalty box. */ 106 | 107 | en_c = get_cpu_usage_us(); 108 | 109 | real_delta = (en_t - st_t) / 1000; 110 | slice_delta = (en_c - st_c) / 1000; 111 | 112 | return real_delta * 100 / slice_delta; 113 | 114 | } 115 | 116 | 117 | /* Do the benchmark thing. */ 118 | 119 | int main(int argc, char** argv) { 120 | 121 | #ifdef HAVE_AFFINITY 122 | 123 | u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN), 124 | idle_cpus = 0, maybe_cpus = 0, i; 125 | 126 | SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by \n"); 127 | 128 | ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...", 129 | ((double)CTEST_CORE_TRG_MS) / 1000); 130 | 131 | for (i = 0; i < cpu_cnt; i++) { 132 | 133 | s32 fr = fork(); 134 | 135 | if (fr < 0) PFATAL("fork failed"); 136 | 137 | if (!fr) { 138 | 139 | cpu_set_t c; 140 | u32 util_perc; 141 | 142 | CPU_ZERO(&c); 143 | CPU_SET(i, &c); 144 | 145 | if (sched_setaffinity(0, sizeof(c), &c)) 146 | PFATAL("sched_setaffinity failed"); 147 | 148 | util_perc = measure_preemption(CTEST_CORE_TRG_MS); 149 | 150 | if (util_perc < 110) { 151 | 152 | SAYF(" Core #%u: " cLGN "AVAILABLE\n" cRST, i); 153 | exit(0); 154 | 155 | } else if (util_perc < 250) { 156 | 157 | SAYF(" Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc); 158 | exit(1); 159 | 160 | } 161 | 162 | SAYF(" Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i, 163 | util_perc); 164 | exit(2); 165 | 166 | } 167 | 168 | } 169 | 170 | for (i = 0; i < cpu_cnt; i++) { 171 | 172 | int ret; 173 | if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); 174 | 175 | if (WEXITSTATUS(ret) == 0) idle_cpus++; 176 | if (WEXITSTATUS(ret) <= 1) maybe_cpus++; 177 | 178 | } 179 | 180 | SAYF(cGRA "\n>>> "); 181 | 182 | if (idle_cpus) { 183 | 184 | if (maybe_cpus == idle_cpus) { 185 | 186 | SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.", 187 | idle_cpus, idle_cpus > 1 ? "s" : ""); 188 | 189 | } else { 190 | 191 | SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.", 192 | idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : ""); 193 | 194 | } 195 | 196 | SAYF(cGRA " <<<" cRST "\n\n"); 197 | return 0; 198 | 199 | } 200 | 201 | if (maybe_cpus) { 202 | 203 | SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.", 204 | maybe_cpus, maybe_cpus > 1 ? "s" : ""); 205 | SAYF(cGRA " <<<" cRST "\n\n"); 206 | return 1; 207 | 208 | } 209 | 210 | SAYF(cLRD "FAIL: " cRST "All cores are overbooked."); 211 | SAYF(cGRA " <<<" cRST "\n\n"); 212 | return 2; 213 | 214 | #else 215 | 216 | u32 util_perc; 217 | 218 | SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by \n"); 219 | 220 | /* Run a busy loop for CTEST_TARGET_MS. */ 221 | 222 | ACTF("Measuring gross preemption rate (this will take %0.02f sec)...", 223 | ((double)CTEST_TARGET_MS) / 1000); 224 | 225 | util_perc = measure_preemption(CTEST_TARGET_MS); 226 | 227 | /* Deliver the final verdict. */ 228 | 229 | SAYF(cGRA "\n>>> "); 230 | 231 | if (util_perc < 105) { 232 | 233 | SAYF(cLGN "PASS: " cRST "You can probably run additional processes."); 234 | 235 | } else if (util_perc < 130) { 236 | 237 | SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).", 238 | util_perc); 239 | 240 | } else { 241 | 242 | SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc); 243 | 244 | } 245 | 246 | SAYF(cGRA " <<<" cRST "\n\n"); 247 | 248 | return (util_perc > 105) + (util_perc > 130); 249 | 250 | #endif /* ^HAVE_AFFINITY */ 251 | 252 | } 253 | -------------------------------------------------------------------------------- /afl-plot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # american fuzzy lop - Advanced Persistent Graphing 4 | # ------------------------------------------------- 5 | # 6 | # Written and maintained by Michal Zalewski 7 | # Based on a design & prototype by Michael Rash. 8 | # 9 | # Copyright 2014, 2015 Google Inc. All rights reserved. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at: 14 | # 15 | # http://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | 18 | echo "progress plotting utility for afl-fuzz by " 19 | echo 20 | 21 | if [ ! "$#" = "2" ]; then 22 | 23 | cat 1>&2 <<_EOF_ 24 | This program generates gnuplot images from afl-fuzz output data. Usage: 25 | 26 | $0 afl_state_dir graph_output_dir 27 | 28 | The afl_state_dir parameter should point to an existing state directory for any 29 | active or stopped instance of afl-fuzz; while graph_output_dir should point to 30 | an empty directory where this tool can write the resulting plots to. 31 | 32 | The program will put index.html and three PNG images in the output directory; 33 | you should be able to view it with any web browser of your choice. 34 | 35 | _EOF_ 36 | 37 | exit 1 38 | 39 | fi 40 | 41 | echo "$1" | grep -qE '^(/var)?/tmp/' 42 | T1="$?" 43 | 44 | echo "$2" | grep -qE '^(/var)?/tmp/' 45 | T2="$?" 46 | 47 | if [ "$T1" = "0" -o "$T2" = "0" ]; then 48 | 49 | echo "[-] Error: this script shouldn't be used with shared /tmp directories." 1>&2 50 | exit 1 51 | 52 | fi 53 | 54 | if [ ! -f "$1/plot_data" ]; then 55 | 56 | echo "[-] Error: input directory is not valid (missing 'plot_data')." 1>&2 57 | exit 1 58 | 59 | fi 60 | 61 | BANNER="`cat "$1/fuzzer_stats" | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`" 62 | 63 | test "$BANNER" = "" && BANNER="(none)" 64 | 65 | GNUPLOT=`which gnuplot 2>/dev/null` 66 | 67 | if [ "$GNUPLOT" = "" ]; then 68 | 69 | echo "[-] Error: can't find 'gnuplot' in your \$PATH." 1>&2 70 | exit 1 71 | 72 | fi 73 | 74 | mkdir "$2" 2>/dev/null 75 | 76 | if [ ! -d "$2" ]; then 77 | 78 | echo "[-] Error: unable to create the output directory - pick another location." 1>&2 79 | exit 1 80 | 81 | fi 82 | 83 | rm -f "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png" 84 | mv -f "$2/index.html" "$2/index.html.orig" 2>/dev/null 85 | 86 | echo "[*] Generating plots..." 87 | 88 | ( 89 | 90 | cat <<_EOF_ 91 | set terminal png truecolor enhanced size 1000,300 butt 92 | 93 | set output '$2/high_freq.png' 94 | 95 | set xdata time 96 | set timefmt '%s' 97 | set format x "%b %d\n%H:%M" 98 | set tics font 'small' 99 | unset mxtics 100 | unset mytics 101 | 102 | set grid xtics linetype 0 linecolor rgb '#e0e0e0' 103 | set grid ytics linetype 0 linecolor rgb '#e0e0e0' 104 | set border linecolor rgb '#50c0f0' 105 | set tics textcolor rgb '#000000' 106 | set key outside 107 | 108 | set autoscale xfixmin 109 | set autoscale xfixmax 110 | 111 | plot '$1/plot_data' using 1:4 with filledcurve x1 title 'total paths' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\ 112 | '' using 1:3 with filledcurve x1 title 'current path' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\ 113 | '' using 1:5 with lines title 'pending paths' linecolor rgb '#0090ff' linewidth 3, \\ 114 | '' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\ 115 | '' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3 116 | 117 | set terminal png truecolor enhanced size 1000,200 butt 118 | set output '$2/low_freq.png' 119 | 120 | plot '$1/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\ 121 | '' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\ 122 | '' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\ 123 | '' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3 124 | 125 | set terminal png truecolor enhanced size 1000,200 butt 126 | set output '$2/exec_speed.png' 127 | 128 | plot '$1/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\ 129 | '$1/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier; 130 | 131 | _EOF_ 132 | 133 | ) | gnuplot 134 | 135 | if [ ! -s "$2/exec_speed.png" ]; then 136 | 137 | echo "[-] Error: something went wrong! Perhaps you have an ancient version of gnuplot?" 1>&2 138 | exit 1 139 | 140 | fi 141 | 142 | echo "[*] Generating index.html..." 143 | 144 | cat >"$2/index.html" <<_EOF_ 145 | 146 | 147 | 148 | 149 |
Banner:$BANNER
Directory:$1
Generated on:`date`
150 |

151 |

152 |

153 | 154 | 155 | _EOF_ 156 | 157 | # Make it easy to remotely view results when outputting directly to a directory 158 | # served by Apache or other HTTP daemon. Since the plots aren't horribly 159 | # sensitive, this seems like a reasonable trade-off. 160 | 161 | chmod 755 "$2" 162 | chmod 644 "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png" "$2/index.html" 163 | 164 | echo "[+] All done - enjoy your charts!" 165 | 166 | exit 0 167 | -------------------------------------------------------------------------------- /afl-whatsup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # american fuzzy lop - status check tool 4 | # -------------------------------------- 5 | # 6 | # Written and maintained by Michal Zalewski 7 | # 8 | # Copyright 2015 Google Inc. All rights reserved. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at: 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # This tool summarizes the status of any locally-running synchronized 17 | # instances of afl-fuzz. 18 | # 19 | 20 | echo "status check tool for afl-fuzz by " 21 | echo 22 | 23 | if [ "$1" = "-s" ]; then 24 | 25 | SUMMARY_ONLY=1 26 | DIR="$2" 27 | 28 | else 29 | 30 | unset SUMMARY_ONLY 31 | DIR="$1" 32 | 33 | fi 34 | 35 | if [ "$DIR" = "" ]; then 36 | 37 | echo "Usage: $0 [ -s ] afl_sync_dir" 1>&2 38 | echo 1>&2 39 | echo "The -s option causes the tool to skip all the per-fuzzer trivia and show" 1>&2 40 | echo "just the summary results. See docs/parallel_fuzzing.txt for additional tips." 1>&2 41 | echo 1>&2 42 | exit 1 43 | 44 | fi 45 | 46 | cd "$DIR" || exit 1 47 | 48 | if [ -d queue ]; then 49 | 50 | echo "[-] Error: parameter is an individual output directory, not a sync dir." 1>&2 51 | exit 1 52 | 53 | fi 54 | 55 | CUR_TIME=`date +%s` 56 | 57 | TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || exit 1 58 | 59 | ALIVE_CNT=0 60 | DEAD_CNT=0 61 | 62 | TOTAL_TIME=0 63 | TOTAL_EXECS=0 64 | TOTAL_EPS=0 65 | TOTAL_CRASHES=0 66 | TOTAL_PFAV=0 67 | TOTAL_PENDING=0 68 | 69 | if [ "$SUMMARY_ONLY" = "" ]; then 70 | 71 | echo "Individual fuzzers" 72 | echo "==================" 73 | echo 74 | 75 | fi 76 | 77 | for i in `find . -maxdepth 2 -iname fuzzer_stats`; do 78 | 79 | sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP" 80 | . "$TMP" 81 | 82 | RUN_UNIX=$((CUR_TIME - start_time)) 83 | RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24)) 84 | RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24)) 85 | 86 | if [ "$SUMMARY_ONLY" = "" ]; then 87 | 88 | echo ">>> $afl_banner ($RUN_DAYS days, $RUN_HRS hrs) <<<" 89 | echo 90 | 91 | fi 92 | 93 | if ! kill -0 "$fuzzer_pid" 2>/dev/null; then 94 | 95 | if [ "$SUMMARY_ONLY" = "" ]; then 96 | 97 | echo " Instance is dead or running remotely, skipping." 98 | echo 99 | 100 | fi 101 | 102 | DEAD_CNT=$((DEAD_CNT + 1)) 103 | continue 104 | 105 | fi 106 | 107 | ALIVE_CNT=$((ALIVE_CNT + 1)) 108 | 109 | EXEC_SEC=$((execs_done / RUN_UNIX)) 110 | PATH_PERC=$((cur_path * 100 / paths_total)) 111 | 112 | TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX)) 113 | TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC)) 114 | TOTAL_EXECS=$((TOTAL_EXECS + execs_done)) 115 | TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes)) 116 | TOTAL_PENDING=$((TOTAL_PENDING + pending_total)) 117 | TOTAL_PFAV=$((TOTAL_PFAV + pending_favs)) 118 | 119 | if [ "$SUMMARY_ONLY" = "" ]; then 120 | 121 | echo " cycle $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, path $cur_path/$paths_total (${PATH_PERC}%)" 122 | 123 | if [ "$unique_crashes" = "0" ]; then 124 | echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, no crashes yet" 125 | else 126 | echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, crash count $unique_crashes (!)" 127 | fi 128 | 129 | echo 130 | 131 | fi 132 | 133 | done 134 | 135 | rm -f "$TMP" 136 | 137 | TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24)) 138 | TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24)) 139 | 140 | test "$TOTAL_TIME" = "0" && TOTAL_TIME=1 141 | 142 | echo "Summary stats" 143 | echo "=============" 144 | echo 145 | echo " Fuzzers alive : $ALIVE_CNT" 146 | 147 | if [ ! "$DEAD_CNT" = "0" ]; then 148 | echo " Dead or remote : $DEAD_CNT (excluded from stats)" 149 | fi 150 | 151 | echo " Total run time : $TOTAL_DAYS days, $TOTAL_HRS hours" 152 | echo " Total execs : $((TOTAL_EXECS / 1000 / 1000)) million" 153 | echo " Cumulative speed : $TOTAL_EPS execs/sec" 154 | echo " Pending paths : $TOTAL_PFAV faves, $TOTAL_PENDING total" 155 | 156 | if [ "$ALIVE_CNT" -gt "1" ]; then 157 | echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" 158 | fi 159 | 160 | echo " Crashes found : $TOTAL_CRASHES locally unique" 161 | echo 162 | 163 | exit 0 164 | -------------------------------------------------------------------------------- /debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - debug / error handling macros 3 | -------------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | */ 16 | 17 | #ifndef _HAVE_DEBUG_H 18 | #define _HAVE_DEBUG_H 19 | 20 | #include 21 | 22 | #include "types.h" 23 | #include "config.h" 24 | 25 | /******************* 26 | * Terminal colors * 27 | *******************/ 28 | 29 | #ifdef USE_COLOR 30 | 31 | # define cBLK "\x1b[0;30m" 32 | # define cRED "\x1b[0;31m" 33 | # define cGRN "\x1b[0;32m" 34 | # define cBRN "\x1b[0;33m" 35 | # define cBLU "\x1b[0;34m" 36 | # define cMGN "\x1b[0;35m" 37 | # define cCYA "\x1b[0;36m" 38 | # define cLGR "\x1b[0;37m" 39 | # define cGRA "\x1b[1;90m" 40 | # define cLRD "\x1b[1;91m" 41 | # define cLGN "\x1b[1;92m" 42 | # define cYEL "\x1b[1;93m" 43 | # define cLBL "\x1b[1;94m" 44 | # define cPIN "\x1b[1;95m" 45 | # define cLCY "\x1b[1;96m" 46 | # define cBRI "\x1b[1;97m" 47 | # define cRST "\x1b[0m" 48 | 49 | # define bgBLK "\x1b[40m" 50 | # define bgRED "\x1b[41m" 51 | # define bgGRN "\x1b[42m" 52 | # define bgBRN "\x1b[43m" 53 | # define bgBLU "\x1b[44m" 54 | # define bgMGN "\x1b[45m" 55 | # define bgCYA "\x1b[46m" 56 | # define bgLGR "\x1b[47m" 57 | # define bgGRA "\x1b[100m" 58 | # define bgLRD "\x1b[101m" 59 | # define bgLGN "\x1b[102m" 60 | # define bgYEL "\x1b[103m" 61 | # define bgLBL "\x1b[104m" 62 | # define bgPIN "\x1b[105m" 63 | # define bgLCY "\x1b[106m" 64 | # define bgBRI "\x1b[107m" 65 | 66 | #else 67 | 68 | # define cBLK "" 69 | # define cRED "" 70 | # define cGRN "" 71 | # define cBRN "" 72 | # define cBLU "" 73 | # define cMGN "" 74 | # define cCYA "" 75 | # define cLGR "" 76 | # define cGRA "" 77 | # define cLRD "" 78 | # define cLGN "" 79 | # define cYEL "" 80 | # define cLBL "" 81 | # define cPIN "" 82 | # define cLCY "" 83 | # define cBRI "" 84 | # define cRST "" 85 | 86 | # define bgBLK "" 87 | # define bgRED "" 88 | # define bgGRN "" 89 | # define bgBRN "" 90 | # define bgBLU "" 91 | # define bgMGN "" 92 | # define bgCYA "" 93 | # define bgLGR "" 94 | # define bgGRA "" 95 | # define bgLRD "" 96 | # define bgLGN "" 97 | # define bgYEL "" 98 | # define bgLBL "" 99 | # define bgPIN "" 100 | # define bgLCY "" 101 | # define bgBRI "" 102 | 103 | #endif /* ^USE_COLOR */ 104 | 105 | /************************* 106 | * Box drawing sequences * 107 | *************************/ 108 | 109 | #ifdef FANCY_BOXES 110 | 111 | # define SET_G1 "\x1b)0" /* Set G1 for box drawing */ 112 | # define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ 113 | # define bSTART "\x0e" /* Enter G1 drawing mode */ 114 | # define bSTOP "\x0f" /* Leave G1 drawing mode */ 115 | # define bH "q" /* Horizontal line */ 116 | # define bV "x" /* Vertical line */ 117 | # define bLT "l" /* Left top corner */ 118 | # define bRT "k" /* Right top corner */ 119 | # define bLB "m" /* Left bottom corner */ 120 | # define bRB "j" /* Right bottom corner */ 121 | # define bX "n" /* Cross */ 122 | # define bVR "t" /* Vertical, branch right */ 123 | # define bVL "u" /* Vertical, branch left */ 124 | # define bHT "v" /* Horizontal, branch top */ 125 | # define bHB "w" /* Horizontal, branch bottom */ 126 | 127 | #else 128 | 129 | # define SET_G1 "" 130 | # define RESET_G1 "" 131 | # define bSTART "" 132 | # define bSTOP "" 133 | # define bH "-" 134 | # define bV "|" 135 | # define bLT "+" 136 | # define bRT "+" 137 | # define bLB "+" 138 | # define bRB "+" 139 | # define bX "+" 140 | # define bVR "+" 141 | # define bVL "+" 142 | # define bHT "+" 143 | # define bHB "+" 144 | 145 | #endif /* ^FANCY_BOXES */ 146 | 147 | /*********************** 148 | * Misc terminal codes * 149 | ***********************/ 150 | 151 | #define TERM_HOME "\x1b[H" 152 | #define TERM_CLEAR TERM_HOME "\x1b[2J" 153 | #define cEOL "\x1b[0K" 154 | #define CURSOR_HIDE "\x1b[?25l" 155 | #define CURSOR_SHOW "\x1b[?25h" 156 | 157 | /************************ 158 | * Debug & error macros * 159 | ************************/ 160 | 161 | /* Just print stuff to the appropriate stream. */ 162 | 163 | #ifdef MESSAGES_TO_STDOUT 164 | # define SAYF(x...) printf(x) 165 | #else 166 | # define SAYF(x...) fprintf(stderr, x) 167 | #endif /* ^MESSAGES_TO_STDOUT */ 168 | 169 | /* Show a prefixed warning. */ 170 | 171 | #define WARNF(x...) do { \ 172 | SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ 173 | SAYF(cRST "\n"); \ 174 | } while (0) 175 | 176 | /* Show a prefixed "doing something" message. */ 177 | 178 | #define ACTF(x...) do { \ 179 | SAYF(cLBL "[*] " cRST x); \ 180 | SAYF(cRST "\n"); \ 181 | } while (0) 182 | 183 | /* Show a prefixed "success" message. */ 184 | 185 | #define OKF(x...) do { \ 186 | SAYF(cLGN "[+] " cRST x); \ 187 | SAYF(cRST "\n"); \ 188 | } while (0) 189 | 190 | /* Show a prefixed fatal error message (not used in afl). */ 191 | 192 | #define BADF(x...) do { \ 193 | SAYF(cLRD "\n[-] " cRST x); \ 194 | SAYF(cRST "\n"); \ 195 | } while (0) 196 | 197 | /* Die with a verbose non-OS fatal error message. */ 198 | 199 | #define FATAL(x...) do { \ 200 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ 201 | cBRI x); \ 202 | SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ 203 | __FUNCTION__, __FILE__, __LINE__); \ 204 | exit(1); \ 205 | } while (0) 206 | 207 | /* Die by calling abort() to provide a core dump. */ 208 | 209 | #define ABORT(x...) do { \ 210 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ 211 | cBRI x); \ 212 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ 213 | __FUNCTION__, __FILE__, __LINE__); \ 214 | abort(); \ 215 | } while (0) 216 | 217 | /* Die while also including the output of perror(). */ 218 | 219 | #define PFATAL(x...) do { \ 220 | fflush(stdout); \ 221 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ 222 | cBRI x); \ 223 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ 224 | __FUNCTION__, __FILE__, __LINE__); \ 225 | SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ 226 | exit(1); \ 227 | } while (0) 228 | 229 | /* Die with FAULT() or PFAULT() depending on the value of res (used to 230 | interpret different failure modes for read(), write(), etc). */ 231 | 232 | #define RPFATAL(res, x...) do { \ 233 | if (res < 0) PFATAL(x); else FATAL(x); \ 234 | } while (0) 235 | 236 | /* Error-checking versions of read() and write() that call RPFATAL() as 237 | appropriate. */ 238 | 239 | #define ck_write(fd, buf, len, fn) do { \ 240 | u32 _len = (len); \ 241 | s32 _res = write(fd, buf, _len); \ 242 | if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ 243 | } while (0) 244 | 245 | #define ck_read(fd, buf, len, fn) do { \ 246 | u32 _len = (len); \ 247 | s32 _res = read(fd, buf, _len); \ 248 | if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ 249 | } while (0) 250 | 251 | #endif /* ! _HAVE_DEBUG_H */ 252 | -------------------------------------------------------------------------------- /docs/INSTALL: -------------------------------------------------------------------------------- 1 | ========================= 2 | Installation instructions 3 | ========================= 4 | 5 | This document provides basic installation instructions and discusses known 6 | issues for a variety of platforms. See README for the general instruction 7 | manual. 8 | 9 | 1) Linux on x86 10 | --------------- 11 | 12 | This platform is expected to work well. Compile the program with: 13 | 14 | $ make 15 | 16 | You can start using the fuzzer without installation, but it is also possible to 17 | install it with: 18 | 19 | # make install 20 | 21 | There are no special dependencies to speak of; you will need GNU make and a 22 | working compiler (gcc or clang). Some of the optional scripts bundled with the 23 | program may depend on bash, gdb, and similar basic tools. 24 | 25 | If you are using clang, please review llvm_mode/README.llvm; the LLVM 26 | integration mode can offer substantial performance gains compared to the 27 | traditional approach. 28 | 29 | You may have to change several settings to get optimal results (most notably, 30 | disable crash reporting utilities and switch to a different CPU governor), but 31 | afl-fuzz will guide you through that if necessary. 32 | 33 | 2) OpenBSD, FreeBSD, NetBSD on x86 34 | ---------------------------------- 35 | 36 | Similarly to Linux, these platforms are expected to work well and are 37 | regularly tested. Compile everything with GNU make: 38 | 39 | $ gmake 40 | 41 | Note that BSD make will *not* work; if you do not have gmake on your system, 42 | please install it first. As on Linux, you can use the fuzzer itself without 43 | installation, or install it with: 44 | 45 | # gmake install 46 | 47 | Keep in mind that if you are using csh as your shell, the syntax of some of the 48 | shell commands given in the README and other docs will be different. 49 | 50 | The llvm_mode requires a dynamically linked, fully-operational installation of 51 | clang. At least on FreeBSD, the clang binaries are static and do not include 52 | some of the essential tools, so if you want to make it work, you may need to 53 | follow the instructions in llvm_mode/README.llvm. 54 | 55 | Beyond that, everything should work as advertised. 56 | 57 | The QEMU mode is currently supported only on Linux. I think it's just a QEMU 58 | problem, I couldn't get a vanilla copy of user-mode emulation support working 59 | correctly on BSD at all. 60 | 61 | 3) MacOS X on x86 62 | ----------------- 63 | 64 | MacOS X should work, but there are some gotchas due to the idiosyncrasies of 65 | the platform. On top of this, I have limited release testing capabilities 66 | and depend mostly on user feedback. 67 | 68 | To build AFL, install Xcode and follow the general instructions for Linux. 69 | 70 | The Xcode 'gcc' tool is just a wrapper for clang, so be sure to use afl-clang 71 | to compile any instrumented binaries; afl-gcc will fail unless you have GCC 72 | installed from another source (in which case, please specify AFL_CC and 73 | AFL_CXX to point to the "real" GCC binaries). 74 | 75 | Only 64-bit compilation will work on the platform; porting the 32-bit 76 | instrumentation would require a fair amount of work due to the way OS X 77 | handles relocations, and today, virtually all MacOS X boxes are 64-bit. 78 | 79 | The crash reporting daemon that comes by default with MacOS X will cause 80 | problems with fuzzing. You need to turn it off by following the instructions 81 | provided here: http://goo.gl/CCcd5u 82 | 83 | The fork() semantics on OS X are a bit unusual compared to other unix systems 84 | and definitely don't look POSIX-compliant. This means two things: 85 | 86 | - Fuzzing will be probably slower than on Linux. In fact, some folks report 87 | considerable performance gains by running the jobs inside a Linux VM on 88 | MacOS X. 89 | 90 | - Some non-portable, platform-specific code may be incompatible with the 91 | AFL forkserver. If you run into any problems, set AFL_NO_FORKSRV=1 in the 92 | environment before starting afl-fuzz. 93 | 94 | User emulation mode of QEMU does not appear to be supported on MacOS X, so 95 | black-box instrumentation mode (-Q) will not work. 96 | 97 | The llvm_mode requires a fully-operational installation of clang. The one that 98 | comes with Xcode is missing some of the essential headers and helper tools. 99 | See llvm_mode/README.llvm for advice on how to build the compiler from scratch. 100 | 101 | 4) Linux or *BSD on non-x86 systems 102 | ----------------------------------- 103 | 104 | Standard build will fail on non-x86 systems, but you should be able to 105 | leverage two other options: 106 | 107 | - The LLVM mode (see llvm_mode/README.llvm), which does not rely on 108 | x86-specific assembly shims. It's fast and robust, but requires a 109 | complete installation of clang. 110 | 111 | - The QEMU mode (see qemu_mode/README.qemu), which can be also used for 112 | fuzzing cross-platform binaries. It's slower and more fragile, but 113 | can be used even when you don't have the source for the tested app. 114 | 115 | If you're not sure what you need, you need the LLVM mode. To get it, try: 116 | 117 | $ AFL_NO_X86=1 gmake && gmake -C llvm_mode 118 | 119 | ...and compile your target program with afl-clang-fast or afl-clang-fast++ 120 | instead of the traditional afl-gcc or afl-clang wrappers. 121 | 122 | 5) Solaris on x86 123 | ----------------- 124 | 125 | The fuzzer reportedly works on Solaris, but I have not tested this first-hand, 126 | and the user base is fairly small, so I don't have a lot of feedback. 127 | 128 | To get the ball rolling, you will need to use GNU make and GCC or clang. I'm 129 | being told that the stock version of GCC that comes with the platform does not 130 | work properly due to its reliance on a hardcoded location for 'as' (completely 131 | ignoring the -B parameter or $PATH). 132 | 133 | To fix this, you may want to build stock GCC from the source, like so: 134 | 135 | $ ./configure --prefix=$HOME/gcc --with-gnu-as --with-gnu-ld \ 136 | --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr 137 | $ make 138 | $ sudo make install 139 | 140 | Do *not* specify --with-as=/usr/gnu/bin/as - this will produce a GCC binary that 141 | ignores the -B flag and you will be back to square one. 142 | 143 | Note that Solaris reportedly comes withe crash reporting enabled, which causes 144 | problems with crashes being misinterpreted as hangs, similarly to the gotchas 145 | for Linux and MacOS X. AFL does not auto-detect crash reporting on this 146 | particular platform, but you may need to run the following command: 147 | 148 | $ coreadm -d global -d global-setid -d process -d proc-setid \ 149 | -d kzone -d log 150 | 151 | User emulation mode of QEMU is not available on Solaris, so black-box 152 | instrumentation mode (-Q) will not work. 153 | 154 | 6) Everything else 155 | ------------------ 156 | 157 | You're on your own. On POSIX-compliant systems, you may be able to compile and 158 | run the fuzzer; and the LLVM mode may offer a way to instrument non-x86 code. 159 | 160 | The fuzzer will not run on Windows. It will also not work under Cygwin. It 161 | could be ported to the latter platform fairly easily, but it's a pretty bad 162 | idea, because Cygwin is extremely slow. It makes much more sense to use 163 | VirtualBox or so to run a hardware-accelerated Linux VM; it will run around 164 | 20x faster or so. If you have a *really* compelling use case for Cygwin, let 165 | me know. 166 | 167 | Although Android on x86 should theoretically work, the stock kernel has SHM 168 | support compiled out, so you will need to address this issue first. It's 169 | possible that all you need is this: 170 | 171 | https://github.com/pelya/android-shmem 172 | -------------------------------------------------------------------------------- /docs/QuickStartGuide.txt: -------------------------------------------------------------------------------- 1 | ===================== 2 | AFL quick start guide 3 | ===================== 4 | 5 | You should read docs/README. It's pretty short. If you really can't, here's 6 | how to hit the ground running: 7 | 8 | 1) Compile AFL with 'make'. If build fails, see docs/INSTALL for tips. 9 | 10 | 2) Find or write a reasonably fast and simple program that takes data from 11 | a file or stdin, processes it in a test-worthy way, then exits cleanly. 12 | If testing a network service, modify it to run in the foreground and read 13 | from stdin. When fuzzing a format that uses checksums, comment out the 14 | checksum verification code, too. 15 | 16 | The program must crash properly when a fault is encountered. Watch out for 17 | custom SIGSEGV or SIGABRT handlers and background processes. For tips on 18 | detecting non-crashing flaws, see section 11 in docs/README. 19 | 20 | 3) Compile the program / library to be fuzzed using afl-gcc. A common way to 21 | do this would be: 22 | 23 | CC=/path/to/afl-gcc CXX=/path/to/afl-g++ ./configure --disable-shared 24 | make clean all 25 | 26 | If program build fails, ping . 27 | 28 | 4) Get a small but valid input file that makes sense to the program. When 29 | fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in 30 | testcases/README.testcases, too. 31 | 32 | 5) If the program reads from stdin, run 'afl-fuzz' like so: 33 | 34 | ./afl-fuzz -i testcase_dir -o findings_dir -- \ 35 | /path/to/tested/program [...program's cmdline...] 36 | 37 | If the program takes input from a file, you can put @@ in the program's 38 | command line; AFL will put an auto-generated file name in there for you. 39 | 40 | 6) Investigate anything shown in red in the fuzzer UI by promptly consulting 41 | docs/status_screen.txt. 42 | 43 | That's it. Sit back, relax, and - time permitting - try to skim through the 44 | following files: 45 | 46 | - docs/README - A general introduction to AFL, 47 | - docs/perf_tips.txt - Simple tips on how to fuzz more quickly, 48 | - docs/status_screen.txt - An explanation of the tidbits shown in the UI, 49 | - docs/parallel_fuzzing.txt - Advice on running AFL on multiple cores. 50 | -------------------------------------------------------------------------------- /docs/historical_notes.txt: -------------------------------------------------------------------------------- 1 | ================ 2 | Historical notes 3 | ================ 4 | 5 | This doc talks about the rationale of some of the high-level design decisions 6 | for American Fuzzy Lop. It's adopted from a discussion with Rob Graham. 7 | See README for the general instruction manual, and technical_details.txt for 8 | additional implementation-level insights. 9 | 10 | 1) Influences 11 | ------------- 12 | 13 | In short, afl-fuzz is inspired chiefly by the work done by Tavis Ormandy back 14 | in 2007. Tavis did some very persuasive experiments using gcov block coverage 15 | to select optimal test cases out of a large corpus of data, and then using 16 | them as a starting point for traditional fuzzing workflows. 17 | 18 | (By "persuasive", I mean: netting a significant number of interesting 19 | vulnerabilities.) 20 | 21 | In parallel to this, both Tavis and I were interested in evolutionary fuzzing. 22 | Tavis had his experiments, and I was working on a tool called bunny-the-fuzzer, 23 | released somewhere in 2007. 24 | 25 | Bunny used a generational algorithm not much different from afl-fuzz, but 26 | also tried to reason about the relationship between various input bits and 27 | the internal state of the program, with hopes of deriving some additional value 28 | from that. The reasoning / correlation part was probably in part inspired by 29 | other projects done around the same time by Will Drewry and Chris Evans. 30 | 31 | The state correlation approach sounded very sexy on paper, but ultimately, made 32 | the fuzzer complicated, brittle, and cumbersome to use; every other target 33 | program would require a tweak or two. Because Bunny didn't fare a whole lot 34 | better than less sophisticated brute-force tools, I eventually decided to write 35 | it off. You can still find its original documentation at: 36 | 37 | https://code.google.com/p/bunny-the-fuzzer/wiki/BunnyDoc 38 | 39 | There has been a fair amount of independent work, too. Most notably, a few 40 | weeks earlier that year, Jared DeMott had a Defcon presentation about a 41 | coverage-driven fuzzer that relied on coverage as a fitness function. 42 | 43 | Jared's approach was by no means identical to what afl-fuzz does, but it was in 44 | the same ballpark. His fuzzer tried to explicitly solve for the maximum coverage 45 | with a single input file; in comparison, afl simply selects for cases that do 46 | something new (which yields better results - see technical_details.txt). 47 | 48 | A few years later, Gabriel Campana released fuzzgrind, a tool that relied purely 49 | on Valgrind and a constraint solver to maximize coverage without any brute-force 50 | bits; and Microsoft Research folks talked extensively about their still 51 | non-public, solver-based SAGE framework. 52 | 53 | In the past six years or so, I've also seen a fair number of academic papers 54 | that dealt with smart fuzzing (focusing chiefly on symbolic execution) and a 55 | couple papers that discussed proof-of-concept applications of genetic 56 | algorithms with the same goals in mind. I'm unconvinced how practical most of 57 | these experiments were; I suspect that many of them suffer from the 58 | bunny-the-fuzzer's curse of being cool on paper and in carefully designed 59 | experiments, but failing the ultimate test of being able to find new, 60 | worthwhile security bugs in otherwise well-fuzzed, real-world software. 61 | 62 | In some ways, the baseline that the "cool" solutions have to compete against is 63 | a lot more impressive than it may seem, making it difficult for competitors to 64 | stand out. For a singular example, check out the work by Gynvael and Mateusz 65 | Jurczyk, applying "dumb" fuzzing to ffmpeg, a prominent and security-critical 66 | component of modern browsers and media players: 67 | 68 | http://googleonlinesecurity.blogspot.com/2014/01/ffmpeg-and-thousand-fixes.html 69 | 70 | Effortlessly getting comparable results with state-of-the-art symbolic execution 71 | in equally complex software still seems fairly unlikely, and hasn't been 72 | demonstrated in practice so far. 73 | 74 | But I digress; ultimately, attribution is hard, and glorying the fundamental 75 | concepts behind AFL is probably a waste of time. The devil is very much in the 76 | often-overlooked details, which brings us to... 77 | 78 | 2) Design goals for afl-fuzz 79 | ---------------------------- 80 | 81 | In short, I believe that the current implementation of afl-fuzz takes care of 82 | several itches that seemed impossible to scratch with other tools: 83 | 84 | 1) Speed. It's genuinely hard to compete with brute force when your "smart" 85 | approach is resource-intensive. If your instrumentation makes it 10x more 86 | likely to find a bug, but runs 100x slower, your users are getting a bad 87 | deal. 88 | 89 | To avoid starting with a handicap, afl-fuzz is meant to let you fuzz most of 90 | the intended targets at roughly their native speed - so even if it doesn't 91 | add value, you do not lose much. 92 | 93 | On top of this, the tool leverages instrumentation to actually reduce the 94 | amount of work in a couple of ways: for example, by carefully trimming the 95 | corpus or skipping non-functional but non-trimmable regions in the input 96 | files. 97 | 98 | 2) Rock-solid reliability. It's hard to compete with brute force if your 99 | approach is brittle and fails unexpectedly. Automated testing is attractive 100 | because it's simple to use and scalable; anything that goes against these 101 | principles is an unwelcome trade-off and means that your tool will be used 102 | less often and with less consistent results. 103 | 104 | Most of the approaches based on symbolic execution, taint tracking, or 105 | complex syntax-aware instrumentation are currently fairly unreliable with 106 | real-world targets. Perhaps more importantly, their failure modes can render 107 | them strictly worse than "dumb" tools, and such degradation can be difficult 108 | for less experienced users to notice and correct. 109 | 110 | In contrast, afl-fuzz is designed to be rock solid, chiefly by keeping it 111 | simple. In fact, at its core, it's designed to be just a very good 112 | traditional fuzzer with a wide range of interesting, well-researched 113 | strategies to go by. The fancy parts just help it focus the effort in 114 | places where it matters the most. 115 | 116 | 3) Simplicity. The author of a testing framework is probably the only person 117 | who truly understands the impact of all the settings offered by the tool - 118 | and who can dial them in just right. Yet, even the most rudimentary fuzzer 119 | frameworks often come with countless knobs and fuzzing ratios that need to 120 | be guessed by the operator ahead of the time. This can do more harm than 121 | good. 122 | 123 | AFL is designed to avoid this as much as possible. The three knobs you 124 | can play with are the output file, the memory limit, and the ability to 125 | override the default, auto-calibrated timeout. The rest is just supposed to 126 | work. When it doesn't, user-friendly error messages outline the probable 127 | causes and workarounds, and get you back on track right away. 128 | 129 | 4) Chainability. Most general-purpose fuzzers can't be easily employed 130 | against resource-hungry or interaction-heavy tools, necessitating the 131 | creation of custom in-process fuzzers or the investment of massive CPU 132 | power (most of which is wasted on tasks not directly related to the code 133 | we actually want to test). 134 | 135 | AFL tries to scratch this itch by allowing users to use more lightweight 136 | targets (e.g., standalone image parsing libraries) to create small 137 | corpora of interesting test cases that can be fed into a manual testing 138 | process or a UI harness later on. 139 | 140 | As mentioned in technical_details.txt, AFL does all this not by systematically 141 | applying a single overarching CS concept, but by experimenting with a variety 142 | of small, complementary methods that were shown to reliably yields results 143 | better than chance. The use of instrumentation is a part of that toolkit, but is 144 | far from being the most important one. 145 | 146 | Ultimately, what matters is that afl-fuzz is designed to find cool bugs - and 147 | has a pretty robust track record of doing just that. 148 | -------------------------------------------------------------------------------- /docs/notes_for_asan.txt: -------------------------------------------------------------------------------- 1 | ================================== 2 | Notes for using ASAN with afl-fuzz 3 | ================================== 4 | 5 | This file discusses some of the caveats for fuzzing under ASAN, and suggests 6 | a handful of alternatives. See README for the general instruction manual. 7 | 8 | 1) Short version 9 | ---------------- 10 | 11 | ASAN on 64-bit systems requests a lot of memory in a way that can't be easily 12 | distinguished from a misbehaving program bent on crashing your system. 13 | 14 | Because of this, fuzzing with ASAN is recommended only in four scenarios: 15 | 16 | - On 32-bit systems, where we can always enforce a reasonable memory limit 17 | (-m 800 or so is a good starting point), 18 | 19 | - On 64-bit systems only if you can do one of the following: 20 | 21 | - Compile the binary in 32-bit mode (gcc -m32), 22 | 23 | - Precisely gauge memory needs using http://jwilk.net/software/recidivm . 24 | 25 | - Limit the memory available to process using cgroups on Linux (see 26 | experimental/asan_cgroups). 27 | 28 | To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The 29 | afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags. 30 | Note that ASAN is incompatible with -static, so be mindful of that. 31 | 32 | (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) 33 | 34 | Note that both ASAN and MSAN are incompatible with -D_FORTIFY_SOURCE (enabled 35 | by default in some distros) and with AFL_HARDEN. Attempting to combine these 36 | settings can lead to false negatives in ASAN and false positives in MSAN. This 37 | is not AFL-specific. 38 | 39 | There is also the option of generating a corpus using a non-ASAN binary, and 40 | then feeding it to an ASAN-instrumented one to check for bugs. This is faster, 41 | and can give you somewhat comparable results. 42 | 43 | 2) Long version 44 | --------------- 45 | 46 | ASAN allocates a huge region of virtual address space for bookkeeping purposes. 47 | Most of this is never actually accessed, so the OS never has to allocate any 48 | real pages of memory for the process, and the VM grabbed by ASAN is essentially 49 | "free" - but the mapping counts against the standard OS-enforced limit 50 | (RLIMIT_AS, aka ulimit -v). 51 | 52 | On our end, afl-fuzz tries to protect you from processes that go off-rails 53 | and start consuming all the available memory in a vain attempt to parse a 54 | malformed input file. This happens surprisingly often, so enforcing such a limit 55 | is important for almost any fuzzer: the alternative is for the kernel OOM 56 | handler to step in and start killing random processes to free up resources. 57 | Needless to say, that's not a very nice prospect to live with. 58 | 59 | Unfortunately, un*x systems offer no portable way to limit the amount of 60 | pages actually given to a process in a way that distinguishes between that 61 | and the harmless "land grab" done by ASAN. In principle, there are three standard 62 | ways to limit the size of the heap: 63 | 64 | - The RLIMIT_AS mechanism (ulimit -v) caps the size of the virtual space - 65 | but as noted, this pays no attention to the number of pages actually 66 | in use by the process, and doesn't help us here. 67 | 68 | - The RLIMIT_DATA mechanism (ulimit -d) seems like a good fit, but it applies 69 | only to the traditional sbrk() / brk() methods of requesting heap space; 70 | modern allocators, including the one in glibc, routinely rely on mmap() 71 | instead, and circumvent this limit completely. 72 | 73 | - Finally, the RLIMIT_RSS limit (ulimit -m) sounds like what we need, but 74 | doesn't work on Linux - mostly because nobody felt like implementing it. 75 | 76 | There are also cgroups, but they are Linux-specific, not universally available 77 | even on Linux systems, and they require root permissions to set up; I'm a bit 78 | hesitant to make afl-fuzz require root permissions just for that. That said, 79 | if you are on Linux and want to use cgroups, check out the contributed script 80 | that ships in experimental/asan_cgroups/. 81 | 82 | In settings where cgroups aren't available, we have no nice, portable way to 83 | avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for 84 | binaries compiled in 32-bit mode (-m32), this is not a big deal: ASAN needs 85 | around 600-800 MB or so, depending on the compiler - so all you need to do is 86 | to specify -m that is a bit higher than that. 87 | 88 | On 64-bit systems, the situation is more murky, because the ASAN allocation 89 | is completely outlandish - around 17.5 TB in older versions, and closer to 90 | 20 TB with newest ones. The actual amount of memory on your system is 91 | (probably!) just a tiny fraction of that - so unless you dial the limit 92 | with surgical precision, you will get no protection from OOM bugs. 93 | 94 | On my system, the amount of memory grabbed by ASAN with a slightly older 95 | version of gcc is around 17,825,850 MB; for newest clang, it's 20,971,600. 96 | But there is no guarantee that these numbers are stable, and if you get them 97 | wrong by "just" a couple gigs or so, you will be at risk. 98 | 99 | To get the precise number, you can use the recidivm tool developed by Jakub 100 | Wilk (http://jwilk.net/software/recidivm). In absence of this, ASAN is *not* 101 | recommended when fuzzing 64-bit binaries, unless you are confident that they 102 | are robust and enforce reasonable memory limits (in which case, you can 103 | specify '-m none' when calling afl-fuzz). 104 | 105 | Using recidivm or running with no limits aside, there are two other decent 106 | alternatives: build a corpus of test cases using a non-ASAN binary, and then 107 | examine them with ASAN, Valgrind, or other heavy-duty tools in a more 108 | controlled setting; or compile the target program with -m32 (32-bit mode) 109 | if your system supports that. 110 | 111 | 3) Interactions with the QEMU mode 112 | ---------------------------------- 113 | 114 | ASAN, MSAN, and other sanitizers appear to be incompatible with QEMU user 115 | emulation, so please do not try to use them with the -Q option; QEMU doesn't 116 | seem to appreciate the shadow VM trick used by these tools, and will likely 117 | just allocate all your physical memory, then crash. 118 | 119 | 4) What about UBSAN? 120 | -------------------- 121 | 122 | Some folks expressed interest in fuzzing with UBSAN. This isn't officially 123 | supported, because many installations of UBSAN don't offer a consistent way 124 | to abort() on fault conditions or to terminate with a distinctive exit code. 125 | 126 | That said, some versions of the library can be binary-patched to address this 127 | issue, while newer releases support explicit compile-time flags - see this 128 | mailing list thread for tips: 129 | 130 | https://groups.google.com/forum/#!topic/afl-users/GyeSBJt4M38 131 | -------------------------------------------------------------------------------- /docs/perf_tips.txt: -------------------------------------------------------------------------------- 1 | ================================= 2 | Tips for performance optimization 3 | ================================= 4 | 5 | This file provides tips for troubleshooting slow or wasteful fuzzing jobs. 6 | See README for the general instruction manual. 7 | 8 | 1) Keep your test cases small 9 | ----------------------------- 10 | 11 | This is probably the single most important step to take! Large test cases do 12 | not merely take more time and memory to be parsed by the tested binary, but 13 | also make the fuzzing process dramatically less efficient in several other 14 | ways. 15 | 16 | To illustrate, let's say that you're randomly flipping bits in a file, one bit 17 | at a time. Let's assume that if you flip bit #47, you will hit a security bug; 18 | flipping any other bit just results in an invalid document. 19 | 20 | Now, if your starting test case is 100 bytes long, you will have a 71% chance of 21 | triggering the bug within the first 1,000 execs - not bad! But if the test case 22 | is 1 kB long, the probability that we will randomly hit the right pattern in 23 | the same timeframe goes down to 11%. And if it has 10 kB of non-essential 24 | cruft, the odds plunge to 1%. 25 | 26 | On top of that, with larger inputs, the binary may be now running 5-10x times 27 | slower than before - so the overall drop in fuzzing efficiency may be easily 28 | as high as 500x or so. 29 | 30 | In practice, this means that you shouldn't fuzz image parsers with your 31 | vacation photos. Generate a tiny 16x16 picture instead, and run it through 32 | jpegtran or pngcrunch for good measure. The same goes for most other types 33 | of documents. 34 | 35 | There's plenty of small starting test cases in ../testcases/* - try them out 36 | or submit new ones! 37 | 38 | If you want to start with a larger, third-party corpus, run afl-cmin with an 39 | aggressive timeout on that data set first. 40 | 41 | 2) Use a simpler target 42 | ----------------------- 43 | 44 | Consider using a simpler target binary in your fuzzing work. For example, for 45 | image formats, bundled utilities such as djpeg, readpng, or gifhisto are 46 | considerably (10-20x) faster than the convert tool from ImageMagick - all while 47 | exercising roughly the same library-level image parsing code. 48 | 49 | Even if you don't have a lightweight harness for a particular target, remember 50 | that you can always use another, related library to generate a corpus that will 51 | be then manually fed to a more resource-hungry program later on. 52 | 53 | 3) Use LLVM instrumentation 54 | --------------------------- 55 | 56 | When fuzzing slow targets, you can gain 2x performance improvement by using 57 | the LLVM-based instrumentation mode described in llvm_mode/README.llvm. Note 58 | that this mode requires the use of clang and will not work with GCC. 59 | 60 | The LLVM mode also offers a "persistent", in-process fuzzing mode that can 61 | work well for certain types of self-contained libraries, and for fast targets, 62 | can offer performance gains up to 5-10x; and a "deferred fork server" mode 63 | that can offer huge benefits for programs with high startup overhead. Both 64 | modes require you to edit the source code of the fuzzed program, but the 65 | changes often amount to just strategically placing a single line or two. 66 | 67 | 4) Profile and optimize the binary 68 | ---------------------------------- 69 | 70 | Check for any parameters or settings that obviously improve performance. For 71 | example, the djpeg utility that comes with IJG jpeg and libjpeg-turbo can be 72 | called with: 73 | 74 | -dct fast -nosmooth -onepass -dither none -scale 1/4 75 | 76 | ...and that will speed things up. There is a corresponding drop in the quality 77 | of decoded images, but it's probably not something you care about. 78 | 79 | In some programs, it is possible to disable output altogether, or at least use 80 | an output format that is computationally inexpensive. For example, with image 81 | transcoding tools, converting to a BMP file will be a lot faster than to PNG. 82 | 83 | With some laid-back parsers, enabling "strict" mode (i.e., bailing out after 84 | first error) may result in smaller files and improved run time without 85 | sacrificing coverage; for example, for sqlite, you may want to specify -bail. 86 | 87 | If the program is still too slow, you can use strace -tt or an equivalent 88 | profiling tool to see if the targeted binary is doing anything silly. 89 | Sometimes, you can speed things up simply by specifying /dev/null as the 90 | config file, or disabling some compile-time features that aren't really needed 91 | for the job (try ./configure --help). One of the notoriously resource-consuming 92 | things would be calling other utilities via exec*(), popen(), system(), or 93 | equivalent calls; for example, tar can invoke external decompression tools 94 | when it decides that the input file is a compressed archive. 95 | 96 | Some programs may also intentionally call sleep(), usleep(), or nanosleep(); 97 | vim is a good example of that. 98 | 99 | In programs that are slow due to unavoidable initialization overhead, you may 100 | want to try the LLVM deferred forkserver mode (see llvm_mode/README.llvm), 101 | which can give you speed gains up to 10x, as mentioned above. 102 | 103 | Last but not least, if you are using ASAN and the performance is unacceptable, 104 | consider turning it off for now, and manually examining the generated corpus 105 | with an ASAN-enabled binary later on. 106 | 107 | 5) Instrument just what you need 108 | -------------------------------- 109 | 110 | Instrument just the libraries you actually want to stress-test right now, one 111 | at a time. Let the program use system-wide, non-instrumented libraries for 112 | any functionality you don't actually want to fuzz. For example, in most 113 | cases, it doesn't make to instrument libgmp just because you're testing a 114 | crypto app that relies on it for bignum math. 115 | 116 | Beware of programs that come with oddball third-party libraries bundled with 117 | their source code (Spidermonkey is a good example of this). Check ./configure 118 | options to use non-instrumented system-wide copies instead. 119 | 120 | 6) Parallelize your fuzzers 121 | --------------------------- 122 | 123 | The fuzzer is designed to need ~1 core per job. This means that on a, say, 124 | 4-core system, you can easily run four parallel fuzzing jobs with relatively 125 | little performance hit. For tips on how to do that, see parallel_fuzzing.txt. 126 | 127 | The afl-gotcpu utility can help you understand if you still have idle CPU 128 | capacity on your system. (It won't tell you about memory bandwidth, cache 129 | misses, or similar factors, but they are less likely to be a concern.) 130 | 131 | 7) Keep memory use and timeouts in check 132 | ---------------------------------------- 133 | 134 | If you have increased the -m or -t limits more than truly necessary, consider 135 | dialing them back down. 136 | 137 | For programs that are nominally very fast, but get sluggish for some inputs, 138 | you can also try setting -t values that are more punishing than what afl-fuzz 139 | dares to use on its own. On fast and idle machines, going down to -t 5 may be 140 | a viable plan. 141 | 142 | The -m parameter is worth looking at, too. Some programs can end up spending 143 | a fair amount of time allocating and initializing megabytes of memory when 144 | presented with pathological inputs. Low -m values can make them give up sooner 145 | and not waste CPU time. 146 | 147 | 8) Check OS configuration 148 | ------------------------- 149 | 150 | There are several OS-level factors that may affect fuzzing speed: 151 | 152 | - High system load. Use idle machines where possible. Kill any non-essential 153 | CPU hogs (idle browser windows, media players, complex screensavers, etc). 154 | 155 | - Network filesystems, either used for fuzzer input / output, or accessed by 156 | the fuzzed binary to read configuration files (pay special attention to the 157 | home directory - many programs search it for dot-files). 158 | 159 | - On-demand CPU scaling. The Linux 'ondemand' governor performs its analysis 160 | on a particular schedule and is known to underestimate the needs of 161 | short-lived processes spawned by afl-fuzz (or any other fuzzer). On Linux, 162 | this can be fixed with: 163 | 164 | cd /sys/devices/system/cpu 165 | echo performance | tee cpu*/cpufreq/scaling_governor 166 | 167 | On other systems, the impact of CPU scaling will be different; when fuzzing, 168 | use OS-specific tools to find out if all cores are running at full speed. 169 | 170 | - Suboptimal scheduling strategies. The significance of this will vary from 171 | one target to another, but on Linux, you may want to make sure that the 172 | following options are set: 173 | 174 | echo 1 >/proc/sys/kernel/sched_child_runs_first 175 | echo 1 >/proc/sys/kernel/sched_autogroup_enabled 176 | 177 | Setting a different scheduling policy for the fuzzer process - say 178 | SCHED_RR - can usually speed things up, too, but needs to be done with 179 | care. 180 | 181 | 9) If all other options fail, use -d 182 | ------------------------------------ 183 | 184 | For programs that are genuinely slow, in cases where you really can't escape 185 | using huge input files, or when you simply want to get quick and dirty results 186 | early on, you can always resort to the -d mode. 187 | 188 | The mode causes afl-fuzz to skip all the deterministic fuzzing steps, which 189 | makes output a lot less neat and makes the testing a bit less in-depth, but 190 | it will give you an experience more familiar from other fuzzing tools. 191 | -------------------------------------------------------------------------------- /docs/visualization/afl_gzip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/visualization/afl_gzip.png -------------------------------------------------------------------------------- /docs/vuln_samples/bash-cmd-exec.var: -------------------------------------------------------------------------------- 1 | () { _; } >_[$($())] { id; } -------------------------------------------------------------------------------- /docs/vuln_samples/bash-uninit-mem.var: -------------------------------------------------------------------------------- 1 | () { x() { _; }; x() { _; } <O));insert into t0 2 | select randomblob(0)-trim(0); 3 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-bad-ptr.sql: -------------------------------------------------------------------------------- 1 | SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE""""""""; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-bad-ptr2.sql: -------------------------------------------------------------------------------- 1 | PRAGMA foreign_keys=1;CREATE TABLE t1("""0"PRIMARY KEy REFERENCES t1 ON DELETE SET NULL);REPLACE INTO t1 SELECT(0); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-bad-ptr3.sql: -------------------------------------------------------------------------------- 1 | create table t(l);PRAGMA writable_schema=ON; 2 | UPDATE sqlite_master SET sql='00000000000000000000000000000000000000000000000000000000000000000000000000000000[%S';PRAGMA t;SAVEPOINT x;ROLLBACK;VACUUM; 3 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-heap-overflow.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS t;CREATE VIRTUAL TABLE t0 USING fts4();insert into t0 select zeroblob(0);SAVEPOINT O;insert into t0 2 | select(0);SAVEPOINT E;insert into t0 SELECT 0 UNION SELECT 0'x'ORDER BY x; 3 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-heap-overwrite.sql: -------------------------------------------------------------------------------- 1 | ATTACH "file:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA?mode=memory&cache=shared" AS x; -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-negative-memset.sql: -------------------------------------------------------------------------------- 1 | SELECT*from(select"",zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(150000000),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)),(select"",zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),(0),zeroblob(150000000),(0),zeroblob(0),(0)EXCEPT select zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr1.sql: -------------------------------------------------------------------------------- 1 | create table t0(t);insert into t0 2 | select strftime(); 3 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr10.sql: -------------------------------------------------------------------------------- 1 | SELECT fts3_tokenizer(@0()); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr11.sql: -------------------------------------------------------------------------------- 1 | select''like''like''like#0; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr12.sql: -------------------------------------------------------------------------------- 1 | PRAGMA e;select lower(0);select lower(0)"a",""GROUP BY a ORDER BY a; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr13.sql: -------------------------------------------------------------------------------- 1 | WITH x AS(SELECT*FROM t)SELECT""EXCEPT SELECT 0 ORDER BY 0 COLLATE""; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr14.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE x USING fts4();VALUES(0,0),(0,0),(0,0),(0,0);PRAGMA writable_schema=ON;UPDATE sqlite_master SET sql=''WHERE name='';UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';SAVEPOINT K;SAVEPOINT T;SAVEPOINT T;ANALYZE;ROLLBACK;SAVEPOINT E;DROP TABLE IF EXISTS t; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr15.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t4 USING fts4(0,b,c,notindexed=0);INSERT INTO t4 VALUES('','','0');BEGIN;INSERT INTO t4 VALUES('','','0');INSERT INTO t4(t4)VALUES('integrity-check'); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr2.sql: -------------------------------------------------------------------------------- 1 | DETACH(select group_concat(q)); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr3.sql: -------------------------------------------------------------------------------- 1 | select(select strftime()); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr4.sql: -------------------------------------------------------------------------------- 1 | select n()AND+#00; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr5.sql: -------------------------------------------------------------------------------- 1 | select e.*,0 from(s,(L))e; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr6.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/sqlite-null-ptr6.sql -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr7.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t USING fts4(tokenize=); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr8.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE p(a UNIQUE,PRIMARY KEY('a'))WITHOUT rowid; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-null-ptr9.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE t0(z);WITH d(x)AS(SELECT*UNION SELECT 0)INSERT INTO t0 SELECT 0 FROM d; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-oob-read.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/sqlite-oob-read.sql -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-oob-write.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t0 USING fts4(x,order=DESC); 2 | INSERT INTO t0(docid,x)VALUES(-1E0,'0(o'); 3 | INSERT INTO t0 VALUES(''); 4 | INSERT INTO t0 VALUES(''); 5 | INSeRT INTO t0 VALUES('o'); 6 | SELECT docid FROM t0 WHERE t0 MATCH'"0*o"'; 7 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-stack-buf-overflow.sql: -------------------------------------------------------------------------------- 1 | SELECT printf('%*.*f',90000||006000000&6600000000,00000000000000000909000000000000.0000000000000000)""WHERE"">""; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-stack-exhaustion.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t0 USING fts4(content=t0); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-unint-mem.sql: -------------------------------------------------------------------------------- 1 | REATE VIRTUAL TABLE t0 USING fts4(prefix=0);INSERT INTO t0 VALUES(0); 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/sqlite-use-after-free.sql: -------------------------------------------------------------------------------- 1 | create table t(s);PRAGMA writable_schema=ON;UPDATE sqlite_master SET sql='ANALYZE;CREATE VIRTUAL TABLE t USING fts3;DROP TABLE t;DROP TABLE EXISTS t';PRAGMA r;SAVEPOINT T;ANALYZE;ROLLBACK;SAVEPOINT E;DROP TABLE IF EXISTS t; 2 | -------------------------------------------------------------------------------- /docs/vuln_samples/strings-bfd-badptr.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/strings-bfd-badptr.elf -------------------------------------------------------------------------------- /docs/vuln_samples/strings-bfd-badptr2.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/strings-bfd-badptr2.elf -------------------------------------------------------------------------------- /docs/vuln_samples/strings-stack-overflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/strings-stack-overflow -------------------------------------------------------------------------------- /docs/vuln_samples/strings-unchecked-ctr.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/strings-unchecked-ctr.elf -------------------------------------------------------------------------------- /docs/vuln_samples/tcpdump-arp-crash.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/tcpdump-arp-crash.pcap -------------------------------------------------------------------------------- /docs/vuln_samples/tcpdump-ppp-crash.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/tcpdump-ppp-crash.pcap -------------------------------------------------------------------------------- /docs/vuln_samples/unrtf-arbitrary-read.rtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/unrtf-arbitrary-read.rtf -------------------------------------------------------------------------------- /docs/vuln_samples/unzip-t-mem-corruption.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leetchicken/afl/cec3f4cb22d106b9ce2848fc3eac8e5c28ac5753/docs/vuln_samples/unzip-t-mem-corruption.zip -------------------------------------------------------------------------------- /experimental/README.experiments: -------------------------------------------------------------------------------- 1 | Here's a quick overview of the stuff you can find in this directory: 2 | 3 | - argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed 4 | (e.g., to test setuid programs). 5 | 6 | - asan_cgroups - a contributed script to simplify fuzzing ASAN 7 | binaries with robust memory limits on Linux. 8 | 9 | - bash_shellshock - a simple hack used to find a bunch of 10 | post-Shellshock bugs in bash. 11 | 12 | - canvas_harness - a test harness used to find browser bugs with a 13 | corpus generated using simple image parsing 14 | binaries & afl-fuzz. 15 | 16 | - clang_asm_normalize - a script that makes it easy to instrument 17 | hand-written assembly, provided that you have clang. 18 | 19 | - crash_triage - a very rudimentary example of how to annotate crashes 20 | with additional gdb metadata. 21 | 22 | - distributed_fuzzing - a sample script for synchronizing fuzzer instances 23 | across multiple machines (see parallel_fuzzing.txt). 24 | 25 | - instrumented_cmp - an experiment showing how a custom memcmp() or 26 | strcmp() can be used to work around one of the 27 | limitations of afl-fuzz. 28 | 29 | - libpng_no_checksum - a sample patch for removing CRC checks in libpng. 30 | 31 | - persistent_demo - an example of how to use the LLVM persistent process 32 | mode to speed up certain fuzzing jobs. 33 | 34 | - post_library - an example of how to build postprocessors for AFL. 35 | 36 | Note that the minimize_corpus.sh tool has graduated from the experimental/ 37 | directory and is now available as ../afl-cmin. The LLVM mode has likewise 38 | graduated to ../llvm_mode/*. 39 | 40 | Most of the tools in this directory are meant chiefly as examples that need to 41 | be tweaked for your specific needs. They come with some basic documentation, 42 | but are not necessarily production-grade. 43 | -------------------------------------------------------------------------------- /experimental/argv_fuzzing/argv-fuzz-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - sample argv fuzzing wrapper 3 | ------------------------------------------------ 4 | 5 | Written by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | This file shows a simple way to fuzz command-line parameters with stock 16 | afl-fuzz. To use, add: 17 | 18 | #include "/path/to/argv-fuzz-inl.h" 19 | 20 | ...to the file containing main(), ideally placing it after all the 21 | standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of 22 | main(). 23 | 24 | This will cause the program to read NUL-delimited input from stdin and 25 | put it in argv[]. Two subsequent NULs terminate the array. Empty 26 | params are encoded as a lone 0x02. Lone 0x02 can't be generated, but 27 | that shouldn't matter in real life. 28 | 29 | If you would like to always preserve argv[0], use this instead: 30 | AFL_INIT_SET0("prog_name"); 31 | 32 | */ 33 | 34 | #ifndef _HAVE_ARGV_FUZZ_INL 35 | #define _HAVE_ARGV_FUZZ_INL 36 | 37 | #include 38 | 39 | #define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0) 40 | 41 | #define AFL_INIT_SET0(_p) do { \ 42 | argv = afl_init_argv(&argc); \ 43 | argv[0] = (_p); \ 44 | if (!argc) argc = 1; \ 45 | } while (0) 46 | 47 | #define MAX_CMDLINE_LEN 100000 48 | #define MAX_CMDLINE_PAR 1000 49 | 50 | static char** afl_init_argv(int* argc) { 51 | 52 | static char in_buf[MAX_CMDLINE_LEN]; 53 | static char* ret[MAX_CMDLINE_PAR]; 54 | 55 | char* ptr = in_buf; 56 | int rc = 0; 57 | 58 | if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0); 59 | 60 | while (*ptr) { 61 | 62 | ret[rc] = ptr; 63 | if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; 64 | rc++; 65 | 66 | while (*ptr) ptr++; 67 | ptr++; 68 | 69 | } 70 | 71 | *argc = rc; 72 | 73 | return ret; 74 | 75 | } 76 | 77 | #undef MAX_CMDLINE_LEN 78 | #undef MAX_CMDLINE_PAR 79 | 80 | #endif /* !_HAVE_ARGV_FUZZ_INL */ 81 | -------------------------------------------------------------------------------- /experimental/asan_cgroups/limit_memory.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # american fuzzy lop - limit memory using cgroups 4 | # ----------------------------------------------- 5 | # 6 | # Written by Samir Khakimov and 7 | # David A. Wheeler 8 | # 9 | # Edits to bring the script in line with afl-cmin and other companion scripts 10 | # by Michal Zalewski . All bugs are my fault. 11 | # 12 | # Copyright 2015 Institute for Defense Analyses. 13 | # 14 | # Licensed under the Apache License, Version 2.0 (the "License"); 15 | # you may not use this file except in compliance with the License. 16 | # You may obtain a copy of the License at: 17 | # 18 | # http://www.apache.org/licenses/LICENSE-2.0 19 | # 20 | # This tool allows the amount of actual memory allocated to a program 21 | # to be limited on Linux systems using cgroups, instead of the traditional 22 | # setrlimit() API. This helps avoid the address space problems discussed in 23 | # docs/notes_for_asan.txt. 24 | # 25 | # Important: the limit covers *both* afl-fuzz and the fuzzed binary. In some 26 | # hopefully rare circumstances, afl-fuzz could be killed before the fuzzed 27 | # task. 28 | # 29 | 30 | echo "cgroup tool for afl-fuzz by and " 31 | echo 32 | 33 | unset NEW_USER 34 | MEM_LIMIT="50" 35 | 36 | while getopts "+u:m:" opt; do 37 | 38 | case "$opt" in 39 | 40 | "u") 41 | NEW_USER="$OPTARG" 42 | ;; 43 | 44 | "m") 45 | MEM_LIMIT="$[OPTARG]" 46 | ;; 47 | 48 | "?") 49 | exit 1 50 | ;; 51 | 52 | esac 53 | 54 | done 55 | 56 | if [ "$MEM_LIMIT" -lt "5" ]; then 57 | echo "[-] Error: malformed or dangerously low value of -m." 1>&2 58 | exit 1 59 | fi 60 | 61 | shift $((OPTIND-1)) 62 | 63 | TARGET_BIN="$1" 64 | 65 | if [ "$TARGET_BIN" = "" -o "$NEW_USER" = "" ]; then 66 | 67 | cat 1>&2 <<_EOF_ 68 | Usage: $0 [ options ] -- /path/to/afl-fuzz [ ...afl options... ] 69 | 70 | Required parameters: 71 | 72 | -u user - run the fuzzer as a specific user after setting up limits 73 | 74 | Optional parameters: 75 | 76 | -m megs - set memory limit to a specified value ($MEM_LIMIT MB) 77 | 78 | This tool configures cgroups-based memory limits for a fuzzing job to simplify 79 | the task of fuzzing ASAN or MSAN binaries. You would normally want to use it in 80 | conjunction with '-m none' passed to the afl-fuzz binary itself, say: 81 | 82 | $0 -u joe ./afl-fuzz -i input -o output -m none /path/to/target 83 | 84 | _EOF_ 85 | 86 | exit 1 87 | 88 | fi 89 | 90 | # Basic sanity checks 91 | 92 | if [ ! "`uname -s`" = "Linux" ]; then 93 | echo "[-] Error: this tool does not support non-Linux systems." 1>&2 94 | exit 1 95 | fi 96 | 97 | if [ ! "`id -u`" = "0" ]; then 98 | echo "[-] Error: you need to run this script as root (sorry!)." 1>&2 99 | exit 1 100 | fi 101 | 102 | if ! type cgcreate 2>/dev/null 1>&2; then 103 | 104 | echo "[-] Error: you need to install cgroup tools first." 1>&2 105 | 106 | if type apt-get 2>/dev/null 1>&2; then 107 | echo " (Perhaps 'apt-get install cgroup-bin' will work.)" 1>&2 108 | elif type yum 2>/dev/null 1>&2; then 109 | echo " (Perhaps 'yum install libcgroup-tools' will work.)" 1>&2 110 | fi 111 | 112 | exit 1 113 | 114 | fi 115 | 116 | if ! id -u "$NEW_USER" 2>/dev/null 1>&2; then 117 | echo "[-] Error: user '$NEW_USER' does not seem to exist." 1>&2 118 | exit 1 119 | fi 120 | 121 | # Create a new cgroup path if necessary... We used PID-keyed groups to keep 122 | # parallel afl-fuzz tasks separate from each other. 123 | 124 | CID="afl-$NEW_USER-$$" 125 | 126 | CPATH="/sys/fs/cgroup/memory/$CID" 127 | 128 | if [ ! -d "$CPATH" ]; then 129 | 130 | cgcreate -a "$NEW_USER" -g memory:"$CID" || exit 1 131 | 132 | fi 133 | 134 | # Set the appropriate limit... 135 | 136 | if [ -f "$CPATH/memory.memsw.limit_in_bytes" ]; then 137 | 138 | echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" 2>/dev/null 139 | echo "${MEM_LIMIT}M" > "$CPATH/memory.memsw.limit_in_bytes" || exit 1 140 | echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" || exit 1 141 | 142 | elif grep -qE 'partition|file' /proc/swaps; then 143 | 144 | echo "[-] Error: your system requires swap to be disabled first (swapoff -a)." 1>&2 145 | exit 1 146 | 147 | else 148 | 149 | echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" || exit 1 150 | 151 | fi 152 | 153 | # All right. At this point, we can just run the command. 154 | 155 | cgexec -g "memory:$CID" su -c "$*" "$NEW_USER" 156 | 157 | cgdelete -g "memory:$CID" 158 | -------------------------------------------------------------------------------- /experimental/bash_shellshock/shellshock-fuzz.diff: -------------------------------------------------------------------------------- 1 | This patch shows a very simple way to find post-Shellshock bugs in bash, as 2 | discussed here: 3 | 4 | http://lcamtuf.blogspot.com/2014/10/bash-bug-how-we-finally-cracked.html 5 | 6 | In essence, it shows a way to fuzz environmental variables. Instructions: 7 | 8 | 1) Download bash 4.3, apply this patch, compile with: 9 | 10 | CC=/path/to/afl-gcc ./configure 11 | make clean all 12 | 13 | Note that the harness puts the fuzzed output in $TEST_VARIABLE. With 14 | Florian's Shellshock patch (bash43-028), this is no longer passed down 15 | to the parser. 16 | 17 | 2) Create and cd to an empty directory, put the compiled bash binary in 18 | there, and run these commands: 19 | 20 | mkdir in_dir 21 | echo -n '() { a() { a; }; : >b; }' >in_dir/script.txt 22 | 23 | 3) Run the fuzzer with: 24 | 25 | /path/to/afl-fuzz -d -i in_dir -o out_dir ./bash -c : 26 | 27 | The -d parameter is advisable only if the tested shell is fairly slow 28 | or if you are in a hurry; will cover more ground faster, but 29 | less systematically. 30 | 31 | 4) Watch for crashes in out_dir/crashes/. Also watch for any new files 32 | created in cwd if you're interested in non-crash RCEs (files will be 33 | created whenever the shell executes "foo>bar" or something like 34 | that). You can correlate their creation date with new entries in 35 | out_dir/queue/. 36 | 37 | You can also modify the bash binary to directly check for more subtle 38 | fault conditions, or use the synthesized entries in out_dir/queue/ 39 | as a seed for other, possibly slower or more involved testing regimes. 40 | 41 | Expect several hours to get decent coverage. 42 | 43 | --- bash-4.3/shell.c.orig 2014-01-14 14:04:32.000000000 +0100 44 | +++ bash-4.3/shell.c 2015-04-30 05:56:46.000000000 +0200 45 | @@ -371,6 +371,14 @@ 46 | env = environ; 47 | #endif /* __OPENNT */ 48 | 49 | + { 50 | + 51 | + static char val[1024 * 16]; 52 | + read(0, val, sizeof(val) - 1); 53 | + setenv("TEST_VARIABLE", val, 1); 54 | + 55 | + } 56 | + 57 | USE_VAR(argc); 58 | USE_VAR(argv); 59 | USE_VAR(env); 60 | -------------------------------------------------------------------------------- /experimental/canvas_harness/canvas_harness.html: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 |

31 | 32 |
33 | 34 | 35 | 36 |

Results

37 | 38 |
    39 | 40 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /experimental/clang_asm_normalize/as: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # american fuzzy lop - clang assembly normalizer 4 | # ---------------------------------------------- 5 | # 6 | # Written and maintained by Michal Zalewski 7 | # The idea for this wrapper comes from Ryan Govostes. 8 | # 9 | # Copyright 2013, 2014 Google Inc. All rights reserved. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at: 14 | # 15 | # http://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # This 'as' wrapper should allow you to instrument unruly, hand-written 18 | # assembly with afl-as. 19 | # 20 | # Usage: 21 | # 22 | # export AFL_REAL_PATH=/path/to/directory/with/afl-as/ 23 | # AFL_PATH=/path/to/this/directory/ make clean all 24 | 25 | if [ "$#" -lt "2" ]; then 26 | echo "[-] Error: this utility can't be called directly." 1>&2 27 | exit 1 28 | fi 29 | 30 | if [ "$AFL_REAL_PATH" = "" ]; then 31 | echo "[-] Error: AFL_REAL_PATH not set!" 1>&2 32 | exit 1 33 | fi 34 | 35 | if [ ! -x "$AFL_REAL_PATH/afl-as" ]; then 36 | echo "[-] Error: AFL_REAL_PATH does not contain the 'afl-as' binary." 1>&2 37 | exit 1 38 | fi 39 | 40 | unset __AFL_AS_CMDLINE __AFL_FNAME 41 | 42 | while [ ! "$#" = "0" ]; do 43 | 44 | if [ "$#" = "1" ]; then 45 | __AFL_FNAME="$1" 46 | else 47 | __AFL_AS_CMDLINE="${__AFL_AS_CMDLINE} $1" 48 | fi 49 | 50 | shift 51 | 52 | done 53 | 54 | test "$TMPDIR" = "" && TMPDIR=/tmp 55 | 56 | TMPFILE=`mktemp $TMPDIR/.afl-XXXXXXXXXX.s` 57 | 58 | test "$TMPFILE" = "" && exit 1 59 | 60 | clang -cc1as -filetype asm -output-asm-variant 0 "${__AFL_FNAME}" >"$TMPFILE" 61 | 62 | ERR="$?" 63 | 64 | if [ ! "$ERR" = "0" ]; then 65 | rm -f "$TMPFILE" 66 | exit $ERR 67 | fi 68 | 69 | "$AFL_REAL_PATH/afl-as" ${__AFL_AS_CMDLINE} "$TMPFILE" 70 | 71 | ERR="$?" 72 | 73 | rm -f "$TMPFILE" 74 | 75 | exit "$ERR" 76 | -------------------------------------------------------------------------------- /experimental/crash_triage/triage_crashes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # american fuzzy lop - crash triage utility 4 | # ----------------------------------------- 5 | # 6 | # Written and maintained by Michal Zalewski 7 | # 8 | # Copyright 2013, 2014 Google Inc. All rights reserved. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at: 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Note that this assumes that the targeted application reads from stdin 17 | # and requires no other cmdline parameters. Modify as needed if this is 18 | # not the case. 19 | # 20 | # Note that on OpenBSD, you may need to install a newer version of gdb 21 | # (e.g., from ports). You can set GDB=/some/path to point to it if 22 | # necessary. 23 | # 24 | 25 | echo "crash triage utility for afl-fuzz by " 26 | echo 27 | 28 | ulimit -v 100000 2>/dev/null 29 | ulimit -d 100000 2>/dev/null 30 | 31 | if [ ! "$#" = "2" ]; then 32 | echo "Usage: $0 /path/to/afl_output_dir /path/to/tested_binary" 1>&2 33 | echo 1>&2 34 | echo "Note: the tested binary must accept input on stdin and require no additional" 1>&2 35 | echo "parameters. For more complex use cases, you need to edit this script." 1>&2 36 | echo 1>&2 37 | exit 1 38 | fi 39 | 40 | DIR="$1" 41 | BIN="$2" 42 | 43 | echo "$DIR" | grep -qE '^(/var)?/tmp/' 44 | T1="$?" 45 | 46 | echo "$BIN" | grep -qE '^(/var)?/tmp/' 47 | T2="$?" 48 | 49 | if [ "$T1" = "0" -o "$T2" = "0" ]; then 50 | echo "[-] Error: do not use shared /tmp or /var/tmp directories with this script." 1>&2 51 | exit 1 52 | fi 53 | 54 | if [ "$GDB" = "" ]; then 55 | GDB=gdb 56 | fi 57 | 58 | if [ ! -f "$BIN" -o ! -x "$BIN" ]; then 59 | echo "[-] Error: binary '$2' not found or is not executable." 1>&2 60 | exit 1 61 | fi 62 | 63 | if [ ! -d "$DIR/queue" ]; then 64 | echo "[-] Error: directory '$1' not found or not created by afl-fuzz." 1>&2 65 | exit 1 66 | fi 67 | 68 | CCOUNT=$((`ls -- "$DIR/crashes" 2>/dev/null | wc -l`)) 69 | 70 | if [ "$CCOUNT" = "0" ]; then 71 | echo "No crashes recorded in the target directory - nothing to be done." 72 | exit 0 73 | fi 74 | 75 | echo 76 | 77 | for crash in $DIR/crashes/id:*; do 78 | 79 | id=`basename -- "$crash" | cut -d, -f1 | cut -d: -f2` 80 | sig=`basename -- "$crash" | cut -d, -f2 | cut -d: -f2` 81 | 82 | echo "+++ ID $id, SIGNAL $sig +++" 83 | echo 84 | 85 | $GDB --batch -q --ex "r <$crash" --ex 'back' --ex 'disass $pc, $pc+16' --ex 'info reg' --ex 'quit' "$BIN" 0 7 | # 8 | # Copyright 2014 Google Inc. All rights reserved. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at: 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # To make this script work: 17 | # 18 | # - Edit FUZZ_HOSTS, FUZZ_DOMAIN, FUZZ_USER, and SYNC_DIR to reflect your 19 | # environment. 20 | # 21 | # - Make sure that the system you are running this on can log into FUZZ_HOSTS 22 | # without a password (authorized_keys or otherwise). 23 | # 24 | # - Make sure that every fuzzer is running with -o pointing to SYNC_DIR and -S 25 | # that consists of its local host name, followed by an underscore, and then 26 | # by some host-local fuzzer ID. 27 | # 28 | 29 | # Hosts to synchronize the data across. 30 | FUZZ_HOSTS='host1 host2 host3 host4' 31 | 32 | # Domain for all hosts 33 | FUZZ_DOMAIN='example.com' 34 | 35 | # Remote user for SSH 36 | FUZZ_USER=bob 37 | 38 | # Directory to synchronize 39 | SYNC_DIR='/home/bob/sync_dir' 40 | 41 | # Interval (seconds) between sync attempts 42 | SYNC_INTERVAL=$((30 * 60)) 43 | 44 | if [ "$PWD" = "/tmp" -o "$PWD" = "/var/tmp" ]; then 45 | echo "[-] Error: do not use shared /tmp or /var/tmp directories with this script." 1>&2 46 | exit 1 47 | fi 48 | 49 | rm -rf .sync_tmp 2>/dev/null 50 | mkdir .sync_tmp || exit 1 51 | 52 | while :; do 53 | 54 | # Pull data in... 55 | 56 | for host in $FUZZ_HOSTS; do 57 | 58 | echo "[*] Retrieving data from ${host}.${FUZZ_DOMAIN}..." 59 | 60 | ssh -o 'passwordauthentication no' ${FUZZ_USER}@${host}.$FUZZ_DOMAIN \ 61 | "cd '$SYNC_DIR' && tar -czf - ${host}_*/[qf]*" >".sync_tmp/${host}.tgz" 62 | 63 | done 64 | 65 | # Distribute data. For large fleets, see tips in the docs/ directory. 66 | 67 | for dst_host in $FUZZ_HOSTS; do 68 | 69 | echo "[*] Distributing data to ${dst_host}.${FUZZ_DOMAIN}..." 70 | 71 | for src_host in $FUZZ_HOSTS; do 72 | 73 | test "$src_host" = "$dst_host" && continue 74 | 75 | echo " Sending fuzzer data from ${src_host}.${FUZZ_DOMAIN}..." 76 | 77 | ssh -o 'passwordauthentication no' ${FUZZ_USER}@$dst_host \ 78 | "cd '$SYNC_DIR' && tar -xkzf -" <".sync_tmp/${src_host}.tgz" 79 | 80 | done 81 | 82 | done 83 | 84 | echo "[+] Done. Sleeping for $SYNC_INTERVAL seconds (Ctrl-C to quit)." 85 | 86 | sleep $SYNC_INTERVAL 87 | 88 | done 89 | 90 | -------------------------------------------------------------------------------- /experimental/instrumented_cmp/instrumented_cmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | american fuzzy lop - instrumented strcmp() or memcmp() proof-of-concept 4 | ----------------------------------------------------------------------- 5 | 6 | Written and maintained by Michal Zalewski 7 | 8 | Copyright 2015 Google Inc. All rights reserved. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at: 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Normally, afl-fuzz will have difficulty ever reaching the code behind 17 | something like: 18 | 19 | if (!strcmp(password, "s3cr3t!")) ... 20 | 21 | This is because the strcmp() operation is completely opaque to the tool. 22 | A simple and non-invasive workaround that doesn't require complex code 23 | analysis is to replace strcmp(), memcmp(), and equivalents with 24 | inlined, non-optimized code. 25 | 26 | I am still evaluating the value of doing this, but for time being, here's 27 | a quick demo of how it may work. To test: 28 | 29 | $ ./afl-gcc instrumented_cmp.c 30 | $ mkdir test_in 31 | $ printf xxxxxxxxxxxxxxxx >test_in/input 32 | $ ./afl-fuzz -i test_in -o test_out ./a.out 33 | 34 | */ 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | /* Naive instrumented memcmp(). */ 41 | 42 | inline int my_memcmp(char* ptr1, char* ptr2, int len) 43 | __attribute__((always_inline)); 44 | 45 | inline int my_memcmp(char* ptr1, char* ptr2, int len) { 46 | 47 | while (len--) if (*(ptr1++) ^ *(ptr2++)) return 1; 48 | return 0; 49 | 50 | } 51 | 52 | #define memcmp my_memcmp 53 | 54 | /* Normal program. */ 55 | 56 | char tmp[16]; 57 | 58 | int main(int argc, char** argv) { 59 | 60 | int len = read(0, tmp, sizeof(tmp)); 61 | 62 | if (len != sizeof(tmp)) { 63 | 64 | printf("Truncated file!\n"); 65 | exit(1); 66 | 67 | } 68 | 69 | if (!memcmp(tmp + 5, "sesame", 6)) { 70 | 71 | /* Simulated "faulty" code path. */ 72 | 73 | int* x = (int*)0x12345678; 74 | *x = 1; 75 | 76 | } else printf("Bad password.\n"); 77 | 78 | return 0; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /experimental/libpng_no_checksum/libpng-nocrc.patch: -------------------------------------------------------------------------------- 1 | --- pngrutil.c.orig 2014-06-12 03:35:16.000000000 +0200 2 | +++ pngrutil.c 2014-07-01 05:08:31.000000000 +0200 3 | @@ -268,7 +268,11 @@ 4 | if (need_crc != 0) 5 | { 6 | crc = png_get_uint_32(crc_bytes); 7 | - return ((int)(crc != png_ptr->crc)); 8 | + 9 | + if (crc != png_ptr->crc) 10 | + fprintf(stderr, "NOTE: CRC in the file is 0x%08x, change to 0x%08x\n", crc, png_ptr->crc); 11 | + 12 | + return ((int)(1 != 1)); 13 | } 14 | 15 | else 16 | -------------------------------------------------------------------------------- /experimental/persistent_demo/persistent_demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - persistent mode example 3 | -------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | This file demonstrates the high-performance "persistent mode" that may be 16 | suitable for fuzzing certain fast and well-behaved libraries, provided that 17 | they are stateless or that their internal state can be easily reset 18 | across runs. 19 | 20 | To make this work, the library and this shim need to be compiled in LLVM 21 | mode using afl-clang-fast (other compiler wrappers will *not* work). 22 | 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | /* Main entry point. */ 33 | 34 | int main(int argc, char** argv) { 35 | 36 | char buf[100]; /* Example-only buffer, you'd replace it with other global or 37 | local variables appropriate for your use case. */ 38 | 39 | /* The number passed to __AFL_LOOP() controls the maximum number of 40 | iterations before the loop exits and the program is allowed to 41 | terminate normally. This limits the impact of accidental memory leaks 42 | and similar hiccups. */ 43 | 44 | while (__AFL_LOOP(1000)) { 45 | 46 | /*** PLACEHOLDER CODE ***/ 47 | 48 | /* STEP 1: Fully re-initialize all critical variables. In our example, this 49 | involves zeroing buf[], our input buffer. */ 50 | 51 | memset(buf, 0, 100); 52 | 53 | /* STEP 2: Read input data. When reading from stdin, no special preparation 54 | is required. When reading from a named file, you need to close 55 | the old descriptor and reopen the file first! 56 | 57 | Beware of reading from buffered FILE* objects such as stdin. Use 58 | raw file descriptors or call fopen() / fdopen() in every pass. */ 59 | 60 | read(0, buf, 100); 61 | 62 | /* STEP 3: This is where we'd call the tested library on the read data. 63 | We just have some trivial inline code that faults on 'foo!'. */ 64 | 65 | if (buf[0] == 'f') { 66 | printf("one\n"); 67 | if (buf[1] == 'o') { 68 | printf("two\n"); 69 | if (buf[2] == 'o') { 70 | printf("three\n"); 71 | if (buf[3] == '!') { 72 | printf("four\n"); 73 | abort(); 74 | } 75 | } 76 | } 77 | } 78 | 79 | /*** END PLACEHOLDER CODE ***/ 80 | 81 | } 82 | 83 | /* Once the loop is exited, terminate normally - AFL will restart the process 84 | when this happens, with a clean slate when it comes to allocated memory, 85 | leftover file descriptors, etc. */ 86 | 87 | return 0; 88 | 89 | } 90 | -------------------------------------------------------------------------------- /experimental/post_library/post_library.so.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - postprocessor library example 3 | -------------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Postprocessor libraries can be passed to afl-fuzz to perform final cleanup 16 | of any mutated test cases - for example, to fix up checksums in PNG files. 17 | 18 | Please heed the following warnings: 19 | 20 | 1) In almost all cases, it is more productive to comment out checksum logic 21 | in the targeted binary (as shown in ../libpng_no_checksum/). One possible 22 | exception is the process of fuzzing binary-only software in QEMU mode. 23 | 24 | 2) The use of postprocessors for anything other than checksums is questionable 25 | and may cause more harm than good. AFL is normally pretty good about 26 | dealing with length fields, magic values, etc. 27 | 28 | 3) Postprocessors that do anything non-trivial must be extremely robust to 29 | gracefully handle malformed data and other error conditions - otherwise, 30 | they will crash and take afl-fuzz down with them. Be wary of reading past 31 | *len and of integer overflows when calculating file offsets. 32 | 33 | In other words, THIS IS PROBABLY NOT WHAT YOU WANT - unless you really, 34 | honestly know what you're doing =) 35 | 36 | With that out of the way: the postprocessor library is passed to afl-fuzz 37 | via AFL_POST_LIBRARY. The library must be compiled with: 38 | 39 | gcc -shared -Wall -O3 post_library.so.c -o post_library.so 40 | 41 | AFL will call the afl_postprocess() function for every mutated output buffer. 42 | From there, you have three choices: 43 | 44 | 1) If you don't want to modify the test case, simply return the original 45 | buffer pointer ('in_buf'). 46 | 47 | 2) If you want to skip this test case altogether and have AFL generate a 48 | new one, return NULL. Use this sparingly - it's faster than running 49 | the target program with patently useless inputs, but still wastes CPU 50 | time. 51 | 52 | 3) If you want to modify the test case, allocate an appropriately-sized 53 | buffer, move the data into that buffer, make the necessary changes, and 54 | then return the new pointer. You can update *len if necessary, too. 55 | 56 | Note that the buffer will *not* be freed for you. To avoid memory leaks, 57 | you need to free it or reuse it on subsequent calls (as shown below). 58 | 59 | *** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. *** 60 | 61 | Aight. The example below shows a simple postprocessor that tries to make 62 | sure that all input files start with "GIF89a". 63 | 64 | PS. If you don't like C, you can try out the unix-based wrapper from 65 | Ben Nagy instead: https://github.com/bnagy/aflfix 66 | 67 | */ 68 | 69 | #include 70 | #include 71 | #include 72 | 73 | /* Header that must be present at the beginning of every test case: */ 74 | 75 | #define HEADER "GIF89a" 76 | 77 | /* The actual postprocessor routine called by afl-fuzz: */ 78 | 79 | const unsigned char* afl_postprocess(const unsigned char* in_buf, 80 | unsigned int* len) { 81 | 82 | static unsigned char* saved_buf; 83 | unsigned char* new_buf; 84 | 85 | /* Skip execution altogether for buffers shorter than 6 bytes (just to 86 | show how it's done). We can trust *len to be sane. */ 87 | 88 | if (*len < strlen(HEADER)) return NULL; 89 | 90 | /* Do nothing for buffers that already start with the expected header. */ 91 | 92 | if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf; 93 | 94 | /* Allocate memory for new buffer, reusing previous allocation if 95 | possible. */ 96 | 97 | new_buf = realloc(saved_buf, *len); 98 | 99 | /* If we're out of memory, the most graceful thing to do is to return the 100 | original buffer and give up on modifying it. Let AFL handle OOM on its 101 | own later on. */ 102 | 103 | if (!new_buf) return in_buf; 104 | saved_buf = new_buf; 105 | 106 | /* Copy the original data to the new location. */ 107 | 108 | memcpy(new_buf, in_buf, *len); 109 | 110 | /* Insert the new header. */ 111 | 112 | memcpy(new_buf, HEADER, strlen(HEADER)); 113 | 114 | /* Return modified buffer. No need to update *len in this particular case, 115 | as we're not changing it. */ 116 | 117 | return new_buf; 118 | 119 | } 120 | -------------------------------------------------------------------------------- /experimental/post_library/post_library_png.so.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - postprocessor for PNG 3 | ------------------------------------------ 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | See post_library.so.c for a general discussion of how to implement 16 | postprocessors. This specific postprocessor attempts to fix up PNG 17 | checksums, providing a slightly more complicated example than found 18 | in post_library.so.c. 19 | 20 | Compile with: 21 | 22 | gcc -shared -Wall -O3 post_library_png.so.c -o post_library_png.so -lz 23 | 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | /* A macro to round an integer up to 4 kB. */ 35 | 36 | #define UP4K(_i) ((((_i) >> 12) + 1) << 12) 37 | 38 | const unsigned char* afl_postprocess(const unsigned char* in_buf, 39 | unsigned int* len) { 40 | 41 | static unsigned char* saved_buf; 42 | static unsigned int saved_len; 43 | 44 | unsigned char* new_buf = (unsigned char*)in_buf; 45 | unsigned int pos = 8; 46 | 47 | /* Don't do anything if there's not enough room for the PNG header 48 | (8 bytes). */ 49 | 50 | if (*len < 8) return in_buf; 51 | 52 | /* Minimum size of a zero-length PNG chunk is 12 bytes; if we 53 | don't have that, we can bail out. */ 54 | 55 | while (pos + 12 <= *len) { 56 | 57 | unsigned int chunk_len, real_cksum, file_cksum; 58 | 59 | /* Chunk length is the first big-endian dword in the chunk. */ 60 | 61 | chunk_len = ntohl(*(uint32_t*)(in_buf + pos)); 62 | 63 | /* Bail out if chunk size is too big or goes past EOF. */ 64 | 65 | if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > *len) break; 66 | 67 | /* Chunk checksum is calculated for chunk ID (dword) and the actual 68 | payload. */ 69 | 70 | real_cksum = htonl(crc32(0, in_buf + pos + 4, chunk_len + 4)); 71 | 72 | /* The in-file checksum is the last dword past the chunk data. */ 73 | 74 | file_cksum = *(uint32_t*)(in_buf + pos + 8 + chunk_len); 75 | 76 | /* If the checksums do not match, we need to fix the file. */ 77 | 78 | if (real_cksum != file_cksum) { 79 | 80 | /* First modification? Make a copy of the input buffer. Round size 81 | up to 4 kB to minimize the number of reallocs needed. */ 82 | 83 | if (new_buf == in_buf) { 84 | 85 | if (*len <= saved_len) { 86 | 87 | new_buf = saved_buf; 88 | 89 | } else { 90 | 91 | new_buf = realloc(saved_buf, UP4K(*len)); 92 | if (!new_buf) return in_buf; 93 | saved_buf = new_buf; 94 | saved_len = UP4K(*len); 95 | memcpy(new_buf, in_buf, *len); 96 | 97 | } 98 | 99 | } 100 | 101 | *(uint32_t*)(new_buf + pos + 8 + chunk_len) = real_cksum; 102 | 103 | } 104 | 105 | /* Skip the entire chunk and move to the next one. */ 106 | 107 | pos += 12 + chunk_len; 108 | 109 | } 110 | 111 | return new_buf; 112 | 113 | } 114 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - hashing function 3 | ------------------------------------- 4 | 5 | The hash32() function is a variant of MurmurHash3, a good 6 | non-cryptosafe hashing function developed by Austin Appleby. 7 | 8 | For simplicity, this variant does *NOT* accept buffer lengths 9 | that are not divisible by 8 bytes. The 32-bit version is otherwise 10 | similar to the original; the 64-bit one is a custom hack with 11 | mostly-unproven properties. 12 | 13 | Austin's original code is public domain. 14 | 15 | Other code written and maintained by Michal Zalewski 16 | 17 | Copyright 2016 Google Inc. All rights reserved. 18 | 19 | Licensed under the Apache License, Version 2.0 (the "License"); 20 | you may not use this file except in compliance with the License. 21 | You may obtain a copy of the License at: 22 | 23 | http://www.apache.org/licenses/LICENSE-2.0 24 | 25 | */ 26 | 27 | #ifndef _HAVE_HASH_H 28 | #define _HAVE_HASH_H 29 | 30 | #include "types.h" 31 | 32 | #ifdef __x86_64__ 33 | 34 | #define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) 35 | 36 | static inline u32 hash32(const void* key, u32 len, u32 seed) { 37 | 38 | const u64* data = (u64*)key; 39 | u64 h1 = seed ^ len; 40 | 41 | len >>= 3; 42 | 43 | while (len--) { 44 | 45 | u64 k1 = *data++; 46 | 47 | k1 *= 0x87c37b91114253d5ULL; 48 | k1 = ROL64(k1, 31); 49 | k1 *= 0x4cf5ad432745937fULL; 50 | 51 | h1 ^= k1; 52 | h1 = ROL64(h1, 27); 53 | h1 = h1 * 5 + 0x52dce729; 54 | 55 | } 56 | 57 | h1 ^= h1 >> 33; 58 | h1 *= 0xff51afd7ed558ccdULL; 59 | h1 ^= h1 >> 33; 60 | h1 *= 0xc4ceb9fe1a85ec53ULL; 61 | h1 ^= h1 >> 33; 62 | 63 | return h1; 64 | 65 | } 66 | 67 | #else 68 | 69 | #define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) 70 | 71 | static inline u32 hash32(const void* key, u32 len, u32 seed) { 72 | 73 | const u32* data = (u32*)key; 74 | u32 h1 = seed ^ len; 75 | 76 | len >>= 2; 77 | 78 | while (len--) { 79 | 80 | u32 k1 = *data++; 81 | 82 | k1 *= 0xcc9e2d51; 83 | k1 = ROL32(k1, 15); 84 | k1 *= 0x1b873593; 85 | 86 | h1 ^= k1; 87 | h1 = ROL32(h1, 13); 88 | h1 = h1 * 5 + 0xe6546b64; 89 | 90 | } 91 | 92 | h1 ^= h1 >> 16; 93 | h1 *= 0x85ebca6b; 94 | h1 ^= h1 >> 13; 95 | h1 *= 0xc2b2ae35; 96 | h1 ^= h1 >> 16; 97 | 98 | return h1; 99 | 100 | } 101 | 102 | #endif /* ^__x86_64__ */ 103 | 104 | #endif /* !_HAVE_HASH_H */ 105 | -------------------------------------------------------------------------------- /llvm_mode/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # american fuzzy lop - LLVM instrumentation 3 | # ----------------------------------------- 4 | # 5 | # Written by Laszlo Szekeres and 6 | # Michal Zalewski 7 | # 8 | # LLVM integration design comes from Laszlo Szekeres. 9 | # 10 | # Copyright 2015, 2016 Google Inc. All rights reserved. 11 | # 12 | # Licensed under the Apache License, Version 2.0 (the "License"); 13 | # you may not use this file except in compliance with the License. 14 | # You may obtain a copy of the License at: 15 | # 16 | # http://www.apache.org/licenses/LICENSE-2.0 17 | # 18 | 19 | PREFIX ?= /usr/local 20 | HELPER_PATH = $(PREFIX)/lib/afl 21 | BIN_PATH = $(PREFIX)/bin 22 | 23 | VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) 24 | 25 | LLVM_CONFIG ?= llvm-config 26 | 27 | CFLAGS ?= -O3 -funroll-loops 28 | CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ 29 | -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ 30 | -DVERSION=\"$(VERSION)\" 31 | ifdef AFL_TRACE_PC 32 | CFLAGS += -DUSE_TRACE_PC=1 33 | endif 34 | 35 | CXXFLAGS ?= -O3 -funroll-loops 36 | CXXFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ 37 | -DVERSION=\"$(VERSION)\" -Wno-variadic-macros 38 | 39 | CLANG_CFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fpic $(CXXFLAGS) 40 | CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS) 41 | 42 | # User teor2345 reports that this is required to make things work on MacOS X. 43 | 44 | ifeq "$(shell uname)" "Darwin" 45 | CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress 46 | endif 47 | 48 | # We were using llvm-config --bindir to get the location of clang, but 49 | # this seems to be busted on some distros, so using the one in $PATH is 50 | # probably better. 51 | 52 | ifeq "$(origin CC)" "default" 53 | CC = clang 54 | CXX = clang++ 55 | endif 56 | 57 | ifndef AFL_TRACE_PC 58 | PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o 59 | else 60 | PROGS = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o 61 | endif 62 | 63 | all: test_deps $(PROGS) test_build all_done 64 | 65 | test_deps: 66 | ifndef AFL_TRACE_PC 67 | @echo "[*] Checking for working 'llvm-config'..." 68 | @which $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 ) 69 | else 70 | @echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)." 71 | endif 72 | @echo "[*] Checking for working '$(CC)'..." 73 | @which $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 ) 74 | @echo "[*] Checking for '../afl-showmap'..." 75 | @test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 ) 76 | @echo "[+] All set and ready to build." 77 | 78 | ../afl-clang-fast: afl-clang-fast.c | test_deps 79 | $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 80 | ln -sf afl-clang-fast ../afl-clang-fast++ 81 | 82 | ../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps 83 | $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) 84 | 85 | ../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps 86 | $(CC) $(CFLAGS) -fPIC -c $< -o $@ 87 | 88 | ../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps 89 | @printf "[*] Building 32-bit variant of the runtime (-m32)... " 90 | @$(CC) $(CFLAGS) -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi 91 | 92 | ../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps 93 | @printf "[*] Building 64-bit variant of the runtime (-m64)... " 94 | @$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi 95 | 96 | test_build: $(PROGS) 97 | @echo "[*] Testing the CC wrapper and instrumentation output..." 98 | unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) 99 | echo 0 | ../afl-showmap -m none -q -o .test-instr0 ./test-instr 100 | echo 1 | ../afl-showmap -m none -q -o .test-instr1 ./test-instr 101 | @rm -f test-instr 102 | @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping to troubleshoot the issue."; echo; exit 1; fi 103 | @echo "[+] All right, the instrumentation seems to be working!" 104 | 105 | all_done: test_build 106 | @echo "[+] All done! You can now use '../afl-clang-fast' to compile programs." 107 | 108 | .NOTPARALLEL: clean 109 | 110 | clean: 111 | rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 112 | rm -f $(PROGS) ../afl-clang-fast++ 113 | -------------------------------------------------------------------------------- /llvm_mode/README.llvm: -------------------------------------------------------------------------------- 1 | ============================================ 2 | Fast LLVM-based instrumentation for afl-fuzz 3 | ============================================ 4 | 5 | (See ../docs/README for the general instruction manual.) 6 | 7 | 1) Introduction 8 | --------------- 9 | 10 | The code in this directory allows you to instrument programs for AFL using 11 | true compiler-level instrumentation, instead of the more crude 12 | assembly-level rewriting approach taken by afl-gcc and afl-clang. This has 13 | several interesting properties: 14 | 15 | - The compiler can make many optimizations that are hard to pull off when 16 | manually inserting assembly. As a result, some slow, CPU-bound programs will 17 | run up to around 2x faster. 18 | 19 | The gains are less pronounced for fast binaries, where the speed is limited 20 | chiefly by the cost of creating new processes. In such cases, the gain will 21 | probably stay within 10%. 22 | 23 | - The instrumentation is CPU-independent. At least in principle, you should 24 | be able to rely on it to fuzz programs on non-x86 architectures (after 25 | building afl-fuzz with AFL_NO_X86=1). 26 | 27 | - The instrumentation can cope a bit better with multi-threaded targets. 28 | 29 | - Because the feature relies on the internals of LLVM, it is clang-specific 30 | and will *not* work with GCC. 31 | 32 | Once this implementation is shown to be sufficiently robust and portable, it 33 | will probably replace afl-clang. For now, it can be built separately and 34 | co-exists with the original code. 35 | 36 | The idea and much of the implementation comes from Laszlo Szekeres. 37 | 38 | 2) How to use 39 | ------------- 40 | 41 | In order to leverage this mechanism, you need to have clang installed on your 42 | system. You should also make sure that the llvm-config tool is in your path 43 | (or pointed to via LLVM_CONFIG in the environment). 44 | 45 | Unfortunately, some systems that do have clang come without llvm-config or the 46 | LLVM development headers; one example of this is FreeBSD. FreeBSD users will 47 | also run into problems with clang being built statically and not being able to 48 | load modules (you'll see "Service unavailable" when loading afl-llvm-pass.so). 49 | 50 | To solve all your problems, you can grab pre-built binaries for your OS from: 51 | 52 | http://llvm.org/releases/download.html 53 | 54 | ...and then put the bin/ directory from the tarball at the beginning of your 55 | $PATH when compiling the feature and building packages later on. You don't need 56 | to be root for that. 57 | 58 | To build the instrumentation itself, type 'make'. This will generate binaries 59 | called afl-clang-fast and afl-clang-fast++ in the parent directory. Once this 60 | is done, you can instrument third-party code in a way similar to the standard 61 | operating mode of AFL, e.g.: 62 | 63 | CC=/path/to/afl/afl-clang-fast ./configure [...options...] 64 | make 65 | 66 | Be sure to also include CXX set to afl-clang-fast++ for C++ code. 67 | 68 | The tool honors roughly the same environmental variables as afl-gcc (see 69 | ../docs/env_variables.txt). This includes AFL_INST_RATIO, AFL_USE_ASAN, 70 | AFL_HARDEN, and AFL_DONT_OPTIMIZE. 71 | 72 | Note: if you want the LLVM helper to be installed on your system for all 73 | users, you need to build it before issuing 'make install' in the parent 74 | directory. 75 | 76 | 3) Gotchas, feedback, bugs 77 | -------------------------- 78 | 79 | This is an early-stage mechanism, so field reports are welcome. You can send bug 80 | reports to . 81 | 82 | 4) Bonus feature #1: deferred instrumentation 83 | --------------------------------------------- 84 | 85 | AFL tries to optimize performance by executing the targeted binary just once, 86 | stopping it just before main(), and then cloning this "master" process to get 87 | a steady supply of targets to fuzz. 88 | 89 | Although this approach eliminates much of the OS-, linker- and libc-level 90 | costs of executing the program, it does not always help with binaries that 91 | perform other time-consuming initialization steps - say, parsing a large config 92 | file before getting to the fuzzed data. 93 | 94 | In such cases, it's beneficial to initialize the forkserver a bit later, once 95 | most of the initialization work is already done, but before the binary attempts 96 | to read the fuzzed input and parse it; in some cases, this can offer a 10x+ 97 | performance gain. You can implement delayed initialization in LLVM mode in a 98 | fairly simple way. 99 | 100 | First, find a suitable location in the code where the delayed cloning can 101 | take place. This needs to be done with *extreme* care to avoid breaking the 102 | binary. In particular, the program will probably malfunction if you select 103 | a location after: 104 | 105 | - The creation of any vital threads or child processes - since the forkserver 106 | can't clone them easily. 107 | 108 | - The initialization of timers via setitimer() or equivalent calls. 109 | 110 | - The creation of temporary files, network sockets, offset-sensitive file 111 | descriptors, and similar shared-state resources - but only provided that 112 | their state meaningfully influences the behavior of the program later on. 113 | 114 | - Any access to the fuzzed input, including reading the metadata about its 115 | size. 116 | 117 | With the location selected, add this code in the appropriate spot: 118 | 119 | #ifdef __AFL_HAVE_MANUAL_CONTROL 120 | __AFL_INIT(); 121 | #endif 122 | 123 | You don't need the #ifdef guards, but including them ensures that the program 124 | will keep working normally when compiled with a tool other than afl-clang-fast. 125 | 126 | Finally, recompile the program with afl-clang-fast (afl-gcc or afl-clang will 127 | *not* generate a deferred-initialization binary) - and you should be all set! 128 | 129 | 5) Bonus feature #2: persistent mode 130 | ------------------------------------ 131 | 132 | Some libraries provide APIs that are stateless, or whose state can be reset in 133 | between processing different input files. When such a reset is performed, a 134 | single long-lived process can be reused to try out multiple test cases, 135 | eliminating the need for repeated fork() calls and the associated OS overhead. 136 | 137 | The basic structure of the program that does this would be: 138 | 139 | while (__AFL_LOOP(1000)) { 140 | 141 | /* Read input data. */ 142 | /* Call library code to be fuzzed. */ 143 | /* Reset state. */ 144 | 145 | } 146 | 147 | /* Exit normally */ 148 | 149 | The numerical value specified within the loop controls the maximum number 150 | of iterations before AFL will restart the process from scratch. This minimizes 151 | the impact of memory leaks and similar glitches; 1000 is a good starting point, 152 | and going much higher increases the likelihood of hiccups without giving you 153 | any real performance benefits. 154 | 155 | A more detailed template is shown in ../experimental/persistent_demo/. 156 | Similarly to the previous mode, the feature works only with afl-clang-fast; 157 | #ifdef guards can be used to suppress it when using other compilers. 158 | 159 | Note that as with the previous mode, the feature is easy to misuse; if you 160 | do not fully reset the critical state, you may end up with false positives or 161 | waste a whole lot of CPU power doing nothing useful at all. Be particularly 162 | wary of memory leaks and of the state of file descriptors. 163 | 164 | PS. Because there are task switches still involved, the mode isn't as fast as 165 | "pure" in-process fuzzing offered, say, by LLVM's LibFuzzer; but it is a lot 166 | faster than the normal fork() model, and compared to in-process fuzzing, 167 | should be a lot more robust. 168 | 169 | 6) Bonus feature #3: new 'trace-pc' mode 170 | ---------------------------------------- 171 | 172 | Recent versions of LLVM are shipping with a built-in execution tracing feature 173 | that is fairly usable for AFL, without the need to post-process the assembly 174 | or install any compiler plugins. See: 175 | 176 | http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs 177 | 178 | As of this writing, the feature is only available on SVN trunk, and is yet to 179 | make it to an official release of LLVM. Nevertheless, if you have a 180 | sufficiently recent compiler and want to give it a try, build afl-clang-fast 181 | this way: 182 | 183 | AFL_TRACE_PC=1 make clean all 184 | 185 | Since a form of 'trace-pc' is also supported in GCC, this mode may become a 186 | longer-term solution to all our needs. 187 | 188 | Note that this mode supports AFL_INST_RATIO at run time, not at compilation 189 | time. This is somewhat similar to the behavior of the QEMU mode. Because of 190 | the need to support it at run time, the mode is also a tad slower than the 191 | plugin-based approach. 192 | -------------------------------------------------------------------------------- /llvm_mode/afl-llvm-pass.so.cc: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - LLVM-mode instrumentation pass 3 | --------------------------------------------------- 4 | 5 | Written by Laszlo Szekeres and 6 | Michal Zalewski 7 | 8 | LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted 9 | from afl-as.c are Michal's fault. 10 | 11 | Copyright 2015, 2016 Google Inc. All rights reserved. 12 | 13 | Licensed under the Apache License, Version 2.0 (the "License"); 14 | you may not use this file except in compliance with the License. 15 | You may obtain a copy of the License at: 16 | 17 | http://www.apache.org/licenses/LICENSE-2.0 18 | 19 | This library is plugged into LLVM when invoking clang through afl-clang-fast. 20 | It tells the compiler to add code roughly equivalent to the bits discussed 21 | in ../afl-as.h. 22 | 23 | */ 24 | 25 | #include "../config.h" 26 | #include "../debug.h" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "llvm/ADT/Statistic.h" 33 | #include "llvm/IR/IRBuilder.h" 34 | #include "llvm/IR/LegacyPassManager.h" 35 | #include "llvm/IR/Module.h" 36 | #include "llvm/Support/Debug.h" 37 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 38 | 39 | using namespace llvm; 40 | 41 | namespace { 42 | 43 | class AFLCoverage : public ModulePass { 44 | 45 | public: 46 | 47 | static char ID; 48 | AFLCoverage() : ModulePass(ID) { } 49 | 50 | bool runOnModule(Module &M) override; 51 | 52 | const char *getPassName() const override { 53 | return "American Fuzzy Lop Instrumentation"; 54 | } 55 | 56 | }; 57 | 58 | } 59 | 60 | 61 | char AFLCoverage::ID = 0; 62 | 63 | 64 | bool AFLCoverage::runOnModule(Module &M) { 65 | 66 | LLVMContext &C = M.getContext(); 67 | 68 | IntegerType *Int8Ty = IntegerType::getInt8Ty(C); 69 | IntegerType *Int32Ty = IntegerType::getInt32Ty(C); 70 | 71 | /* Show a banner */ 72 | 73 | char be_quiet = 0; 74 | 75 | if (isatty(2) && !getenv("AFL_QUIET")) { 76 | 77 | SAYF(cCYA "afl-llvm-pass " cBRI VERSION cRST " by \n"); 78 | 79 | } else be_quiet = 1; 80 | 81 | /* Decide instrumentation ratio */ 82 | 83 | char* inst_ratio_str = getenv("AFL_INST_RATIO"); 84 | unsigned int inst_ratio = 100; 85 | 86 | if (inst_ratio_str) { 87 | 88 | if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio || 89 | inst_ratio > 100) 90 | FATAL("Bad value of AFL_INST_RATIO (must be between 1 and 100)"); 91 | 92 | } 93 | 94 | /* Get globals for the SHM region and the previous location. Note that 95 | __afl_prev_loc is thread-local. */ 96 | 97 | GlobalVariable *AFLMapPtr = 98 | new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, 99 | GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); 100 | 101 | GlobalVariable *AFLPrevLoc = new GlobalVariable( 102 | M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 103 | 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); 104 | 105 | /* Instrument all the things! */ 106 | 107 | int inst_blocks = 0; 108 | 109 | for (auto &F : M) 110 | for (auto &BB : F) { 111 | 112 | BasicBlock::iterator IP = BB.getFirstInsertionPt(); 113 | IRBuilder<> IRB(&(*IP)); 114 | 115 | if (R(100) >= inst_ratio) continue; 116 | 117 | /* Make up cur_loc */ 118 | 119 | unsigned int cur_loc = R(MAP_SIZE); 120 | 121 | ConstantInt *CurLoc = ConstantInt::get(Int32Ty, cur_loc); 122 | 123 | /* Load prev_loc */ 124 | 125 | LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc); 126 | PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); 127 | Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); 128 | 129 | /* Load SHM pointer */ 130 | 131 | LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); 132 | MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); 133 | Value *MapPtrIdx = 134 | IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted, CurLoc)); 135 | 136 | /* Update bitmap */ 137 | 138 | LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); 139 | Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); 140 | Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1)); 141 | IRB.CreateStore(Incr, MapPtrIdx) 142 | ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); 143 | 144 | /* Set prev_loc to cur_loc >> 1 */ 145 | 146 | StoreInst *Store = 147 | IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc); 148 | Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); 149 | 150 | inst_blocks++; 151 | 152 | } 153 | 154 | /* Say something nice. */ 155 | 156 | if (!be_quiet) { 157 | 158 | if (!inst_blocks) WARNF("No instrumentation targets found."); 159 | else OKF("Instrumented %u locations (%s mode, ratio %u%%).", 160 | inst_blocks, 161 | getenv("AFL_HARDEN") ? "hardened" : "non-hardened", 162 | inst_ratio); 163 | 164 | } 165 | 166 | return true; 167 | 168 | } 169 | 170 | 171 | static void registerAFLPass(const PassManagerBuilder &, 172 | legacy::PassManagerBase &PM) { 173 | 174 | PM.add(new AFLCoverage()); 175 | 176 | } 177 | 178 | 179 | static RegisterStandardPasses RegisterAFLPass( 180 | PassManagerBuilder::EP_OptimizerLast, registerAFLPass); 181 | 182 | static RegisterStandardPasses RegisterAFLPass0( 183 | PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); 184 | -------------------------------------------------------------------------------- /llvm_mode/afl-llvm-rt.o.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - LLVM instrumentation bootstrap 3 | --------------------------------------------------- 4 | 5 | Written by Laszlo Szekeres and 6 | Michal Zalewski 7 | 8 | LLVM integration design comes from Laszlo Szekeres. 9 | 10 | Copyright 2015, 2016 Google Inc. All rights reserved. 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at: 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | This code is the rewrite of afl-as.h's main_payload. 19 | 20 | */ 21 | 22 | #include "../config.h" 23 | #include "../types.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | /* Globals needed by the injected instrumentation. The __afl_area_initial region 38 | is used for instrumentation output before __afl_map_shm() has a chance to run. 39 | It will end up as .comm, so it shouldn't be too wasteful. */ 40 | 41 | u8 __afl_area_initial[MAP_SIZE]; 42 | u8* __afl_area_ptr = __afl_area_initial; 43 | 44 | __thread u32 __afl_prev_loc; 45 | 46 | 47 | /* Running in persistent mode? */ 48 | 49 | static u8 is_persistent; 50 | 51 | 52 | /* SHM setup. */ 53 | 54 | static void __afl_map_shm(void) { 55 | 56 | u8 *id_str = getenv(SHM_ENV_VAR); 57 | 58 | /* If we're running under AFL, attach to the appropriate region, replacing the 59 | early-stage __afl_area_initial region that is needed to allow some really 60 | hacky .init code to work correctly in projects such as OpenSSL. */ 61 | 62 | if (id_str) { 63 | 64 | u32 shm_id = atoi(id_str); 65 | 66 | __afl_area_ptr = shmat(shm_id, NULL, 0); 67 | 68 | /* Whooooops. */ 69 | 70 | if (__afl_area_ptr == (void *)-1) _exit(1); 71 | 72 | /* Write something into the bitmap so that even with low AFL_INST_RATIO, 73 | our parent doesn't give up on us. */ 74 | 75 | __afl_area_ptr[0] = 1; 76 | 77 | } 78 | 79 | } 80 | 81 | 82 | /* Fork server logic. */ 83 | 84 | static void __afl_start_forkserver(void) { 85 | 86 | static u8 tmp[4]; 87 | s32 child_pid; 88 | 89 | u8 child_stopped = 0; 90 | 91 | /* Phone home and tell the parent that we're OK. If parent isn't there, 92 | assume we're not running in forkserver mode and just execute program. */ 93 | 94 | if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; 95 | 96 | while (1) { 97 | 98 | u32 was_killed; 99 | int status; 100 | 101 | /* Wait for parent by reading from the pipe. Abort if read fails. */ 102 | 103 | if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); 104 | 105 | /* If we stopped the child in persistent mode, but there was a race 106 | condition and afl-fuzz already issued SIGKILL, write off the old 107 | process. */ 108 | 109 | if (child_stopped && was_killed) { 110 | child_stopped = 0; 111 | if (waitpid(child_pid, &status, 0) < 0) _exit(1); 112 | } 113 | 114 | if (!child_stopped) { 115 | 116 | /* Once woken up, create a clone of our process. */ 117 | 118 | child_pid = fork(); 119 | if (child_pid < 0) _exit(1); 120 | 121 | /* In child process: close fds, resume execution. */ 122 | 123 | if (!child_pid) { 124 | 125 | close(FORKSRV_FD); 126 | close(FORKSRV_FD + 1); 127 | return; 128 | 129 | } 130 | 131 | } else { 132 | 133 | /* Special handling for persistent mode: if the child is alive but 134 | currently stopped, simply restart it with SIGCONT. */ 135 | 136 | kill(child_pid, SIGCONT); 137 | child_stopped = 0; 138 | 139 | } 140 | 141 | /* In parent process: write PID to pipe, then wait for child. */ 142 | 143 | if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1); 144 | 145 | if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) 146 | _exit(1); 147 | 148 | /* In persistent mode, the child stops itself with SIGSTOP to indicate 149 | a successful run. In this case, we want to wake it up without forking 150 | again. */ 151 | 152 | if (WIFSTOPPED(status)) child_stopped = 1; 153 | 154 | /* Relay wait status to pipe, then loop back. */ 155 | 156 | if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1); 157 | 158 | } 159 | 160 | } 161 | 162 | 163 | /* A simplified persistent mode handler, used as explained in README.llvm. */ 164 | 165 | int __afl_persistent_loop(unsigned int max_cnt) { 166 | 167 | static u8 first_pass = 1; 168 | static u32 cycle_cnt; 169 | 170 | if (first_pass) { 171 | 172 | /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate. 173 | On subsequent calls, the parent will take care of that, but on the first 174 | iteration, it's our job to erase any trace of whatever happened 175 | before the loop. */ 176 | 177 | if (is_persistent) { 178 | memset(__afl_area_ptr, 0, MAP_SIZE); 179 | __afl_area_ptr[0] = 1; 180 | } 181 | 182 | cycle_cnt = max_cnt; 183 | first_pass = 0; 184 | return 1; 185 | 186 | } 187 | 188 | if (is_persistent) { 189 | 190 | if (--cycle_cnt) { 191 | 192 | raise(SIGSTOP); 193 | return 1; 194 | 195 | } else { 196 | 197 | /* When exiting __AFL_LOOP(), make sure that the subsequent code that 198 | follows the loop is not traced. We do that by pivoting back to the 199 | dummy output region. */ 200 | 201 | __afl_area_ptr = __afl_area_initial; 202 | 203 | } 204 | 205 | } 206 | 207 | return 0; 208 | 209 | } 210 | 211 | 212 | /* This one can be called from user code when deferred forkserver mode 213 | is enabled. */ 214 | 215 | void __afl_manual_init(void) { 216 | 217 | static u8 init_done; 218 | 219 | if (!init_done) { 220 | 221 | __afl_map_shm(); 222 | __afl_start_forkserver(); 223 | init_done = 1; 224 | 225 | } 226 | 227 | } 228 | 229 | 230 | static void __afl_trace_pc_init(void); 231 | 232 | 233 | /* Proper initialization routine. */ 234 | 235 | __attribute__((constructor(0))) void __afl_auto_init(void) { 236 | 237 | is_persistent = !!getenv(PERSIST_ENV_VAR); 238 | 239 | __afl_trace_pc_init(); 240 | 241 | if (getenv(DEFER_ENV_VAR)) return; 242 | 243 | __afl_manual_init(); 244 | 245 | } 246 | 247 | 248 | /* The following stuff deals with support for -fsanitize-coverage=bb,trace-pc. 249 | It remains non-operational in the traditional, plugin-backed LLVM mode. 250 | For more info about 'trace-pc', see README.llvm. 251 | 252 | The first function (__sanitizer_cov_trace_pc) is called back on every 253 | basic block. Since LLVM is not giving us any stable IDs for the blocks, 254 | we use 12 least significant bits of the return address (which should be 255 | stable even with ASLR; more significant bits may vary across runs). 256 | 257 | Since MAP_SIZE is usually larger than 12 bits, we "pad" it by combining 258 | left-shifted __afl_prev_loc. This gives us a theoretical maximum of 24 259 | bits, although instruction alignment likely reduces this somewhat. */ 260 | 261 | 262 | static u32 inst_ratio_scaled = MIN(4096, MAP_SIZE); 263 | 264 | void __sanitizer_cov_trace_pc(void) { 265 | 266 | u32 cur = ((u32)__builtin_return_address(0)) & MIN(4095, MAP_SIZE - 1); 267 | 268 | if (cur > inst_ratio_scaled) return; 269 | 270 | __afl_area_ptr[cur ^ __afl_prev_loc]++; 271 | 272 | #if MAP_SIZE_POW2 > 12 273 | __afl_prev_loc = cur << (MAP_SIZE_POW2 - 12); 274 | #else 275 | __afl_prev_loc = cur >> 1; 276 | #endif /* ^MAP_SIZE_POW2 > 12 */ 277 | 278 | } 279 | 280 | 281 | /* Init callback. Unfortunately, LLVM does not support compile-time 282 | instrumentation density scaling, at least not just yet. This means 283 | taking some performance hit by checking inst_ratio_scaled at runtime. */ 284 | 285 | static void __afl_trace_pc_init(void) { 286 | 287 | u8* x = getenv("AFL_INST_RATIO"); 288 | 289 | if (!x) return; 290 | 291 | inst_ratio_scaled = atoi(x); 292 | 293 | if (!inst_ratio_scaled || inst_ratio_scaled > 100) { 294 | fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); 295 | abort(); 296 | } 297 | 298 | inst_ratio_scaled = inst_ratio_scaled * MIN(4096, MAP_SIZE) / 100; 299 | 300 | } 301 | 302 | 303 | /* Work around a short-lived bug in LLVM with -fsanitize-coverage=trace-pc. */ 304 | 305 | void __sanitizer_cov_module_init(void) __attribute__((weak)); 306 | void __sanitizer_cov_module_init(void) { } 307 | 308 | -------------------------------------------------------------------------------- /qemu_mode/README.qemu: -------------------------------------------------------------------------------- 1 | ========================================================= 2 | High-performance binary-only instrumentation for afl-fuzz 3 | ========================================================= 4 | 5 | (See ../docs/README for the general instruction manual.) 6 | 7 | 1) Introduction 8 | --------------- 9 | 10 | The code in this directory allows you to build a standalone feature that 11 | leverages the QEMU "user emulation" mode and allows callers to obtain 12 | instrumentation output for black-box, closed-source binaries. This mechanism 13 | can be then used by afl-fuzz to stress-test targets that couldn't be built 14 | with afl-gcc. 15 | 16 | The usual performance cost is 2-5x, which is considerably better than 17 | seen so far in experiments with tools such as DynamoRIO and PIN. 18 | 19 | The idea and much of the implementation comes from Andrew Griffiths. 20 | 21 | 2) How to use 22 | ------------- 23 | 24 | The feature is implemented with a fairly simple patch to QEMU 2.3.0. The 25 | simplest way to build it is to run ./build_qemu_support.sh. The script will 26 | download, configure, and compile the QEMU binary for you. 27 | 28 | QEMU is a big project, so this will take a while, and you may have to 29 | resolve a couple of dependencies (most notably, you will definitely need 30 | libtool and glib2-devel). 31 | 32 | Once the binaries are compiled, you can leverage the QEMU tool by calling 33 | afl-fuzz and all the related utilities with -Q in the command line. 34 | 35 | Note that QEMU requires a generous memory limit to run; somewhere around 36 | 200 MB is a good starting point, but considerably more may be needed for 37 | more complex programs. The default -m limit will be automatically bumped up 38 | to 200 MB when specifying -Q to afl-fuzz; be careful when overriding this. 39 | 40 | In principle, if you set CPU_TARGET before calling ./build_qemu_support.sh, 41 | you should get a build capable of running non-native binaries (say, you 42 | can try CPU_TARGET=arm). This is also necessary for running 32-bit binaries 43 | on a 64-bit system (CPU_TARGET=i386). 44 | 45 | Note: if you want the QEMU helper to be installed on your system for all 46 | users, you need to build it before issuing 'make install' in the parent 47 | directory. 48 | 49 | 3) Notes on linking 50 | ------------------- 51 | 52 | The feature is supported only on Linux. Supporting BSD may amount to porting 53 | the changes made to linux-user/elfload.c and applying them to 54 | bsd-user/elfload.c, but I have not looked into this yet. 55 | 56 | The instrumentation follows only the .text section of the first ELF binary 57 | encountered in the linking process. It does not trace shared libraries. In 58 | practice, this means two things: 59 | 60 | - Any libraries you want to analyze *must* be linked statically into the 61 | executed ELF file (this will usually be the case for closed-source 62 | apps). 63 | 64 | - Standard C libraries and other stuff that is wasteful to instrument 65 | should be linked dynamically - otherwise, AFL will have no way to avoid 66 | peeking into them. 67 | 68 | Setting AFL_INST_LIBS=1 can be used to circumvent the .text detection logic 69 | and instrument every basic block encountered. 70 | 71 | 4) Benchmarking 72 | --------------- 73 | 74 | If you want to compare the performance of the QEMU instrumentation with that of 75 | afl-gcc compiled code against the same target, you need to build the 76 | non-instrumented binary with the same optimization flags that are normally 77 | injected by afl-gcc, and make sure that the bits to be tested are statically 78 | linked into the binary. A common way to do this would be: 79 | 80 | $ CFLAGS="-O3 -funroll-loops" ./configure --disable-shared 81 | $ make clean all 82 | 83 | Comparative measurements of execution speed or instrumentation coverage will be 84 | fairly meaningless if the optimization levels or instrumentation scopes don't 85 | match. 86 | 87 | 5) Gotchas, feedback, bugs 88 | -------------------------- 89 | 90 | If you need to fix up checksums or do other cleanup on mutated test cases, see 91 | experimental/post_library/ for a viable solution. 92 | 93 | Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate 94 | the "shadow VM" trick employed by the sanitizers and will probably just 95 | run out of memory. 96 | 97 | Compared to fully-fledged virtualization, the user emulation mode is *NOT* a 98 | security boundary. The binaries can freely interact with the host OS. If you 99 | somehow need to fuzz an untrusted binary, put everything in a sandbox first. 100 | 101 | Beyond that, this is an early-stage mechanism, so fields reports are welcome. 102 | You can send them to . 103 | 104 | 6) Alternatives: static rewriting 105 | --------------------------------- 106 | 107 | Statically rewriting binaries just once, instead of attempting to translate 108 | them at run time, can be a faster alternative. That said, static rewriting is 109 | fraught with peril, because it depends on being able to properly and fully model 110 | program control flow without actually executing each and every code path. 111 | 112 | If you want to experiment with this mode of operation, there is a module 113 | contributed by Aleksandar Nikolich: 114 | 115 | https://github.com/vrtadmin/moflow/tree/master/afl-dyninst 116 | https://groups.google.com/forum/#!topic/afl-users/HlSQdbOTlpg 117 | 118 | At this point, the author reports the possibility of hiccups with stripped 119 | binaries. That said, if we can get it to be comparably reliable to QEMU, we may 120 | decide to switch to this mode, but I had no time to play with it yet. 121 | -------------------------------------------------------------------------------- /qemu_mode/build_qemu_support.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # american fuzzy lop - QEMU build script 4 | # -------------------------------------- 5 | # 6 | # Written by Andrew Griffiths and 7 | # Michal Zalewski 8 | # 9 | # Copyright 2015, 2016 Google Inc. All rights reserved. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at: 14 | # 15 | # http://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # This script downloads, patches, and builds a version of QEMU with 18 | # minor tweaks to allow non-instrumented binaries to be run under 19 | # afl-fuzz. 20 | # 21 | # The modifications reside in patches/*. The standalone QEMU binary 22 | # will be written to ../afl-qemu-trace. 23 | # 24 | 25 | QEMU_URL="http://wiki.qemu-project.org/download/qemu-2.3.0.tar.bz2" 26 | QEMU_SHA384="7a0f0c900f7e2048463cc32ff3e904965ab466c8428847400a0f2dcfe458108a68012c4fddb2a7e7c822b4fd1a49639b" 27 | 28 | echo "=================================================" 29 | echo "AFL binary-only instrumentation QEMU build script" 30 | echo "=================================================" 31 | echo 32 | 33 | echo "[*] Performing basic sanity checks..." 34 | 35 | if [ ! "`uname -s`" = "Linux" ]; then 36 | 37 | echo "[-] Error: QEMU instrumentation is supported only on Linux." 38 | exit 1 39 | 40 | fi 41 | 42 | if [ ! -f "patches/afl-qemu-cpu-inl.h" -o ! -f "../config.h" ]; then 43 | 44 | echo "[-] Error: key files not found - wrong working directory?" 45 | exit 1 46 | 47 | fi 48 | 49 | if [ ! -f "../afl-showmap" ]; then 50 | 51 | echo "[-] Error: ../afl-showmap not found - compile AFL first!" 52 | exit 1 53 | 54 | fi 55 | 56 | 57 | for i in libtool wget python automake autoconf sha384sum bison iconv; do 58 | 59 | T=`which "$i" 2>/dev/null` 60 | 61 | if [ "$T" = "" ]; then 62 | 63 | echo "[-] Error: '$i' not found, please install first." 64 | exit 1 65 | 66 | fi 67 | 68 | done 69 | 70 | if [ ! -d "/usr/include/glib-2.0/" -a ! -d "/usr/local/include/glib-2.0/" ]; then 71 | 72 | echo "[-] Error: devel version of 'glib2' not found, please install first." 73 | exit 1 74 | 75 | fi 76 | 77 | if echo "$CC" | grep -qF /afl-; then 78 | 79 | echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool." 80 | exit 1 81 | 82 | fi 83 | 84 | echo "[+] All checks passed!" 85 | 86 | : ' 87 | ARCHIVE="`basename -- "$QEMU_URL"`" 88 | 89 | CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1` 90 | 91 | if [ ! "$CKSUM" = "$QEMU_SHA384" ]; then 92 | 93 | echo "[*] Downloading QEMU 2.3.0 from the web..." 94 | rm -f "$ARCHIVE" 95 | wget -O "$ARCHIVE" -- "$QEMU_URL" || exit 1 96 | 97 | CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1` 98 | 99 | fi 100 | 101 | if [ "$CKSUM" = "$QEMU_SHA384" ]; then 102 | 103 | echo "[+] Cryptographic signature on $ARCHIVE checks out." 104 | 105 | else 106 | 107 | echo "[-] Error: signature mismatch on $ARCHIVE (perhaps download error?)." 108 | exit 1 109 | 110 | fi 111 | 112 | echo "[*] Uncompressing archive (this will take a while)..." 113 | 114 | rm -rf "qemu-2.3.0" || exit 1 115 | tar xf "$ARCHIVE" || exit 1 116 | 117 | echo "[+] Unpacking successful." 118 | ' 119 | 120 | echo "[*] Applying patches..." 121 | 122 | patch -p0 /dev/null || exit 1 168 | 169 | gcc test-instr.c -o test-instr || exit 1 170 | 171 | unset AFL_INST_RATIO 172 | 173 | echo 0 | ./afl-showmap -m none -Q -q -o .test-instr0 ./test-instr || exit 1 174 | echo 1 | ./afl-showmap -m none -Q -q -o .test-instr1 ./test-instr || exit 1 175 | 176 | rm -f test-instr 177 | 178 | cmp -s .test-instr0 .test-instr1 179 | DR="$?" 180 | 181 | rm -f .test-instr0 .test-instr1 182 | 183 | if [ "$DR" = "0" ]; then 184 | 185 | echo "[-] Error: afl-qemu-trace instrumentation doesn't seem to work!" 186 | exit 1 187 | 188 | fi 189 | 190 | echo "[+] Instrumentation tests passed. " 191 | echo "[+] All set, you can now use the -Q mode in afl-fuzz!" 192 | 193 | else 194 | 195 | echo "[!] Note: can't test instrumentation when CPU_TARGET set." 196 | echo "[+] All set, you can now (hopefully) use the -Q mode in afl-fuzz!" 197 | 198 | fi 199 | 200 | exit 0 201 | -------------------------------------------------------------------------------- /qemu_mode/patches/afl-qemu-cpu-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - high-performance binary-only instrumentation 3 | ----------------------------------------------------------------- 4 | 5 | Written by Andrew Griffiths and 6 | Michal Zalewski 7 | 8 | Idea & design very much by Andrew Griffiths. 9 | 10 | Copyright 2015, 2016 Google Inc. All rights reserved. 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at: 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | This code is a shim patched into the separately-distributed source 19 | code of QEMU 2.2.0. It leverages the built-in QEMU tracing functionality 20 | to implement AFL-style instrumentation and to take care of the remaining 21 | parts of the AFL fork server logic. 22 | 23 | The resulting QEMU binary is essentially a standalone instrumentation 24 | tool; for an example of how to leverage it for other purposes, you can 25 | have a look at afl-showmap.c. 26 | 27 | */ 28 | 29 | #include 30 | #include "../../config.h" 31 | 32 | /*************************** 33 | * VARIOUS AUXILIARY STUFF * 34 | ***************************/ 35 | 36 | /* A snippet patched into tb_find_slow to inform the parent process that 37 | we have hit a new block that hasn't been translated yet, and to tell 38 | it to translate within its own context, too (this avoids translation 39 | overhead in the next forked-off copy). */ 40 | 41 | #define AFL_QEMU_CPU_SNIPPET1 do { \ 42 | afl_request_tsl(pc, cs_base, flags); \ 43 | } while (0) 44 | 45 | /* This snippet kicks in when the instruction pointer is positioned at 46 | _start and does the usual forkserver stuff, not very different from 47 | regular instrumentation injected via afl-as.h. */ 48 | 49 | #define AFL_QEMU_CPU_SNIPPET2 do { \ 50 | if(tb->pc == afl_entry_point) { \ 51 | afl_setup(); \ 52 | afl_forkserver(env); \ 53 | } \ 54 | afl_maybe_log(tb->pc); \ 55 | } while (0) 56 | 57 | /* We use one additional file descriptor to relay "needs translation" 58 | messages between the child and the fork server. */ 59 | 60 | #define TSL_FD (FORKSRV_FD - 1) 61 | 62 | /* This is equivalent to afl-as.h: */ 63 | 64 | static unsigned char *afl_area_ptr; 65 | 66 | /* Exported variables populated by the code patched into elfload.c: */ 67 | 68 | abi_ulong afl_entry_point, /* ELF entry point (_start) */ 69 | afl_start_code, /* .text start pointer */ 70 | afl_end_code; /* .text end pointer */ 71 | 72 | /* Set in the child process in forkserver mode: */ 73 | 74 | static unsigned char afl_fork_child; 75 | unsigned int afl_forksrv_pid; 76 | 77 | /* Instrumentation ratio: */ 78 | 79 | static unsigned int afl_inst_rms = MAP_SIZE; 80 | 81 | /* Function declarations. */ 82 | 83 | static void afl_setup(void); 84 | static void afl_forkserver(CPUArchState*); 85 | static inline void afl_maybe_log(abi_ulong); 86 | 87 | static void afl_wait_tsl(CPUArchState*, int); 88 | static void afl_request_tsl(target_ulong, target_ulong, uint64_t); 89 | 90 | static TranslationBlock *tb_find_slow(CPUArchState*, target_ulong, 91 | target_ulong, uint64_t); 92 | 93 | 94 | /* Data structure passed around by the translate handlers: */ 95 | 96 | struct afl_tsl { 97 | target_ulong pc; 98 | target_ulong cs_base; 99 | uint64_t flags; 100 | }; 101 | 102 | 103 | /************************* 104 | * ACTUAL IMPLEMENTATION * 105 | *************************/ 106 | 107 | 108 | /* Set up SHM region and initialize other stuff. */ 109 | 110 | static void afl_setup(void) { 111 | 112 | char *id_str = getenv(SHM_ENV_VAR), 113 | *inst_r = getenv("AFL_INST_RATIO"); 114 | 115 | int shm_id; 116 | 117 | if (inst_r) { 118 | 119 | unsigned int r; 120 | 121 | r = atoi(inst_r); 122 | 123 | if (r > 100) r = 100; 124 | if (!r) r = 1; 125 | 126 | afl_inst_rms = MAP_SIZE * r / 100; 127 | 128 | } 129 | 130 | if (id_str) { 131 | 132 | shm_id = atoi(id_str); 133 | afl_area_ptr = shmat(shm_id, NULL, 0); 134 | 135 | if (afl_area_ptr == (void*)-1) exit(1); 136 | 137 | /* With AFL_INST_RATIO set to a low value, we want to touch the bitmap 138 | so that the parent doesn't give up on us. */ 139 | 140 | if (inst_r) afl_area_ptr[0] = 1; 141 | 142 | 143 | } 144 | 145 | if (getenv("AFL_INST_LIBS")) { 146 | 147 | afl_start_code = 0; 148 | afl_end_code = (abi_ulong)-1; 149 | 150 | } 151 | 152 | } 153 | 154 | 155 | /* Fork server logic, invoked once we hit _start. */ 156 | 157 | static void afl_forkserver(CPUArchState *env) { 158 | 159 | static unsigned char tmp[4]; 160 | 161 | if (!afl_area_ptr) return; 162 | 163 | /* Tell the parent that we're alive. If the parent doesn't want 164 | to talk, assume that we're not running in forkserver mode. */ 165 | 166 | if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; 167 | 168 | afl_forksrv_pid = getpid(); 169 | 170 | /* All right, let's await orders... */ 171 | 172 | while (1) { 173 | 174 | pid_t child_pid; 175 | int status, t_fd[2]; 176 | 177 | /* Whoops, parent dead? */ 178 | 179 | if (read(FORKSRV_FD, tmp, 4) != 4) exit(2); 180 | 181 | /* Establish a channel with child to grab translation commands. We'll 182 | read from t_fd[0], child will write to TSL_FD. */ 183 | 184 | if (pipe(t_fd) || dup2(t_fd[1], TSL_FD) < 0) exit(3); 185 | close(t_fd[1]); 186 | 187 | child_pid = fork(); 188 | if (child_pid < 0) exit(4); 189 | 190 | if (!child_pid) { 191 | 192 | /* Child process. Close descriptors and run free. */ 193 | 194 | afl_fork_child = 1; 195 | close(FORKSRV_FD); 196 | close(FORKSRV_FD + 1); 197 | close(t_fd[0]); 198 | return; 199 | 200 | } 201 | 202 | /* Parent. */ 203 | 204 | close(TSL_FD); 205 | 206 | if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5); 207 | 208 | /* Collect translation requests until child dies and closes the pipe. */ 209 | 210 | afl_wait_tsl(env, t_fd[0]); 211 | 212 | /* Get and relay exit status to parent. */ 213 | 214 | if (waitpid(child_pid, &status, 0) < 0) exit(6); 215 | if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7); 216 | 217 | } 218 | 219 | } 220 | 221 | 222 | /* The equivalent of the tuple logging routine from afl-as.h. */ 223 | 224 | static inline void afl_maybe_log(abi_ulong cur_loc) { 225 | 226 | static __thread abi_ulong prev_loc; 227 | 228 | /* Optimize for cur_loc > afl_end_code, which is the most likely case on 229 | Linux systems. */ 230 | 231 | if (cur_loc > afl_end_code || cur_loc < afl_start_code || !afl_area_ptr) 232 | return; 233 | 234 | /* Looks like QEMU always maps to fixed locations, so ASAN is not a 235 | concern. Phew. But instruction addresses may be aligned. Let's mangle 236 | the value to get something quasi-uniform. */ 237 | 238 | cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); 239 | cur_loc &= MAP_SIZE - 1; 240 | 241 | /* Implement probabilistic instrumentation by looking at scrambled block 242 | address. This keeps the instrumented locations stable across runs. */ 243 | 244 | if (cur_loc >= afl_inst_rms) return; 245 | 246 | afl_area_ptr[cur_loc ^ prev_loc]++; 247 | prev_loc = cur_loc >> 1; 248 | 249 | } 250 | 251 | 252 | /* This code is invoked whenever QEMU decides that it doesn't have a 253 | translation of a particular block and needs to compute it. When this happens, 254 | we tell the parent to mirror the operation, so that the next fork() has a 255 | cached copy. */ 256 | 257 | static void afl_request_tsl(target_ulong pc, target_ulong cb, uint64_t flags) { 258 | 259 | struct afl_tsl t; 260 | 261 | if (!afl_fork_child) return; 262 | 263 | t.pc = pc; 264 | t.cs_base = cb; 265 | t.flags = flags; 266 | 267 | if (write(TSL_FD, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) 268 | return; 269 | 270 | } 271 | 272 | 273 | /* This is the other side of the same channel. Since timeouts are handled by 274 | afl-fuzz simply killing the child, we can just wait until the pipe breaks. */ 275 | 276 | static void afl_wait_tsl(CPUArchState *env, int fd) { 277 | 278 | struct afl_tsl t; 279 | 280 | while (1) { 281 | 282 | /* Broken pipe means it's time to return to the fork server routine. */ 283 | 284 | if (read(fd, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) 285 | break; 286 | 287 | tb_find_slow(env, t.pc, t.cs_base, t.flags); 288 | 289 | } 290 | 291 | close(fd); 292 | 293 | } 294 | 295 | -------------------------------------------------------------------------------- /qemu_mode/patches/cpu-exec.diff: -------------------------------------------------------------------------------- 1 | --- qemu-2.3.0/cpu-exec.c.orig 2014-12-09 14:45:40.000000000 +0000 2 | +++ qemu-2.3.0/cpu-exec.c 2015-02-20 22:07:02.966000000 +0000 3 | @@ -28,6 +28,8 @@ 4 | #include "exec/memory-internal.h" 5 | #include "qemu/rcu.h" 6 | 7 | +#include "../patches/afl-qemu-cpu-inl.h" 8 | + 9 | /* -icount align implementation. */ 10 | 11 | typedef struct SyncClocks { 12 | @@ -296,8 +298,11 @@ 13 | } 14 | not_found: 15 | /* if no translated code available, then translate it now */ 16 | + 17 | tb = tb_gen_code(cpu, pc, cs_base, flags, 0); 18 | 19 | + AFL_QEMU_CPU_SNIPPET1; 20 | + 21 | found: 22 | /* Move the last found TB to the head of the list */ 23 | if (likely(*ptb1)) { 24 | @@ -492,6 +497,9 @@ 25 | next_tb = 0; 26 | tcg_ctx.tb_ctx.tb_invalidated_flag = 0; 27 | } 28 | + 29 | + AFL_QEMU_CPU_SNIPPET2; 30 | + 31 | if (qemu_loglevel_mask(CPU_LOG_EXEC)) { 32 | qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n", 33 | tb->tc_ptr, tb->pc, lookup_symbol(tb->pc)); 34 | -------------------------------------------------------------------------------- /qemu_mode/patches/elfload.diff: -------------------------------------------------------------------------------- 1 | --- qemu-2.3.0/cgc-user/elfload.c.orig 2014-12-09 14:45:42.000000000 +0000 2 | +++ qemu-2.3.0/cgc-user/elfload.c 2015-01-28 02:51:23.719000000 +0000 3 | @@ -28,6 +28,8 @@ 4 | 5 | #define ELF_OSABI ELFOSABI_SYSV 6 | 7 | +extern abi_ulong afl_entry_point, afl_start_code, afl_end_code; 8 | + 9 | /* from personality.h */ 10 | 11 | /* 12 | @@ -1889,6 +1891,8 @@ 13 | info->brk = 0; 14 | info->elf_flags = ehdr->e_flags; 15 | 16 | + if (!afl_entry_point) afl_entry_point = info->entry; 17 | + 18 | for (i = 0; i < ehdr->e_phnum; i++) { 19 | struct elf_phdr *eppnt = phdr + i; 20 | if (eppnt->p_type == PT_LOAD) { 21 | @@ -1922,9 +1926,11 @@ 22 | if (elf_prot & PROT_EXEC) { 23 | if (vaddr < info->start_code) { 24 | info->start_code = vaddr; 25 | + if (!afl_start_code) afl_start_code = vaddr; 26 | } 27 | if (vaddr_ef > info->end_code) { 28 | info->end_code = vaddr_ef; 29 | + if (!afl_end_code) afl_end_code = vaddr_ef; 30 | } 31 | } 32 | if (elf_prot & PROT_WRITE) { 33 | -------------------------------------------------------------------------------- /qemu_mode/patches/syscall.diff: -------------------------------------------------------------------------------- 1 | --- qemu-2.3.0/cgc-user/syscall.c.orig 2014-12-09 14:45:43.000000000 +0000 2 | +++ qemu-2.3.0/cgc-user/syscall.c 2015-03-27 06:33:00.736000000 +0000 3 | @@ -227,7 +227,23 @@ 4 | _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) 5 | _syscall3(int,sys_syslog,int,type,char*,bufp,int,len) 6 | #if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) 7 | -_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) 8 | + 9 | +extern unsigned int afl_forksrv_pid; 10 | + 11 | +#ifdef __NR_sys_tgkill 12 | +static int sys_tgkill(int tgid, int pid, int sig) { 13 | + 14 | + /* Workaround for -lpthread to make abort() work properly, without 15 | + killing the forkserver due to a prematurely cached PID. */ 16 | + 17 | + if (afl_forksrv_pid && afl_forksrv_pid == pid && sig == SIGABRT) 18 | + pid = tgid = getpid(); 19 | + 20 | + return syscall(__NR_sys_tgkill, pid, tgid, sig); 21 | + 22 | +} 23 | +#endif 24 | + 25 | #endif 26 | #if defined(TARGET_NR_tkill) && defined(__NR_tkill) 27 | _syscall2(int,sys_tkill,int,tid,int,sig) 28 | -------------------------------------------------------------------------------- /qemu_mode/patches/translate-all.diff: -------------------------------------------------------------------------------- 1 | --- qemu-2.3.0/translate-all.c.orig 2014-12-09 14:45:46.000000000 +0000 2 | +++ qemu-2.3.0/translate-all.c 2015-01-28 22:37:42.383000000 +0000 3 | @@ -393,8 +393,13 @@ 4 | /* We can't use g_malloc because it may recurse into a locked mutex. */ 5 | # define ALLOC(P, SIZE) \ 6 | do { \ 7 | - P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ 8 | - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ 9 | + void* _tmp = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ 10 | + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ 11 | + if (_tmp == (void*)-1) { \ 12 | + qemu_log(">>> Out of memory for stack, bailing out. <<<\n"); \ 13 | + exit(1); \ 14 | + } \ 15 | + (P) = _tmp; \ 16 | } while (0) 17 | #else 18 | # define ALLOC(P, SIZE) \ 19 | -------------------------------------------------------------------------------- /test-instr.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - a trivial program to test the build 3 | -------------------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2014 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | int main(int argc, char** argv) { 22 | 23 | char buf[8]; 24 | 25 | if (read(0, buf, 8) < 1) { 26 | printf("Hum?\n"); 27 | exit(1); 28 | } 29 | 30 | if (buf[0] == '0') 31 | printf("Looks like a zero to me!\n"); 32 | else 33 | printf("A non-zero value? How quaint!\n"); 34 | 35 | exit(0); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /testcases/README.testcases: -------------------------------------------------------------------------------- 1 | =============================== 2 | AFL test cases and dictionaries 3 | =============================== 4 | 5 | (See ../docs/README for the general instruction manual.) 6 | 7 | 1) Starting test cases 8 | ---------------------- 9 | 10 | The archives/, images/, multimedia/, and others/ subdirectories contain small, 11 | standalone files that can be used to seed afl-fuzz when testing parsers for a 12 | variety of common data formats. 13 | 14 | There is probably not much to be said about these files, except that they were 15 | optimized for size and stripped of any non-essential fluff. Some directories 16 | contain several examples that exercise various features of the underlying format. 17 | For example, there is a PNG file with and without a color profile. 18 | 19 | Additional test cases are always welcome; the current "most wanted" list 20 | includes: 21 | 22 | - JBIG, 23 | - Ogg Vorbis, 24 | - Ogg Theora, 25 | - MP3, 26 | - AAC, 27 | - WebM, 28 | - Small JPEG with a color profile, 29 | - Small fonts. 30 | 31 | 2) Dictionaries 32 | --------------- 33 | 34 | The _extras/ subdirectory contains a set of dictionaries that can be used in 35 | conjunction with the -x option to allow the fuzzer to effortlessly explore the 36 | grammar of some of the more verbose data formats or languages. The basic 37 | principle behind the operation of fuzzer dictionaries is outlined in section 9 38 | of the "main" README for the project. 39 | 40 | Custom dictionaries can be added at will. They should consist of a 41 | reasonably-sized set of rudimentary syntax units that the fuzzer will then try 42 | to clobber together in various ways. Snippets between 2 and 16 bytes are usually 43 | the sweet spot. 44 | 45 | Custom dictionaries can be created in two ways: 46 | 47 | - By creating a new directory and placing each token in a separate file, in 48 | which case, there is no need to escape or otherwise format the data. 49 | 50 | - By creating a flat text file where tokens are listed one per line in the 51 | format of name="value". The alphanumeric name is ignored and can be omitted, 52 | although it is a convenient way to document the meaning of a particular 53 | token. The value must appear in quotes, with hex escaping (\xNN) applied to 54 | all non-printable, high-bit, or otherwise problematic characters (\\ and \" 55 | shorthands are recognized, too). 56 | 57 | The fuzzer auto-selects the appropriate mode depending on whether the -x 58 | parameter is a file or a directory. 59 | 60 | In the file mode, every name field can be optionally followed by @, e.g.: 61 | 62 | keyword_foo@1 = "foo" 63 | 64 | Such entries will be loaded only if the requested dictionary level is equal or 65 | higher than this number. The default level is zero; a higher value can be set 66 | by appending @ to the dictionary file name, like so: 67 | 68 | -x path/to/dictionary.dct@2 69 | 70 | Good examples of dictionaries can be found in _extras/xml.dict and 71 | _extras/png.dict. 72 | -------------------------------------------------------------------------------- /testcases/_extras/gif.dict: -------------------------------------------------------------------------------- 1 | # 2 | # AFL dictionary for GIF images 3 | # ----------------------------- 4 | # 5 | # Created by Michal Zalewski 6 | # 7 | 8 | header_87a="87a" 9 | header_89a="89a" 10 | header_gif="GIF" 11 | 12 | marker_2c="," 13 | marker_3b=";" 14 | 15 | section_2101="!\x01\x12" 16 | section_21f9="!\xf9\x04" 17 | section_21fe="!\xfe" 18 | section_21ff="!\xff\x11" 19 | -------------------------------------------------------------------------------- /testcases/_extras/html_tags.dict: -------------------------------------------------------------------------------- 1 | # 2 | # AFL dictionary for HTML parsers (tags only) 3 | # ------------------------------------------- 4 | # 5 | # A basic collection of HTML tags likely to matter to HTML parsers. Does *not* 6 | # include any attributes or attribute values. 7 | # 8 | # Created by Michal Zalewski 9 | # 10 | 11 | tag_a="" 12 | tag_abbr="" 13 | tag_acronym="" 14 | tag_address="
    " 15 | tag_annotation_xml="" 16 | tag_applet="" 17 | tag_area="" 18 | tag_article="
    " 19 | tag_aside="