mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-13 18:48:08 +00:00
add cull queue, -i subdir traversal
This commit is contained in:
220
GNUmakefile
220
GNUmakefile
@ -24,21 +24,22 @@ BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH = $(PREFIX)/share/doc/afl
|
||||
MISC_PATH = $(PREFIX)/share/afl
|
||||
MAN_PATH = $(PREFIX)/share/man/man8
|
||||
MAN_PATH = $(PREFIX)/man/man8
|
||||
|
||||
PROGNAME = afl
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
# PROGS intentionally omit afl-as, which gets installed elsewhere.
|
||||
|
||||
PROGS = afl-gcc afl-g++ afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
|
||||
ASAN_OPTIONS=detect_leaks=0
|
||||
|
||||
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=full
|
||||
else
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=thin
|
||||
else
|
||||
@ -46,7 +47,7 @@ ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
CFLAGS_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
@ -61,10 +62,7 @@ ifneq "$(shell uname)" "Darwin"
|
||||
endif
|
||||
endif
|
||||
# OS X does not like _FORTIFY_SOURCE=2
|
||||
# _FORTIFY_SOURCE=2 does not like -O0
|
||||
ifndef DEBUG
|
||||
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname)" "SunOS"
|
||||
@ -206,10 +204,7 @@ else
|
||||
endif
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
# _FORTIFY_SOURCE=2 does not like -O0
|
||||
ifndef DEBUG
|
||||
override CFLAGS += -D_FORTIFY_SOURCE=2
|
||||
endif
|
||||
LDFLAGS += -ldl -lrt
|
||||
endif
|
||||
|
||||
@ -223,11 +218,7 @@ ifneq "$(findstring NetBSD, $(shell uname))" ""
|
||||
LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
TEST_CC = afl-gcc
|
||||
else
|
||||
TEST_CC = afl-clang
|
||||
endif
|
||||
TEST_CC = afl-gcc
|
||||
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
|
||||
@ -277,28 +268,47 @@ ifdef TEST_MMAP
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
|
||||
.PHONY: all
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
|
||||
|
||||
man: afl-gcc all $(MANPAGES)
|
||||
.PHONY: llvm
|
||||
llvm:
|
||||
-$(MAKE) -f GNUmakefile.llvm
|
||||
@test -e afl-cc || { echo "[-] Compiling afl-cc failed. You seem not to have a working compiler." ; exit 1; }
|
||||
|
||||
.PHONY: gcc_plugin
|
||||
gcc_plugin:
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
|
||||
.PHONY: man
|
||||
man: $(MANPAGES)
|
||||
|
||||
.PHONY: test
|
||||
test: tests
|
||||
|
||||
.PHONY: tests
|
||||
tests: source-only
|
||||
@cd test ; ./test-all.sh
|
||||
@rm -f test/errors
|
||||
|
||||
.PHONY: performance-tests
|
||||
performance-tests: performance-test
|
||||
.PHONY: test-performance
|
||||
test-performance: performance-test
|
||||
|
||||
.PHONY: performance-test
|
||||
performance-test: source-only
|
||||
@cd test ; ./test-performance.sh
|
||||
|
||||
|
||||
# hint: make targets are also listed in the top level README.md
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "HELP --- the following make targets exist:"
|
||||
@echo "=========================================="
|
||||
@echo "all: just the main afl++ binaries"
|
||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap"
|
||||
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap"
|
||||
@echo "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap"
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@ -322,8 +332,8 @@ help:
|
||||
@echo "=========================================="
|
||||
@echo e.g.: make ASAN_BUILD=1
|
||||
|
||||
.PHONY: test_x86
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_x86:
|
||||
@echo "[*] Checking for the default compiler cc..."
|
||||
@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
|
||||
@ -332,148 +342,129 @@ test_x86:
|
||||
@echo "[*] Checking for the ability to compile x86 code..."
|
||||
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( 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 )
|
||||
@rm -f .test1
|
||||
|
||||
else
|
||||
|
||||
test_x86:
|
||||
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: test_shm
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: test_python
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
|
||||
test_python:
|
||||
@rm -f .test 2> /dev/null
|
||||
@echo "[+] $(PYTHON_VERSION) support seems to be working."
|
||||
|
||||
else
|
||||
|
||||
test_python:
|
||||
@echo "[-] You seem to need to install the package python3-dev, python2-dev or python-dev (and perhaps python[23]-apt), but it is optional so we continue"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: ready
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile."
|
||||
|
||||
afl-g++: afl-gcc
|
||||
|
||||
afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
|
||||
|
||||
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
ln -sf afl-as as
|
||||
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
@ln -sf afl-as as
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
|
||||
$(CC) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-common.c -o src/afl-common.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
|
||||
|
||||
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||
|
||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) $(CPPFLAGS) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
|
||||
.PHONY: document
|
||||
document: afl-fuzz-document
|
||||
|
||||
# document all mutations and only do one run (use with only one input file!)
|
||||
document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
|
||||
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) $(CPPFLAGS) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
afl-fuzz-document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
|
||||
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
|
||||
|
||||
unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
|
||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_maybe_alloc
|
||||
|
||||
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
|
||||
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_hash
|
||||
|
||||
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
|
||||
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_rand
|
||||
|
||||
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
|
||||
|
||||
unit_list: test/unittests/unit_list.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_list
|
||||
|
||||
test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
|
||||
|
||||
unit_preallocable: test/unittests/unit_preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_preallocable
|
||||
|
||||
.PHONY: unit_clean
|
||||
unit_clean:
|
||||
@rm -f ./test/unittests/unit_preallocable ./test/unittests/unit_list ./test/unittests/unit_maybe_alloc test/unittests/*.o
|
||||
|
||||
.PHONY: unit
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
|
||||
unit: unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
|
||||
|
||||
else
|
||||
|
||||
unit:
|
||||
@echo [-] unit tests are skipped on Darwin \(lacks GNU linker feature --wrap\)
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: code-format
|
||||
code-format:
|
||||
./.custom-format.py -i src/*.c
|
||||
./.custom-format.py -i include/*.h
|
||||
./.custom-format.py -i libdislocator/*.c
|
||||
./.custom-format.py -i libtokencap/*.c
|
||||
./.custom-format.py -i llvm_mode/*.c
|
||||
./.custom-format.py -i llvm_mode/*.h
|
||||
./.custom-format.py -i llvm_mode/*.cc
|
||||
./.custom-format.py -i gcc_plugin/*.c
|
||||
@#./.custom-format.py -i gcc_plugin/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i instrumentation/*.h
|
||||
./.custom-format.py -i instrumentation/*.cc
|
||||
./.custom-format.py -i instrumentation/*.c
|
||||
./.custom-format.py -i custom_mutators/*/*.c
|
||||
@#./.custom-format.py -i custom_mutators/*/*.h # destroys input.h :-(
|
||||
./.custom-format.py -i examples/*/*.c
|
||||
@ -489,38 +480,40 @@ code-format:
|
||||
./.custom-format.py -i *.c
|
||||
|
||||
|
||||
.PHONY: test_build
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
test_build: afl-cc afl-as afl-showmap
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_AS_FORCE_INSTRUMENT=1 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
|
||||
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
@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 post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
else
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
test_build: afl-cc afl-as afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all_done
|
||||
all_done: test_build
|
||||
@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
|
||||
@test -e afl-cc && echo "[+] Main compiler 'afl-cc' successfully built!" || { echo "[-] Main compiler 'afl-cc' failed to built, set up a working build environment first!" ; exit 1 ; }
|
||||
@test -e cmplog-instructions-pass.so && echo "[+] LLVM mode for 'afl-cc' successfully built!" || echo "[-] LLVM mode for 'afl-cc' failed to built, likely you either have not llvm installed or you have not set LLVM_CONFIG pointing to e.g. llvm-config-11. See instrumenation/README.llvm.md how to do this. Highly recommended!"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to built, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to built, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@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
|
||||
@! 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.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
.NOTPARALLEL: clean all
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-*
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
-$(MAKE) -f GNUmakefile.llvm clean
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C examples/afl_network_proxy clean
|
||||
@ -530,20 +523,22 @@ clean:
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
rm -rf qemu_mode/qemu-3.1.1
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||
test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||
else
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
endif
|
||||
|
||||
.PHONY: deepclean
|
||||
deepclean: clean
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
git reset --hard >/dev/null 2>&1 || true
|
||||
|
||||
.PHONY: distrib
|
||||
distrib: all
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
-$(MAKE) -f GNUmakefile.llvm
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/afl_network_proxy
|
||||
@ -552,6 +547,7 @@ distrib: all
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
|
||||
.PHONY: binary-only
|
||||
binary-only: all
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
@ -561,9 +557,10 @@ binary-only: all
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
|
||||
.PHONY: source-only
|
||||
source-only: all
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
-$(MAKE) -f GNUmakefile.llvm
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
@#$(MAKE) -C examples/afl_network_proxy
|
||||
@ -573,8 +570,7 @@ source-only: all
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@echo .SH NAME >> $@
|
||||
@printf "%s" ".B $* \- " >> $@
|
||||
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> $@
|
||||
@echo .B $* >> $@
|
||||
@echo >> $@
|
||||
@echo .SH SYNOPSIS >> $@
|
||||
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@
|
||||
@ -590,30 +586,28 @@ source-only: all
|
||||
@echo .SH LICENSE >> $@
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
.PHONY: install
|
||||
install: all $(MANPAGES)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi
|
||||
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
|
||||
if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
|
||||
if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
|
||||
if [ -f libAFLDriver.a ]; then install -m 644 libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libAFLQemuDriver.a ]; then install -m 644 libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
|
||||
|
||||
mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
@if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
|
||||
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
|
||||
@if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
|
||||
@if [ -f examples/aflpp_driver/libAFLDriver.a ]; then install -m 644 examples/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f examples/aflpp_driver/libAFLQemuDriver.a ]; then install -m 644 examples/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
-$(MAKE) -f GNUmakefile.llvm install
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin install
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
|
@ -419,17 +419,14 @@ document:
|
||||
|
||||
./afl-compiler-rt.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||
$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
|
||||
ln -sf ./afl-compiler-rt.o ./afl-llvm-rt.o
|
||||
|
||||
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
@test -e ./afl-compiler-rt-32.o && ln -sf ./afl-compiler-rt-32.o ./afl-llvm-rt-32.o
|
||||
|
||||
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
||||
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
@test -e ./afl-compiler-rt-64.o && ln -sf ./afl-compiler-rt-64.o ./afl-llvm-rt-64.o
|
||||
|
||||
.PHONY: test_build
|
||||
test_build: $(PROGS)
|
||||
@ -454,8 +451,8 @@ install: all
|
||||
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-lto-instrumentation.so ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o; fi
|
||||
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o; fi
|
||||
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi
|
||||
@if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi
|
||||
|
177
README.md
177
README.md
@ -4,9 +4,9 @@
|
||||
|
||||

|
||||
|
||||
Release Version: [2.68c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release Version: [2.67c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
Github Version: 3.00a
|
||||
Github Version: 2.67d
|
||||
|
||||
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
||||
@ -22,6 +22,26 @@
|
||||
afl++ is a superior fork to Google's afl - more speed, more and better
|
||||
mutations, more and better instrumentation, custom module support, etc.
|
||||
|
||||
## Major changes in afl++ 3.0
|
||||
|
||||
With afl++ 3.0 we introduced changes that break some previous afl and afl++
|
||||
behaviours:
|
||||
|
||||
* There are no llvm_mode and gcc_plugin subdirectories anymore and there is
|
||||
only one compiler: afl-cc. All previous compilers now symlink to this one
|
||||
compiler. All instrumentation source code is now in the `instrumentation/`
|
||||
folder.
|
||||
* qemu_mode got upgraded to QEMU 5.1, but to be able to build this a current
|
||||
ninja build tool version and python3 setuptools are required.
|
||||
qemu_mode also got new options like snapshotting, instrumenting specific
|
||||
shared libraries, etc. and QEMU 5.1 supports more CPU targets so this is
|
||||
worth it.
|
||||
* When instrumenting targets, afl-cc will not supersede optimizations. This
|
||||
allows to fuzz targets as same as they are built for debug or release.
|
||||
* afl-fuzz' `-i` option now descends into subdirectories.
|
||||
* afl-fuzz will skip over empty dictionaries and too large test cases instead
|
||||
of failing.
|
||||
|
||||
## Contents
|
||||
|
||||
1. [Features](#important-features-of-afl)
|
||||
@ -39,7 +59,7 @@
|
||||
with laf-intel and redqueen, unicorn mode, gcc plugin, full *BSD, Solaris and
|
||||
Android support and much, much, much more.
|
||||
|
||||
| Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode |
|
||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | qemu_mode | unicorn_mode |
|
||||
| -------------------------|:-------:|:---------:|:----------:|:----------------:|:------------:|
|
||||
| NeverZero | x86[_64]| x(1) | (2) | x | x |
|
||||
| Persistent Mode | | x | x | x86[_64]/arm[64] | x |
|
||||
@ -47,9 +67,8 @@
|
||||
| CmpLog | | x | | x86[_64]/arm[64] | |
|
||||
| Selective Instrumentation| | x | x | (x)(3) | |
|
||||
| Non-Colliding Coverage | | x(4) | | (x)(5) | |
|
||||
| InsTrim | | x | | | |
|
||||
| Ngram prev_loc Coverage | | x(6) | | | |
|
||||
| Context Coverage | | x | | | |
|
||||
| Context Coverage | | x(6) | | | |
|
||||
| Auto Dictionary | | x(7) | | | |
|
||||
| Snapshot LKM Support | | x | | (x)(5) | |
|
||||
|
||||
@ -59,11 +78,11 @@
|
||||
4. with pcguard mode and LTO mode for LLVM >= 11
|
||||
5. upcoming, development in the branch
|
||||
6. not compatible with LTO instrumentation and needs at least LLVM >= 4.1
|
||||
7. only in LTO mode with LLVM >= 11
|
||||
7. automatic in LTO mode with LLVM >= 11, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
|
||||
|
||||
Among others, the following features and patches have been integrated:
|
||||
|
||||
* NeverZero patch for afl-gcc, llvm_mode, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
|
||||
* NeverZero patch for afl-gcc, instrumentation, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
|
||||
* Persistent mode, deferred forkserver and in-memory fuzzing for qemu_mode
|
||||
* Unicorn mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
|
||||
* The new CmpLog instrumentation for LLVM and QEMU inspired by [Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
|
||||
@ -71,10 +90,9 @@
|
||||
* AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||
* The MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
|
||||
* LLVM mode Ngram coverage by Adrian Herrera [https://github.com/adrianherrera/afl-ngram-pass](https://github.com/adrianherrera/afl-ngram-pass)
|
||||
* InsTrim, a CFG llvm_mode instrumentation implementation: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim)
|
||||
* C. Holler's afl-fuzz Python mutator module: [https://github.com/choller/afl](https://github.com/choller/afl)
|
||||
* Custom mutator by a library (instead of Python) by kyakdan
|
||||
* LAF-Intel/CompCov support for llvm_mode, qemu_mode and unicorn_mode (with enhanced capabilities)
|
||||
* LAF-Intel/CompCov support for instrumentation, qemu_mode and unicorn_mode (with enhanced capabilities)
|
||||
* Radamsa and honggfuzz mutators (as custom mutators).
|
||||
* QBDI mode to fuzz android native libraries via Quarkslab's [QBDI](https://github.com/QBDI/QBDI) framework
|
||||
* Frida and ptrace mode to fuzz binary-only libraries, etc.
|
||||
@ -88,7 +106,7 @@
|
||||
send a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
|
||||
See [docs/QuickStartGuide.md](docs/QuickStartGuide.md) if you don't have time to
|
||||
read this file.
|
||||
read this file - however this is not recommended!
|
||||
|
||||
## Branches
|
||||
|
||||
@ -105,13 +123,14 @@
|
||||
|
||||
## Help wanted
|
||||
|
||||
We are happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)! :-)
|
||||
We were happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)
|
||||
and we will try to participate again in 2021!
|
||||
|
||||
We have several ideas we would like to see in AFL++ to make it even better.
|
||||
However, we already work on so many things that we do not have the time for
|
||||
all the big ideas.
|
||||
|
||||
This can be your way to support and contribute to AFL++ - extend it to
|
||||
This can be your way to support and contribute to AFL++ - extend it to do
|
||||
something cool.
|
||||
|
||||
We have an idea list in [docs/ideas.md](docs/ideas.md).
|
||||
@ -132,7 +151,7 @@ This image is automatically generated when a push to the stable repo happens.
|
||||
You will find your target source code in /src in the container.
|
||||
|
||||
If you want to build afl++ yourself you have many options.
|
||||
The easiest is to build and install everything:
|
||||
The easiest choice is to build and install everything:
|
||||
|
||||
```shell
|
||||
sudo apt install build-essential libtool-bin python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools llvm
|
||||
@ -142,9 +161,9 @@ sudo make install
|
||||
It is recommended to install the newest available gcc, clang and llvm-dev
|
||||
possible in your distribution!
|
||||
|
||||
Note that "make distrib" also builds llvm_mode, qemu_mode, unicorn_mode and
|
||||
Note that "make distrib" also builds instrumentation, qemu_mode, unicorn_mode and
|
||||
more. If you just want plain afl++ then do "make all", however compiling and
|
||||
using at least llvm_mode is highly recommended for much better results -
|
||||
using at least instrumentation is highly recommended for much better results -
|
||||
hence in this case
|
||||
|
||||
```shell
|
||||
@ -156,7 +175,7 @@ These build targets exist:
|
||||
|
||||
* all: just the main afl++ binaries
|
||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap
|
||||
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap
|
||||
* source-only: everything for source code fuzzing: instrumentation, libdislocator, libtokencap
|
||||
* distrib: everything (for both binary-only and source code fuzzing)
|
||||
* man: creates simple man pages from the help option of the programs
|
||||
* install: installs everything you have compiled with the build options above
|
||||
@ -212,18 +231,19 @@ If you have a binary-only target please skip to [#Instrumenting binary-only apps
|
||||
|
||||
Fuzzing source code is a three-step process.
|
||||
|
||||
1. compile the target with a special compiler that prepares the target to be
|
||||
1. Compile the target with a special compiler that prepares the target to be
|
||||
fuzzed efficiently. This step is called "instrumenting a target".
|
||||
2. Prepare the fuzzing by selecting and optimizing the input corpus for the
|
||||
target.
|
||||
3. perform the fuzzing of the target by randomly mutating input and assessing
|
||||
3. Perform the fuzzing of the target by randomly mutating input and assessing
|
||||
if a generated input was processed in a new path in the target binary.
|
||||
|
||||
### 1. Instrumenting that target
|
||||
|
||||
#### a) Selecting the best afl++ compiler for instrumenting the target
|
||||
|
||||
afl++ comes with different compilers and instrumentation options.
|
||||
afl++ comes with a central compiler `afl-cc` that incorporates various different
|
||||
kinds of compiler targets and and instrumentation options.
|
||||
The following evaluation flow will help you to select the best possible.
|
||||
|
||||
It is highly recommended to have the newest llvm version possible installed,
|
||||
@ -231,49 +251,62 @@ anything below 9 is not recommended.
|
||||
|
||||
```
|
||||
+--------------------------------+
|
||||
| clang/clang++ 11+ is available | --> use afl-clang-lto and afl-clang-lto++
|
||||
+--------------------------------+ see [llvm/README.lto.md](llvm/README.lto.md)
|
||||
| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
|
||||
+--------------------------------+ see [instrumentation/README.lto.md](instrumentation/README.lto.md)
|
||||
|
|
||||
| if not, or if the target fails with afl-clang-lto/++
|
||||
| if not, or if the target fails with LTO afl-clang-lto/++
|
||||
|
|
||||
v
|
||||
+---------------------------------+
|
||||
| clang/clang++ 3.3+ is available | --> use afl-clang-fast and afl-clang-fast++
|
||||
+---------------------------------+ see [llvm/README.md](llvm/README.md)
|
||||
| clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
|
||||
+---------------------------------+ see [instrumentation/README.md](instrumentation/README.md)
|
||||
|
|
||||
| if not, or if the target fails with afl-clang-fast/++
|
||||
| if not, or if the target fails with LLVM afl-clang-fast/++
|
||||
|
|
||||
v
|
||||
+--------------------------------+
|
||||
| if you want to instrument only | -> use afl-gcc-fast and afl-gcc-fast++
|
||||
| parts of the target | see [gcc_plugin/README.md](gcc_plugin/README.md) and
|
||||
+--------------------------------+ [gcc_plugin/README.instrument_list.md](gcc_plugin/README.instrument_list.md)
|
||||
| if you want to instrument only | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast)
|
||||
| parts of the target | see [instrumentation/README.gcc_plugin.md](instrumentation/README.gcc_plugin.md) and
|
||||
+--------------------------------+ [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
|
||||
|
|
||||
| if not, or if you do not have a gcc with plugin support
|
||||
|
|
||||
v
|
||||
use afl-gcc and afl-g++ (or afl-clang and afl-clang++)
|
||||
use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)
|
||||
```
|
||||
|
||||
Clickable README links for the chosen compiler:
|
||||
|
||||
* [afl-clang-lto](llvm/README.lto.md)
|
||||
* [afl-clang-fast](llvm/README.md)
|
||||
* [afl-gcc-fast](gcc_plugin/README.md)
|
||||
* afl-gcc has no README as it has no features
|
||||
* [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
|
||||
* [LLVM mode - afl-clang-fast](instrumentation/README.md)
|
||||
* [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
|
||||
* GCC mode (afl-gcc) has no README as it has no own features
|
||||
|
||||
You can select the mode for the afl-cc compiler by:
|
||||
1. passing --afl-MODE command line options to the compiler via CFLAGS/CXXFLAGS/CPPFLAGS
|
||||
2. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||
afl-gcc-fast, afl-g++-fast
|
||||
3. using the environment variable AFL_CC_COMPILER with MODE
|
||||
|
||||
MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN
|
||||
(afl-g*-fast) or GCC (afl-gcc/afl-g++).
|
||||
|
||||
Because no afl specific command-line options are accepted (beside the
|
||||
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
||||
variables, which can be listed with `afl-cc -hh` or by reading [docs/env_variables.md](docs/env_variables.md).
|
||||
|
||||
#### b) Selecting instrumentation options
|
||||
|
||||
The following options are available when you instrument with afl-clang-fast or
|
||||
afl-clang-lto:
|
||||
The following options are available when you instrument with LTO mode (afl-clang-fast/afl-clang-lto):
|
||||
|
||||
* Splitting integer, string, float and switch comparisons so afl++ can easier
|
||||
solve these. This is an important option if you do not have a very good
|
||||
and large input corpus. This technique is called laf-intel or COMPCOV.
|
||||
To use this set the following environment variable before compiling the
|
||||
target: `export AFL_LLVM_LAF_ALL=1`
|
||||
You can read more about this in [llvm/README.laf-intel.md](llvm/README.laf-intel.md)
|
||||
* A different technique (and usually a better than laf-intel) is to
|
||||
You can read more about this in [instrumentation/README.laf-intel.md](instrumentation/README.laf-intel.md)
|
||||
* A different technique (and usually a better one than laf-intel) is to
|
||||
instrument the target so that any compare values in the target are sent to
|
||||
afl++ which then tries to put these values into the fuzzing data at different
|
||||
locations. This technique is very fast and good - if the target does not
|
||||
@ -282,12 +315,13 @@ afl-clang-lto:
|
||||
If you want to use this technique, then you have to compile the target
|
||||
twice, once specifically with/for this mode, and pass this binary to afl-fuzz
|
||||
via the `-c` parameter.
|
||||
Not that you can compile also just a cmplog binary and use that for both
|
||||
however there will a performance penality.
|
||||
You can read more about this in [llvm_mode/README.cmplog.md](llvm_mode/README.cmplog.md)
|
||||
Note that you can compile also just a cmplog binary and use that for both
|
||||
however there will be a performance penality.
|
||||
You can read more about this in [instrumentation/README.cmplog.md](instrumentation/README.cmplog.md)
|
||||
|
||||
If you use afl-clang-fast, afl-clang-lto or afl-gcc-fast you have the option to
|
||||
selectively only instrument parts of the target that you are interested in:
|
||||
If you use LTO, LLVM or GCC_PLUGIN mode (afl-clang-fast/afl-clang-lto/afl-gcc-fast)
|
||||
you have the option to selectively only instrument parts of the target that you
|
||||
are interested in:
|
||||
|
||||
* To instrument only those parts of the target that you are interested in
|
||||
create a file with all the filenames of the source code that should be
|
||||
@ -299,29 +333,29 @@ selectively only instrument parts of the target that you are interested in:
|
||||
`export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per
|
||||
default to instrument unless noted (DENYLIST) or not perform instrumentation
|
||||
unless requested (ALLOWLIST).
|
||||
**NOTE:** In optimization functions might be inlined and then not match!
|
||||
see [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md)
|
||||
**NOTE:** During optimization functions might be inlined and then would not match!
|
||||
See [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
|
||||
For afl-clang-fast > 6.0 or if PCGUARD instrumentation is used then use the
|
||||
llvm sancov allow-list feature: [http://clang.llvm.org/docs/SanitizerCoverage.html](http://clang.llvm.org/docs/SanitizerCoverage.html)
|
||||
The llvm sancov format works with the allowlist/denylist feature of afl++
|
||||
however afl++ is more flexible in the format.
|
||||
however afl++'s format is more flexible.
|
||||
|
||||
There are many more options and modes available however these are most of the
|
||||
time less effective. See:
|
||||
* [llvm_mode/README.ctx.md](llvm_mode/README.ctx.md)
|
||||
* [llvm_mode/README.ngram.md](llvm_mode/README.ngram.md)
|
||||
* [llvm_mode/README.instrim.md](llvm_mode/README.instrim.md)
|
||||
* [instrumentation/README.ctx.md](instrumentation/README.ctx.md)
|
||||
* [instrumentation/README.ngram.md](instrumentation/README.ngram.md)
|
||||
* [instrumentation/README.instrim.md](instrumentation/README.instrim.md)
|
||||
|
||||
afl++ employs never zero counting in its bitmap. You can read more about this
|
||||
afl++ performs "never zero" counting in its bitmap. You can read more about this
|
||||
here:
|
||||
* [llvm_mode/README.neverzero.md](llvm_mode/README.neverzero.md)
|
||||
* [instrumentation/README.neverzero.md](instrumentation/README.neverzero.md)
|
||||
|
||||
#### c) Modify the target
|
||||
|
||||
If the target has features that make fuzzing more difficult, e.g.
|
||||
checksums, HMAC, etc. then modify the source code so that this is
|
||||
removed.
|
||||
This can even be done for productional source code be eliminating
|
||||
This can even be done for operational source code by eliminating
|
||||
these checks within this specific defines:
|
||||
|
||||
```
|
||||
@ -332,13 +366,15 @@ these checks within this specific defines:
|
||||
#endif
|
||||
```
|
||||
|
||||
All afl++ compilers will set this preprocessor definition automatically.
|
||||
|
||||
#### d) Instrument the target
|
||||
|
||||
In this step the target source code is compiled so that it can be fuzzed.
|
||||
|
||||
Basically you have to tell the target build system that the selected afl++
|
||||
compiler is used. Also - if possible - you should always configure the
|
||||
build system that the target is compiled statically and not dynamically.
|
||||
build system such that the target is compiled statically and not dynamically.
|
||||
How to do this is described below.
|
||||
|
||||
Then build the target. (Usually with `make`)
|
||||
@ -349,20 +385,22 @@ For `configure` build systems this is usually done by:
|
||||
`CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared`
|
||||
|
||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as it is
|
||||
described in [llvm/README.lto.md](llvm/README.lto.md)
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
||||
described in [instrumentation/README.lto.md](instrumentation/README.lto.md).
|
||||
|
||||
##### cmake
|
||||
|
||||
For `configure` build systems this is usually done by:
|
||||
`mkdir build; cd build; CC=afl-clang-fast CXX=afl-clang-fast++ cmake ..`
|
||||
|
||||
Some cmake scripts require something like `-DCMAKE_CC=... -DCMAKE_CXX=...`
|
||||
or `-DCMAKE_C_COMPILER=... DCMAKE_CPP_COMPILER=...` instead.
|
||||
For `cmake` build systems this is usually done by:
|
||||
`mkdir build; cmake -DCMAKE_C_COMPILERC=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
|
||||
|
||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as it is
|
||||
described in [llvm/README.lto.md](llvm/README.lto.md)
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
||||
described in [instrumentation/README.lto.md](instrumentation/README.lto.md).
|
||||
|
||||
##### meson
|
||||
|
||||
For meson you have to set the afl++ compiler with the very first command!
|
||||
`CC=afl-cc CXX=afl-c++ meson`
|
||||
|
||||
##### other build systems or if configure/cmake didn't work
|
||||
|
||||
@ -370,7 +408,7 @@ Sometimes cmake and configure do not pick up the afl++ compiler, or the
|
||||
ranlib/ar that is needed - because this was just not foreseen by the developer
|
||||
of the target. Or they have non-standard options. Figure out if there is a
|
||||
non-standard way to set this, otherwise set up the build normally and edit the
|
||||
generated build environment afterwards manually to point to the right compiler
|
||||
generated build environment afterwards manually to point it to the right compiler
|
||||
(and/or ranlib and ar).
|
||||
|
||||
#### d) Better instrumentation
|
||||
@ -383,12 +421,12 @@ This requires the usage of afl-clang-lto or afl-clang-fast.
|
||||
This is the so-called `persistent mode`, which is much, much faster but
|
||||
requires that you code a source file that is specifically calling the target
|
||||
functions that you want to fuzz, plus a few specific afl++ functions around
|
||||
it. See [llvm_mode/README.persistent_mode.md](llvm_mode/README.persistent_mode.md) for details.
|
||||
it. See [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md) for details.
|
||||
|
||||
Basically if you do not fuzz a target in persistent mode then you are just
|
||||
doing it for a hobby and not professionally :-)
|
||||
|
||||
### 2. Preparing the fuzzing
|
||||
### 2. Preparing the fuzzing campaign
|
||||
|
||||
As you fuzz the target with mutated input, having as diverse inputs for the
|
||||
target as possible improves the efficiency a lot.
|
||||
@ -401,7 +439,7 @@ reported bugs, test suites, random downloads from the internet, unit test
|
||||
case data - from all kind of PNG software.
|
||||
|
||||
If the input format is not known, you can also modify a target program to write
|
||||
away normal data it receives and processes to a file and use these.
|
||||
normal data it receives and processes to a file and use these.
|
||||
|
||||
#### b) Making the input corpus unique
|
||||
|
||||
@ -432,7 +470,7 @@ for i in *; do
|
||||
done
|
||||
```
|
||||
|
||||
This can also be parallelized, e.g. with `parallel`
|
||||
This step can also be parallelized, e.g. with `parallel`
|
||||
|
||||
#### Done!
|
||||
|
||||
@ -456,7 +494,7 @@ before the start of afl-fuzz as this improves performance by a x2 speed increase
|
||||
|
||||
#### a) Running afl-fuzz
|
||||
|
||||
Before to do even a test run of afl-fuzz execute `sudo afl-system-config` (on
|
||||
Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
|
||||
the host if you execute afl-fuzz in a docker container). This reconfigures the
|
||||
system for optimal speed - which afl-fuzz checks and bails otherwise.
|
||||
Set `export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot
|
||||
@ -588,7 +626,7 @@ then terminate it. The main node will pick it up and make it available to the
|
||||
other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` if you have no
|
||||
free core.
|
||||
|
||||
Note that you in nearly all cases you can never reach full coverage. A lot of
|
||||
Note that you in nearly all cases can never reach full coverage. A lot of
|
||||
functionality is usually behind options that were not activated or fuzz e.g.
|
||||
if you fuzz a library to convert image formats and your target is the png to
|
||||
tiff API then you will not touch any of the other library APIs and features.
|
||||
@ -607,7 +645,7 @@ switch or honggfuzz.
|
||||
|
||||
#### f) Improve the speed!
|
||||
|
||||
* Use [persistent mode](llvm_mode/README.persistent_mode.md) (x2-x20 speed increase)
|
||||
* Use [persistent mode](instrumentation/README.persistent_mode.md) (x2-x20 speed increase)
|
||||
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [docs/env_variables.md](docs/env_variables.md)
|
||||
* Linux: Use the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase)
|
||||
* Linux: Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure)
|
||||
@ -1035,7 +1073,6 @@ without feedback, bug reports, or patches from:
|
||||
Andrea Biondo Vincent Le Garrec
|
||||
Khaled Yakdan Kuang-che Wu
|
||||
Josephine Calliotte Konrad Welc
|
||||
Thomas Rooijakkers
|
||||
```
|
||||
|
||||
Thank you!
|
||||
|
@ -162,8 +162,7 @@ struct queue_entry {
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u32 tc_ref; /* Trace bytes ref count */
|
||||
|
||||
struct queue_entry *next, /* Next element, if any */
|
||||
*next_100; /* 100 elements ahead */
|
||||
struct queue_entry *next; /* Next element, if any */
|
||||
|
||||
};
|
||||
|
||||
@ -575,8 +574,7 @@ typedef struct afl_state {
|
||||
|
||||
struct queue_entry *queue, /* Fuzzing queue (linked list) */
|
||||
*queue_cur, /* Current offset within the queue */
|
||||
*queue_top, /* Top of the list */
|
||||
*q_prev100; /* Previous 100 marker */
|
||||
*queue_top; /* Top of the list */
|
||||
|
||||
// growing buf
|
||||
struct queue_entry **queue_buf;
|
||||
|
@ -101,7 +101,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
if (rptr < lptr || *rptr != '"') {
|
||||
|
||||
FATAL("Malformed name=\"value\" pair in line %u.", cur_line);
|
||||
WARNF("Malformed name=\"value\" pair in line %u.", cur_line);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -141,13 +142,19 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
if (*lptr != '"') {
|
||||
|
||||
FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line);
|
||||
WARNF("Malformed name=\"keyword\" pair in line %u.", cur_line);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
++lptr;
|
||||
|
||||
if (!*lptr) { FATAL("Empty keyword in line %u.", cur_line); }
|
||||
if (!*lptr) {
|
||||
|
||||
WARNF("Empty keyword in line %u.", cur_line);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Okay, let's allocate memory and copy data between "...", handling
|
||||
\xNN escaping, \\, and \". */
|
||||
@ -169,7 +176,9 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
case 1 ... 31:
|
||||
case 128 ... 255:
|
||||
FATAL("Non-printable characters in line %u.", cur_line);
|
||||
WARNF("Non-printable characters in line %u.", cur_line);
|
||||
continue;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
|
||||
@ -185,7 +194,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) {
|
||||
|
||||
FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line);
|
||||
WARNF("Invalid escaping (not \\xNN) in line %u.", cur_line);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -209,10 +219,11 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) {
|
||||
|
||||
FATAL(
|
||||
WARNF(
|
||||
"Keyword too big in line %u (%s, limit is %s)", cur_line,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -232,12 +243,17 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
|
||||
|
||||
u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); }
|
||||
if (!afl->extras_cnt) {
|
||||
|
||||
WARNF("No usable data in '%s'", dir);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
|
||||
compare_extras_len);
|
||||
|
||||
OKF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
|
||||
ACTF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
|
||||
|
||||
@ -250,7 +266,7 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
|
||||
|
||||
if (afl->extras_cnt > afl->max_det_extras) {
|
||||
|
||||
OKF("More than %d tokens - will use them probabilistically.",
|
||||
WARNF("More than %d tokens - will use them probabilistically.",
|
||||
afl->max_det_extras);
|
||||
|
||||
}
|
||||
@ -320,9 +336,10 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
if (st.st_size > MAX_DICT_FILE) {
|
||||
|
||||
WARNF(
|
||||
"Extra '%s' is very big (%s, limit is %s)", fn,
|
||||
"Extra '%s' is too big (%s, limit is %s)", fn,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -370,16 +387,74 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
/* Adds a new extra / dict entry. Used for LTO autodict. */
|
||||
/* Removes duplicates from the loaded extras. This can happen if multiple files
|
||||
are loaded */
|
||||
|
||||
void dedup_extras(afl_state_t *afl) {
|
||||
|
||||
if (afl->extras_cnt < 2) return;
|
||||
|
||||
u32 i, j, orig_cnt = afl->extras_cnt;
|
||||
|
||||
for (i = 0; i < afl->extras_cnt - 1; i++) {
|
||||
|
||||
for (j = i + 1; j < afl->extras_cnt; j++) {
|
||||
|
||||
restart_dedup:
|
||||
|
||||
// if the goto was used we could be at the end of the list
|
||||
if (j >= afl->extras_cnt || afl->extras[i].len != afl->extras[j].len)
|
||||
break;
|
||||
|
||||
if (memcmp(afl->extras[i].data, afl->extras[j].data,
|
||||
afl->extras[i].len) == 0) {
|
||||
|
||||
ck_free(afl->extras[j].data);
|
||||
if (j + 1 < afl->extras_cnt) // not at the end of the list?
|
||||
memmove((char *)&afl->extras[j], (char *)&afl->extras[j + 1],
|
||||
(afl->extras_cnt - j - 1) * sizeof(struct extra_data));
|
||||
afl->extras_cnt--;
|
||||
goto restart_dedup; // restart if several duplicates are in a row
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (afl->extras_cnt != orig_cnt)
|
||||
afl->extras = afl_realloc((void **)&afl->extras,
|
||||
afl->extras_cnt * sizeof(struct extra_data));
|
||||
|
||||
}
|
||||
|
||||
/* Adds a new extra / dict entry. */
|
||||
void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
|
||||
|
||||
u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
|
||||
u32 i, found = 0;
|
||||
|
||||
for (i = 0; i < afl->extras_cnt; i++) {
|
||||
|
||||
if (afl->extras[i].len == len) {
|
||||
|
||||
if (memcmp(afl->extras[i].data, mem, len) == 0) return;
|
||||
found = 1;
|
||||
|
||||
} else {
|
||||
|
||||
if (found) break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (len > MAX_DICT_FILE) {
|
||||
|
||||
WARNF("Extra '%.*s' is very big (%s, limit is %s)", (int)len, mem,
|
||||
WARNF("Extra '%.*s' is too big (%s, limit is %s)", (int)len, mem,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
return;
|
||||
|
||||
} else if (len > 32) {
|
||||
|
||||
@ -405,7 +480,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
|
||||
|
||||
if (afl->extras_cnt == afl->max_det_extras + 1) {
|
||||
|
||||
OKF("More than %d tokens - will use them probabilistically.",
|
||||
WARNF("More than %d tokens - will use them probabilistically.",
|
||||
afl->max_det_extras);
|
||||
|
||||
}
|
||||
@ -609,7 +684,7 @@ void load_auto(afl_state_t *afl) {
|
||||
|
||||
} else {
|
||||
|
||||
OKF("No auto-generated dictionary tokens to reuse.");
|
||||
ACTF("No auto-generated dictionary tokens to reuse.");
|
||||
|
||||
}
|
||||
|
||||
|
@ -611,17 +611,17 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
/* Read all testcases from the input directory, then queue them for testing.
|
||||
Called at startup. */
|
||||
|
||||
void read_testcases(afl_state_t *afl) {
|
||||
void read_testcases(afl_state_t *afl, u8 *directory) {
|
||||
|
||||
struct dirent **nl;
|
||||
s32 nl_cnt;
|
||||
s32 nl_cnt, subdirs = 1;
|
||||
u32 i;
|
||||
u8 * fn1;
|
||||
|
||||
u8 * fn1, *dir = directory;
|
||||
u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
/* Auto-detect non-in-place resumption attempts. */
|
||||
|
||||
if (dir == NULL) {
|
||||
fn1 = alloc_printf("%s/queue", afl->in_dir);
|
||||
if (!access(fn1, F_OK)) {
|
||||
|
||||
@ -632,16 +632,18 @@ void read_testcases(afl_state_t *afl) {
|
||||
ck_free(fn1);
|
||||
|
||||
}
|
||||
dir = afl->in_dir;
|
||||
}
|
||||
|
||||
ACTF("Scanning '%s'...", afl->in_dir);
|
||||
ACTF("Scanning '%s'...", dir);
|
||||
|
||||
/* We use scandir() + alphasort() rather than readdir() because otherwise,
|
||||
the ordering of test cases would vary somewhat randomly and would be
|
||||
difficult to control. */
|
||||
|
||||
nl_cnt = scandir(afl->in_dir, &nl, NULL, alphasort);
|
||||
nl_cnt = scandir(dir, &nl, NULL, alphasort);
|
||||
|
||||
if (nl_cnt < 0) {
|
||||
if (nl_cnt < 0 && directory == NULL) {
|
||||
|
||||
if (errno == ENOENT || errno == ENOTDIR) {
|
||||
|
||||
@ -656,7 +658,7 @@ void read_testcases(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
PFATAL("Unable to open '%s'", afl->in_dir);
|
||||
PFATAL("Unable to open '%s'", dir);
|
||||
|
||||
}
|
||||
|
||||
@ -674,19 +676,29 @@ void read_testcases(afl_state_t *afl) {
|
||||
u8 dfn[PATH_MAX];
|
||||
snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
|
||||
nl[i]->d_name);
|
||||
u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name);
|
||||
u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
|
||||
|
||||
u8 passed_det = 0;
|
||||
|
||||
free(nl[i]); /* not tracked */
|
||||
|
||||
if (lstat(fn2, &st) || access(fn2, R_OK)) {
|
||||
|
||||
PFATAL("Unable to access '%s'", fn2);
|
||||
|
||||
}
|
||||
|
||||
/* This also takes care of . and .. */
|
||||
/* obviously we want to skip "descending" into . and .. directories,
|
||||
however it is a good idea to skip also directories that start with
|
||||
a dot */
|
||||
if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
|
||||
|
||||
free(nl[i]); /* not tracked */
|
||||
read_testcases(afl, fn2);
|
||||
ck_free(fn2);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
free(nl[i]);
|
||||
|
||||
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
|
||||
|
||||
@ -718,7 +730,7 @@ void read_testcases(afl_state_t *afl) {
|
||||
|
||||
free(nl); /* not tracked */
|
||||
|
||||
if (!afl->queued_paths) {
|
||||
if (!afl->queued_paths && directory == NULL) {
|
||||
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
"Looks like there are no valid test cases in the input directory! The "
|
||||
@ -985,6 +997,76 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
/* Now we remove all entries from the queue that have a duplicate trace map */
|
||||
|
||||
q = afl->queue;
|
||||
struct queue_entry *p, *prev = NULL;
|
||||
int duplicates = 0;
|
||||
|
||||
restart_outer_cull_loop:
|
||||
|
||||
while (q) {
|
||||
|
||||
if (q->cal_failed || !q->exec_cksum) continue;
|
||||
|
||||
restart_inner_cull_loop:
|
||||
|
||||
p = q->next;
|
||||
|
||||
while (p) {
|
||||
|
||||
if (!p->cal_failed && p->exec_cksum == q->exec_cksum) {
|
||||
|
||||
duplicates = 1;
|
||||
--afl->pending_not_fuzzed;
|
||||
|
||||
// We do not remove any of the memory allocated because for
|
||||
// splicing the data might still be interesting.
|
||||
// We only decouple them from the linked list.
|
||||
// This will result in some leaks at exit, but who cares.
|
||||
|
||||
// we keep the shorter file
|
||||
if (p->len >= q->len) {
|
||||
|
||||
q->next = p->next;
|
||||
goto restart_inner_cull_loop;
|
||||
|
||||
} else {
|
||||
|
||||
if (prev)
|
||||
prev->next = q = p;
|
||||
else
|
||||
afl->queue = q = p;
|
||||
goto restart_outer_cull_loop;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
|
||||
}
|
||||
|
||||
prev = q;
|
||||
q = q->next;
|
||||
|
||||
}
|
||||
|
||||
if (duplicates) {
|
||||
|
||||
afl->max_depth = 0;
|
||||
q = afl->queue;
|
||||
while (q) {
|
||||
|
||||
if (q->depth > afl->max_depth) afl->max_depth = q->depth;
|
||||
q = q->next;
|
||||
|
||||
}
|
||||
|
||||
afl->q_prev100 = afl->queue = afl->queue_top = afl->queue;
|
||||
|
||||
}
|
||||
|
||||
OKF("All test cases processed.");
|
||||
|
||||
}
|
||||
|
@ -1707,20 +1707,8 @@ custom_mutator_stage:
|
||||
|
||||
} while (tid == afl->current_entry && afl->queued_paths > 1);
|
||||
|
||||
target = afl->queue;
|
||||
|
||||
while (tid >= 100) {
|
||||
|
||||
target = target->next_100;
|
||||
tid -= 100;
|
||||
|
||||
}
|
||||
|
||||
while (tid--) {
|
||||
|
||||
target = target->next;
|
||||
|
||||
}
|
||||
afl->splicing_with = tid;
|
||||
target = afl->queue_buf[tid];
|
||||
|
||||
/* Make sure that the target has a reasonable length. */
|
||||
|
||||
@ -4518,20 +4506,7 @@ pacemaker_fuzzing:
|
||||
} while (tid == afl->current_entry);
|
||||
|
||||
afl->splicing_with = tid;
|
||||
target = afl->queue;
|
||||
|
||||
while (tid >= 100) {
|
||||
|
||||
target = target->next_100;
|
||||
tid -= 100;
|
||||
|
||||
}
|
||||
|
||||
while (tid--) {
|
||||
|
||||
target = target->next;
|
||||
|
||||
}
|
||||
target = afl->queue_buf[tid];
|
||||
|
||||
/* Make sure that the target has a reasonable length. */
|
||||
|
||||
|
@ -239,13 +239,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
|
||||
afl->cycles_wo_finds = 0;
|
||||
|
||||
if (!(afl->queued_paths % 100)) {
|
||||
|
||||
afl->q_prev100->next_100 = q;
|
||||
afl->q_prev100 = q;
|
||||
|
||||
}
|
||||
|
||||
struct queue_entry **queue_buf = afl_realloc(
|
||||
AFL_BUF_PARAM(queue), afl->queued_paths * sizeof(struct queue_entry *));
|
||||
if (unlikely(!queue_buf)) { PFATAL("alloc"); }
|
||||
|
@ -119,8 +119,8 @@ static void usage(u8 *argv0, int more_help) {
|
||||
"etc.)\n"
|
||||
" -d - quick & dirty mode (skips deterministic steps)\n"
|
||||
" -n - fuzz without instrumentation (non-instrumented mode)\n"
|
||||
" -x dict_file - optional fuzzer dictionary (see README.md, its really "
|
||||
"good!)\n\n"
|
||||
" -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
|
||||
"times)\n\n"
|
||||
|
||||
"Testing settings:\n"
|
||||
" -s seed - use a fixed seed for the RNG\n"
|
||||
@ -243,11 +243,11 @@ static int stricmp(char const *a, char const *b) {
|
||||
|
||||
int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
s32 opt;
|
||||
s32 opt, i;
|
||||
u64 prev_queued = 0;
|
||||
u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE;
|
||||
u8 * extras_dir = 0;
|
||||
u8 mem_limit_given = 0, exit_1 = 0, debug = 0;
|
||||
u8 * extras_dir[4];
|
||||
u8 mem_limit_given = 0, exit_1 = 0, debug = 0, extras_dir_cnt = 0;
|
||||
char **use_argv;
|
||||
|
||||
struct timeval tv;
|
||||
@ -450,8 +450,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
case 'x': /* dictionary */
|
||||
|
||||
if (extras_dir) { FATAL("Multiple -x options not supported"); }
|
||||
extras_dir = optarg;
|
||||
if (extras_dir_cnt >= 4) {
|
||||
|
||||
FATAL("More than four -x options are not supported");
|
||||
|
||||
}
|
||||
|
||||
extras_dir[extras_dir_cnt++] = optarg;
|
||||
break;
|
||||
|
||||
case 't': { /* timeout */
|
||||
@ -828,10 +833,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
"Eißfeldt, Andrea Fioraldi and Dominik Maier");
|
||||
OKF("afl++ is open source, get it at "
|
||||
"https://github.com/AFLplusplus/AFLplusplus");
|
||||
OKF("Power schedules from github.com/mboehme/aflfast");
|
||||
OKF("Python Mutator and llvm_mode instrument file list from "
|
||||
"github.com/choller/afl");
|
||||
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
|
||||
|
||||
if (afl->sync_id && afl->is_main_node &&
|
||||
afl->afl_env.afl_custom_mutator_only) {
|
||||
@ -1139,7 +1140,15 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
pivot_inputs(afl);
|
||||
|
||||
if (extras_dir) { load_extras(afl, extras_dir); }
|
||||
if (extras_dir_cnt) {
|
||||
|
||||
for (i = 0; i < extras_dir_cnt; i++)
|
||||
load_extras(afl, extras_dir[i]);
|
||||
|
||||
dedup_extras(afl);
|
||||
OKF("Loaded a total of %u extras.", afl->extras_cnt);
|
||||
|
||||
}
|
||||
|
||||
if (!afl->timeout_given) { find_timeout(afl); }
|
||||
|
||||
|
Reference in New Issue
Block a user