diff options
31 files changed, 256 insertions, 172 deletions
diff --git a/.gitignore b/.gitignore index 4307fc4c..0527a0b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .test .test2 .sync_tmp +.vscode *.o *.so *.swp @@ -11,6 +12,7 @@ ld in out core* +compile_commands.json afl-analyze afl-as afl-clang @@ -40,6 +42,7 @@ afl-cmin.8 afl-cmin.bash.8 afl-fuzz.8 afl-gcc.8 +afl-g++.8 afl-gcc-fast.8 afl-g++-fast.8 afl-gotcpu.8 diff --git a/GNUmakefile b/GNUmakefile index cae172dd..1ccb2bb0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -24,17 +24,16 @@ BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH = $(PREFIX)/share/doc/afl MISC_PATH = $(PREFIX)/share/afl -MAN_PATH = $(PREFIX)/man/man8 +MAN_PATH = $(PREFIX)/share/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-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze +PROGS = afl-gcc afl-g++ 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" @@ -62,7 +61,10 @@ ifneq "$(shell uname)" "Darwin" endif endif # OS X does not like _FORTIFY_SOURCE=2 - CFLAGS_OPT += -D_FORTIFY_SOURCE=2 + # _FORTIFY_SOURCE=2 does not like -O0 + ifndef DEBUG + CFLAGS_OPT += -D_FORTIFY_SOURCE=2 + endif endif ifeq "$(shell uname)" "SunOS" @@ -204,7 +206,10 @@ 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 @@ -274,7 +279,7 @@ endif all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done -man: $(MANPAGES) +man: afl-gcc all $(MANPAGES) tests: source-only @cd test ; ./test-all.sh @@ -367,79 +372,81 @@ endif 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) src/$@.c -o $@ $(LDFLAGS) + $(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) src/$@.c -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CPPFLAGS) src/$@.c -o $@ $(LDFLAGS) ln -sf afl-as as src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h - $(CC) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o + $(CC) $(CFLAGS) $(CPPFLAGS) -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) -c src/afl-common.c -o src/afl-common.o + $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -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) -c src/afl-forkserver.c -o src/afl-forkserver.o + $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -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) -c src/afl-sharedmem.c -o src/afl-sharedmem.o + $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -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) 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) $(CPPFLAGS) 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) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) 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) 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) $(CPPFLAGS) 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) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) 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) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) # 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) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS) + $(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) 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) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -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) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(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 ./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) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -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) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(CPPFLAGS) -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) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -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) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -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) -c test/unittests/unit_list.c -o test/unittests/unit_list.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o unit_list: test/unittests/unit_list.o - @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(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 ./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) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o unit_preallocable: test/unittests/unit_preallocable.o - @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(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 ./test/unittests/unit_preallocable unit_clean: @@ -486,7 +493,7 @@ ifndef AFL_NO_X86 test_build: afl-gcc 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_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_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 ) 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 @@ -566,7 +573,8 @@ source-only: all %.8: % @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@ @echo .SH NAME >> $@ - @echo .B $* >> $@ + @echo -n ".B $* \- " >> $@ + @./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> $@ @echo >> $@ @echo .SH SYNOPSIS >> $@ @./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@ diff --git a/TODO.md b/TODO.md index 65d59271..52065bb0 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,13 @@ # TODO list for AFL++ -## Roadmap 2.67+ +## Roadmap 2.68+ - AFL_MAP_SIZE for qemu_mode and unicorn_mode - CPU affinity for many cores? There seems to be an issue > 96 cores - afl-plot to support multiple plot_data + - afl_custom_fuzz_splice_optin() + - intel-pt tracer + - honor -O flags and -fno-unroll-loops in afl-cc ## Further down the road diff --git a/afl-cmin b/afl-cmin index d38e7a97..619c6dae 100755 --- a/afl-cmin +++ b/afl-cmin @@ -120,6 +120,7 @@ function usage() { "AFL_PATH: path for the afl-showmap binary\n" \ "AFL_SKIP_BIN_CHECK: skip check for target binary\n" \ "AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" +"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" exit 1 } diff --git a/custom_mutators/radamsa/GNUmakefile b/custom_mutators/radamsa/GNUmakefile index 60e43b17..3798b110 100644 --- a/custom_mutators/radamsa/GNUmakefile +++ b/custom_mutators/radamsa/GNUmakefile @@ -15,14 +15,14 @@ libradamsa.a: libradamsa.c radamsa.h @echo " ***************************************************************" @echo " * Compiling libradamsa, wait some minutes (~3 on modern CPUs) *" @echo " ***************************************************************" - $(CC) -fPIC $(CFLAGS) -I $(CUR_DIR) -o libradamsa.a -c libradamsa.c + $(CC) -fPIC $(CFLAGS) $(CPPFLAGS) -I $(CUR_DIR) -o libradamsa.a -c libradamsa.c radamsa-mutator.so: radamsa-mutator.c libradamsa.a - $(CC) $(CFLAGS) -g -I. -I../../include -shared -fPIC -c radamsa-mutator.c - $(CC) $(CFLAGS) -shared -fPIC -o radamsa-mutator.so radamsa-mutator.o libradamsa.a + $(CC) $(CFLAGS) $(CPPFLAGS) -g -I. -I../../include -shared -fPIC -c radamsa-mutator.c + $(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC -o radamsa-mutator.so radamsa-mutator.o libradamsa.a test: libradamsa.a libradamsa-test.c - $(CC) $(CFLAGS) -I $(CUR_DIR) -o libradamsa-test libradamsa-test.c libradamsa.a + $(CC) $(CFLAGS) $(CPPFLAGS) -I $(CUR_DIR) -o libradamsa-test libradamsa-test.c libradamsa.a ./libradamsa-test libradamsa-test.c | grep "library test passed" rm /tmp/libradamsa-*.fuzz diff --git a/docs/Changelog.md b/docs/Changelog.md index 45fbd528..72c8952c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. ### Version ++2.67d (develop) + - a few QOL changes for Apple and its outdated gmake - afl-fuzz: - Fix for auto dictionary entries found during fuzzing to not throw out a -x dictionary @@ -18,6 +19,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. dict entries without recompiling. - AFL_FORKSRV_INIT_TMOUT env variable added to control the time to wait for the forkserver to come up without the need to increase the overall timeout. + - bugfix for cmplog that results in a heap overflow based on target data + (thanks to the magma team for reporting!) - custom mutators: - added afl_custom_fuzz_count/fuzz_count function to allow specifying the number of fuzz attempts for custom_fuzz @@ -416,7 +419,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - big code refactoring: * all includes are now in include/ * all afl sources are now in src/ - see src/README.md - * afl-fuzz was splitted up in various individual files for including + * afl-fuzz was split up in various individual files for including functionality in other programs (e.g. forkserver, memory map, etc.) for better readability. * new code indention everywhere diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md index a3d3330f..cb1288ef 100644 --- a/docs/binaryonly_fuzzing.md +++ b/docs/binaryonly_fuzzing.md @@ -6,14 +6,14 @@ However, if there is only the binary program and no source code available, then standard `afl-fuzz -n` (non-instrumented mode) is not effective. - The following is a description of how these binaries can be fuzzed with afl++ + The following is a description of how these binaries can be fuzzed with afl++. ## TL;DR: qemu_mode in persistent mode is the fastest - if the stability is high enough. Otherwise try retrowrite, afl-dyninst and if these - fail too then standard qemu_mode with AFL_ENTRYPOINT to where you need it. + fail too then try standard qemu_mode with AFL_ENTRYPOINT to where you need it. If your target is a library use examples/afl_frida/. @@ -29,10 +29,10 @@ The speed decrease is at about 50%. However various options exist to increase the speed: - - using AFL_ENTRYPOINT to move the forkserver to a later basic block in + - using AFL_ENTRYPOINT to move the forkserver entry to a later basic block in the binary (+5-10% speed) - using persistent mode [qemu_mode/README.persistent.md](../qemu_mode/README.persistent.md) - this will result in 150-300% overall speed - so 3-8x the original + this will result in 150-300% overall speed increase - so 3-8x the original qemu_mode speed! - using AFL_CODE_START/AFL_CODE_END to only instrument specific parts @@ -104,7 +104,7 @@ ## RETROWRITE - If you have an x86/x86_64 binary that still has it's symbols, is compiled + If you have an x86/x86_64 binary that still has its symbols, is compiled with position independant code (PIC/PIE) and does not use most of the C++ features then the retrowrite solution might be for you. It decompiles to ASM files which can then be instrumented with afl-gcc. @@ -148,7 +148,7 @@ ## CORESIGHT Coresight is ARM's answer to Intel's PT. - There is no implementation so far which handle coresight and getting + There is no implementation so far which handles coresight and getting it working on an ARM Linux is very difficult due to custom kernel building on embedded systems is difficult. And finding one that has coresight in the ARM chip is difficult too. diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 75dbea21..a128f587 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -94,8 +94,11 @@ def queue_new_entry(filename_new_queue, filename_orig_queue): - `fuzz_count` (optional): - This method can be used to instruct afl-fuzz how often to perform a fuzz - attempt on this input data. + When a queue entry is selected to be fuzzed, afl-fuzz selects the number + of fuzzing attempts with this input based on a few factors. + If however the custom mutator wants to set this number instead on how often + it is called for a specific queue entry, use this function. + This function in mostly useful if **not** `AFL_CUSTOM_MUTATOR_ONLY` is used. - `fuzz` (optional): diff --git a/docs/env_variables.md b/docs/env_variables.md index e8129a3f..c47d10e8 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -10,8 +10,8 @@ Because they can't directly accept command-line options, the compile-time tools make fairly broad use of environmental variables: - - Most afl tools do not print any ouput if stout/stderr are redirected. - If you want to have the output into a file then set the AFL_DEBUG + - Most afl tools do not print any output if stdout/stderr are redirected. + If you want to save the output in a file then set the AFL_DEBUG environment variable. This is sadly necessary for various build processes which fail otherwise. @@ -44,7 +44,7 @@ tools make fairly broad use of environmental variables: you instrument hand-written assembly when compiling clang code by plugging a normalizer into the chain. (There is no equivalent feature for GCC.) - - Setting AFL_INST_RATIO to a percentage between 0 and 100% controls the + - Setting AFL_INST_RATIO to a percentage between 0% and 100% controls the probability of instrumenting every branch. This is (very rarely) useful when dealing with exceptionally complex programs that saturate the output bitmap. Examples include v8, ffmpeg, and perl. @@ -88,7 +88,7 @@ of the settings discussed in section #1, with the exception of: - TMPDIR and AFL_KEEP_ASSEMBLY, since no temporary assembly files are created. - - AFL_INST_RATIO, as we by default collision free instrumentation is used. + - AFL_INST_RATIO, as we by default use collision free instrumentation. Then there are a few specific features that are only available in llvm_mode: @@ -121,7 +121,7 @@ Then there are a few specific features that are only available in llvm_mode: None of the following options are necessary to be used and are rather for manual use (which only ever the author of this LTO implementation will use). - These are used if several seperated instrumentation are performed which + These are used if several seperated instrumentations are performed which are then later combined. - AFL_LLVM_DOCUMENT_IDS=file will document to a file which edge ID was given @@ -200,7 +200,7 @@ Then there are a few specific features that are only available in llvm_mode: ### INSTRUMENT LIST (selectively instrument files and functions) - This feature allows selectively instrumentation of the source + This feature allows selective instrumentation of the source - Setting AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST with a filenames and/or function will only instrument (or skip) those files that match the names @@ -369,13 +369,6 @@ checks or alter some of the more exotic semantics of the tool: for an existing out folder, even if a different `-i` was provided. Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir. - - Setting AFL_MAX_DET_EXRAS will change the threshold at what number of elements - in the `-x` dictionary and LTO autodict (combined) the probabilistic mode will - kick off. In probabilistic mode, not all dictionary entires will be used all - of the times for fuzzing mutations to not make fuzzing slower by it. - The default count is `200` element. So for the 200 + 1st element, there is a - 1 in 201 chance, that one of the dictionary entry will not be used directly. - - Setting AFL_NO_FORKSRV disables the forkserver optimization, reverting to fork + execve() call for every tested input. This is useful mostly when working with unruly libraries that create threads or do other crazy @@ -384,6 +377,16 @@ checks or alter some of the more exotic semantics of the tool: Note that this setting inhibits some of the user-friendly diagnostics normally done when starting up the forkserver and causes a pretty significant performance drop. + + - Setting AFL_MAX_DET_EXTRAS changes the count of dictionary entries/extras + (default 200), after which the entries will be used probabilistically. + So, if the dict/extras file (`-x`) contains more tokens than this threshold, + not all of the tokens will be used in each fuzzing step, every time. + Instead, there is a chance that the entry will be skipped during fuzzing. + This makes sure that the fuzzer doesn't spend all its time only inserting + the extras, but will still do other mutations. However, it decreases the + likelihood for each token to be inserted, before the next queue entry is fuzzed. + Either way, all tokens will be used eventually, in a longer fuzzing campaign. - Outdated environment variables that are that not supported anymore: AFL_DEFER_FORKSRV diff --git a/docs/parallel_fuzzing.md b/docs/parallel_fuzzing.md index 2ab1466c..bf57ace8 100644 --- a/docs/parallel_fuzzing.md +++ b/docs/parallel_fuzzing.md @@ -10,8 +10,8 @@ n-core system, you can almost always run around n concurrent fuzzing jobs with virtually no performance hit (you can use the afl-gotcpu tool to make sure). In fact, if you rely on just a single job on a multi-core system, you will -be underutilizing the hardware. So, parallelization is usually the right -way to go. +be underutilizing the hardware. So, parallelization is always the right way to +go. When targeting multiple unrelated binaries or using the tool in "non-instrumented" (-n) mode, it is perfectly fine to just start up several @@ -65,22 +65,7 @@ still perform deterministic checks; while the secondary instances will proceed straight to random tweaks. Note that you must always have one -M main instance! - -Note that running multiple -M instances is wasteful, although there is an -experimental support for parallelizing the deterministic checks. To leverage -that, you need to create -M instances like so: - -``` -./afl-fuzz -i testcase_dir -o sync_dir -M mainA:1/3 [...] -./afl-fuzz -i testcase_dir -o sync_dir -M mainB:2/3 [...] -./afl-fuzz -i testcase_dir -o sync_dir -M mainC:3/3 [...] -``` - -...where the first value after ':' is the sequential ID of a particular main -instance (starting at 1), and the second value is the total number of fuzzers to -distribute the deterministic fuzzing across. Note that if you boot up fewer -fuzzers than indicated by the second number passed to -M, you may end up with -poor coverage. +Running multiple -M instances is wasteful! You can also monitor the progress of your jobs from the command line with the provided afl-whatsup tool. When the instances are no longer finding new paths, @@ -99,61 +84,88 @@ example may be: This is not a concern if you use @@ without -f and let afl-fuzz come up with the file name. -## 3) Syncing with non-afl fuzzers or independant instances +## 3) Multiple -M mains + + +There is support for parallelizing the deterministic checks. +This is only needed where + + 1. many new paths are found fast over a long time and it looks unlikely that + main node will ever catch up, and + 2. deterministic fuzzing is actively helping path discovery (you can see this + in the main node for the first for lines in the "fuzzing strategy yields" + section. If the ration `found/attemps` is high, then it is effective. It + most commonly isn't.) + +Only if both are true it is beneficial to have more than one main. +You can leverage this by creating -M instances like so: + +``` +./afl-fuzz -i testcase_dir -o sync_dir -M mainA:1/3 [...] +./afl-fuzz -i testcase_dir -o sync_dir -M mainB:2/3 [...] +./afl-fuzz -i testcase_dir -o sync_dir -M mainC:3/3 [...] +``` + +... where the first value after ':' is the sequential ID of a particular main +instance (starting at 1), and the second value is the total number of fuzzers to +distribute the deterministic fuzzing across. Note that if you boot up fewer +fuzzers than indicated by the second number passed to -M, you may end up with +poor coverage. + +## 4) Syncing with non-afl fuzzers or independant instances A -M main node can be told with the `-F other_fuzzer_queue_directory` option to sync results from other fuzzers, e.g. libfuzzer or honggfuzz. Only the specified directory will by synced into afl, not subdirectories. -The specified directories do not need to exist yet at the start of afl. +The specified directory does not need to exist yet at the start of afl. -## 4) Multi-system parallelization +The `-F` option can be passed to the main node several times. + +## 5) Multi-system parallelization The basic operating principle for multi-system parallelization is similar to the mechanism explained in section 2. The key difference is that you need to write a simple script that performs two actions: - Uses SSH with authorized_keys to connect to every machine and retrieve - a tar archive of the /path/to/sync_dir/<fuzzer_id>/queue/ directories for - every <fuzzer_id> local to the machine. It's best to use a naming scheme - that includes host name in the fuzzer ID, so that you can do something - like: + a tar archive of the /path/to/sync_dir/<main_node(s)> directory local to + the machine. + It is best to use a naming scheme that includes host name and it's being + a main node (e.g. main1, main2) in the fuzzer ID, so that you can do + something like: ```sh - for s in {1..10}; do - ssh user@host${s} "tar -czf - sync/host${s}_fuzzid*/[qf]*" >host${s}.tgz + for host in `cat HOSTLIST`; do + ssh user@$host "tar -czf - sync/$host_main*/" > $host.tgz done ``` - Distributes and unpacks these files on all the remaining machines, e.g.: ```sh - for s in {1..10}; do - for d in {1..10}; do - test "$s" = "$d" && continue - ssh user@host${d} 'tar -kxzf -' <host${s}.tgz + for srchost in `cat HOSTLIST`; do + for dsthost in `cat HOSTLIST`; do + test "$srchost" = "$dsthost" && continue + ssh user@$srchost 'tar -kxzf -' < $dsthost.tgz done done ``` -There is an example of such a script in examples/distributed_fuzzing/; -you can also find a more featured, experimental tool developed by -Martijn Bogaard at: - - https://github.com/MartijnB/disfuzz-afl - -Another client-server implementation from Richo Healey is: +There is an example of such a script in examples/distributed_fuzzing/. - https://github.com/richo/roving +There are other (older) more featured, experimental tools: + * https://github.com/richo/roving + * https://github.com/MartijnB/disfuzz-afl -Note that these third-party tools are unsafe to run on systems exposed to the -Internet or to untrusted users. +However these do not support syncing just main nodes (yet). When developing custom test case sync code, there are several optimizations to keep in mind: - The synchronization does not have to happen very often; running the - task every 30 minutes or so may be perfectly fine. + task every 60 minutes or even less often at later fuzzing stages is + fine - There is no need to synchronize crashes/ or hangs/; you only need to copy over queue/* (and ideally, also fuzzer_stats). @@ -179,19 +191,24 @@ to keep in mind: - You do not want a "main" instance of afl-fuzz on every system; you should run them all with -S, and just designate a single process somewhere within the fleet to run with -M. + + - Syncing is only necessary for the main nodes on a system. It is possible + to run main-less with only secondaries. However then you need to find out + which secondary took over the temporary role to be the main node. Look for + the `is_main_node` file in the fuzzer directories, eg. `sync-dir/hostname-*/is_main_node` It is *not* advisable to skip the synchronization script and run the fuzzers directly on a network filesystem; unexpected latency and unkillable processes in I/O wait state can mess things up. -## 5) Remote monitoring and data collection +## 6) Remote monitoring and data collection You can use screen, nohup, tmux, or something equivalent to run remote instances of afl-fuzz. If you redirect the program's output to a file, it will automatically switch from a fancy UI to more limited status reports. There is -also basic machine-readable information always written to the fuzzer_stats file -in the output directory. Locally, that information can be interpreted with -afl-whatsup. +also basic machine-readable information which is always written to the +fuzzer_stats file in the output directory. Locally, that information can be +interpreted with afl-whatsup. In principle, you can use the status screen of the main (-M) instance to monitor the overall fuzzing progress and decide when to stop. In this @@ -208,7 +225,7 @@ Keep in mind that crashing inputs are *not* automatically propagated to the main instance, so you may still want to monitor for crashes fleet-wide from within your synchronization or health checking scripts (see afl-whatsup). -## 6) Asymmetric setups +## 7) Asymmetric setups It is perhaps worth noting that all of the following is permitted: @@ -224,7 +241,7 @@ It is perhaps worth noting that all of the following is permitted: the discovered test cases can have synergistic effects and improve the overall coverage. - (In this case, running one -M instance per each binary is a good plan.) + (In this case, running one -M instance per target is necessary.) - Having some of the fuzzers invoke the binary in different ways. For example, 'djpeg' supports several DCT modes, configurable with diff --git a/examples/afl_network_proxy/afl-network-server.c b/examples/afl_network_proxy/afl-network-server.c index c70fd47d..75eb3d20 100644 --- a/examples/afl_network_proxy/afl-network-server.c +++ b/examples/afl_network_proxy/afl-network-server.c @@ -74,6 +74,7 @@ static u8 *in_data; /* Input data for trimming */ static u8 *buf2; static s32 in_len; +static s32 buf2_len; static u32 map_size = MAP_SIZE; static volatile u8 stop_soon; /* Ctrl-C pressed? */ @@ -381,6 +382,7 @@ int recv_testcase(int s, void **buf) { if (clen < 1) FATAL("did not receive valid compressed len information: %u", clen); buf2 = afl_realloc((void **)&buf2, clen); + buf2_len = clen; if (unlikely(!buf2)) { PFATAL("Alloc"); } received = 0; while (received < clen && @@ -641,6 +643,7 @@ int main(int argc, char **argv_orig, char **envp) { compressor = libdeflate_alloc_compressor(1); decompressor = libdeflate_alloc_decompressor(); buf2 = afl_realloc((void **)&buf2, map_size + 16); + buf2_len = map_size + 16; if (unlikely(!buf2)) { PFATAL("alloc"); } lenptr = (u32 *)(buf2 + 4); fprintf(stderr, "Compiled with compression support\n"); diff --git a/examples/distributed_fuzzing/sync_script.sh b/examples/distributed_fuzzing/sync_script.sh index c45ae69b..b28ff6cd 100755 --- a/examples/distributed_fuzzing/sync_script.sh +++ b/examples/distributed_fuzzing/sync_script.sh @@ -39,8 +39,11 @@ FUZZ_USER=bob # Directory to synchronize SYNC_DIR='/home/bob/sync_dir' -# Interval (seconds) between sync attempts -SYNC_INTERVAL=$((30 * 60)) +# We only capture -M main nodes, set the name to your chosen naming scheme +MAIN_NAME='main' + +# Interval (seconds) between sync attempts (eg one hour) +SYNC_INTERVAL=$((60 * 60)) if [ "$AFL_ALLOW_TMP" = "" ]; then @@ -63,7 +66,7 @@ while :; do echo "[*] Retrieving data from ${host}.${FUZZ_DOMAIN}..." ssh -o 'passwordauthentication no' ${FUZZ_USER}@${host}.$FUZZ_DOMAIN \ - "cd '$SYNC_DIR' && tar -czf - ${host}_*/[qf]*" >".sync_tmp/${host}.tgz" + "cd '$SYNC_DIR' && tar -czf - ${host}_${MAIN_NAME}*/" > ".sync_tmp/${host}.tgz" done @@ -80,7 +83,7 @@ while :; do echo " Sending fuzzer data from ${src_host}.${FUZZ_DOMAIN}..." ssh -o 'passwordauthentication no' ${FUZZ_USER}@$dst_host \ - "cd '$SYNC_DIR' && tar -xkzf -" <".sync_tmp/${src_host}.tgz" + "cd '$SYNC_DIR' && tar -xkzf - " < ".sync_tmp/${src_host}.tgz" done diff --git a/gcc_plugin/GNUmakefile b/gcc_plugin/GNUmakefile index f10a6c1d..625b55fb 100644 --- a/gcc_plugin/GNUmakefile +++ b/gcc_plugin/GNUmakefile @@ -24,7 +24,7 @@ PREFIX ?= /usr/local HELPER_PATH ?= $(PREFIX)/lib/afl BIN_PATH ?= $(PREFIX)/bin DOC_PATH ?= $(PREFIX)/share/doc/afl -MAN_PATH ?= $(PREFIX)/man/man8 +MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) @@ -111,21 +111,21 @@ test_deps: @echo "[+] All set and ready to build." afl-common.o: ../src/afl-common.c - $(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS) ../afl-gcc-fast: afl-gcc-fast.c afl-common.o | test_deps - $(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) + $(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS) ln -sf afl-gcc-fast ../afl-g++-fast ../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps $(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@ ../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps - $(CC) $(CFLAGS_SAFE) -fPIC -c $< -o $@ + $(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -fPIC -c $< -o $@ test_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." - unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) + unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) # unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) 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 diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index c088b61c..23477e22 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -24,7 +24,7 @@ PREFIX ?= /usr/local HELPER_PATH ?= $(PREFIX)/lib/afl BIN_PATH ?= $(PREFIX)/bin DOC_PATH ?= $(PREFIX)/share/doc/afl -MAN_PATH ?= $(PREFIX)/man/man8 +MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) VERSION:sh= grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2 diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c5b01da8..f3a76492 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1027,11 +1027,17 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { } - /* Modulo is biased - we don't want our fuzzing to be biased so let's do it right. */ - u64 unbiased_rnd; + /* Modulo is biased - we don't want our fuzzing to be biased so let's do it + right. See: + https://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator + */ + u64 unbiased_rnd; do { + unbiased_rnd = rand_next(afl); + } while (unlikely(unbiased_rnd >= (UINT64_MAX - (UINT64_MAX % limit)))); + return unbiased_rnd % limit; } diff --git a/libdislocator/Makefile b/libdislocator/Makefile index f9c4cb65..1c2fcaa7 100644 --- a/libdislocator/Makefile +++ b/libdislocator/Makefile @@ -28,7 +28,7 @@ all: libdislocator.so VPATH = .. libdislocator.so: libdislocator.so.c ../config.h - $(CC) $(CFLAGS) -shared -fPIC libdislocator.so.c -o ../$@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC libdislocator.so.c -o ../$@ $(LDFLAGS) .NOTPARALLEL: clean diff --git a/libtokencap/Makefile b/libtokencap/Makefile index 244ee58f..2343125f 100644 --- a/libtokencap/Makefile +++ b/libtokencap/Makefile @@ -16,7 +16,7 @@ PREFIX ?= /usr/local HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH ?= $(PREFIX)/share/doc/afl -MAN_PATH ?= $(PREFIX)/man/man8 +MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) @@ -70,7 +70,7 @@ all: $(TARGETS) VPATH = .. libtokencap.so: libtokencap.so.c ../config.h - $(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS) .NOTPARALLEL: clean diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 702c2c08..55c488f9 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -24,10 +24,12 @@ HELPER_PATH ?= $(PREFIX)/lib/afl BIN_PATH ?= $(PREFIX)/bin DOC_PATH ?= $(PREFIX)/share/doc/afl MISC_PATH ?= $(PREFIX)/share/afl -MAN_PATH ?= $(PREFIX)/man/man8 +MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) +BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d") + ifeq "$(shell uname)" "OpenBSD" LLVM_CONFIG ?= $(BIN_PATH)/llvm-config HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1) @@ -224,7 +226,8 @@ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \ -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \ -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \ -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \ - -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function + -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function \ + -fdebug-prefix-map="$(CURDIR)=llvm_mode" override CFLAGS += $(CFLAGS_SAFE) ifdef AFL_TRACE_PC @@ -329,10 +332,10 @@ endif @echo "[+] All set and ready to build." afl-common.o: ../src/afl-common.c - $(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS) ../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps - $(CC) $(CLANG_CFL) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" + $(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" ln -sf afl-clang-fast ../afl-clang-fast++ ifneq "$(AFL_CLANG_FLTO)" "" ifeq "$(LLVM_LTO)" "1" @@ -342,7 +345,7 @@ endif endif afl-llvm-common.o: afl-llvm-common.cc afl-llvm-common.h - $(CXX) $(CFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ + $(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ ../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc afl-llvm-common.o | test_deps -$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) afl-llvm-common.o @@ -360,7 +363,7 @@ endif ../afl-ld-lto: afl-ld-lto.c ifeq "$(LLVM_LTO)" "1" - $(CC) $(CFLAGS) $< -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ endif ../SanitizerCoverageLTO.so: SanitizerCoverageLTO.so.cc @@ -371,9 +374,9 @@ endif ../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o - $(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o - @$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi - @$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi + $(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o + @$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi + @$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi endif # laf @@ -392,20 +395,20 @@ endif $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o document: - $(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o - @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi - @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + $(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o + @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi ../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps - $(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -fPIC -c $< -o $@ + $(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@ ../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps @printf "[*] Building 32-bit variant of the runtime (-m32)... " - @$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(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 ../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps @printf "[*] Building 64-bit variant of the runtime (-m64)... " - @$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(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_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." @@ -434,15 +437,16 @@ install: all if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi if [ -f ../SanitizerCoverageLTO.so ]; then set -e; install -m 755 ../SanitizerCoverageLTO.so $${DESTDIR}$(HELPER_PATH); fi set -e; install -m 644 ../dynamic_list.txt $${DESTDIR}$(HELPER_PATH) - 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 + 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 install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/ - install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md + install -m 644 README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md vpath % .. %.8: % - @echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@ + @echo .TH $* 8 $(BUILD_DATE) "afl++" > ../$@ @echo .SH NAME >> ../$@ - @echo .B $* >> ../$@ + @echo -n ".B $* \- " >> ../$@ + @../$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ../$@ @echo >> ../$@ @echo .SH SYNOPSIS >> ../$@ @../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@ diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 6ea98111..ccdbca9d 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -670,9 +670,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + #ifndef __APPLE__ if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); + #endif #endif @@ -812,16 +814,24 @@ int main(int argc, char **argv, char **envp) { ptr += strlen("ngram"); while (*ptr && (*ptr < '0' || *ptr > '9')) { + ptr++; + } + if (!*ptr) { + ptr = getenv("AFL_LLVM_NGRAM_SIZE"); if (!ptr || !*ptr) { + FATAL( "you must set the NGRAM size with (e.g. for value 2) " "AFL_LLVM_INSTRUMENT=ngram-2"); + } + } + ngram_size = atoi(ptr); if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) FATAL( diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 7dd5a02a..189b4ec6 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -344,14 +344,10 @@ static std::string getSourceName(llvm::Function *F) { (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) if (Loc) { - StringRef instFilename; + StringRef instFilename; DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode()); - if (cDILoc) { - - instFilename = cDILoc->getFilename(); - - } + if (cDILoc) { instFilename = cDILoc->getFilename(); } if (instFilename.str().empty()) { diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index c25cad9d..125db229 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -374,17 +374,29 @@ bool AFLLTOPass::runOnModule(Module &M) { std::string Str1, Str2; StringRef TmpStr; bool HasStr1 = getConstantStringInfo(Str1P, TmpStr); - if (TmpStr.empty()) + if (TmpStr.empty()) { + HasStr1 = false; - else + + } else { + + HasStr1 = true; Str1 = TmpStr.str(); + + } + bool HasStr2 = getConstantStringInfo(Str2P, TmpStr); - if (TmpStr.empty()) + if (TmpStr.empty()) { + HasStr2 = false; - (void) HasStr2 /* never read */ - else + + } else { + + HasStr2 = true; Str2 = TmpStr.str(); + } + if (debug) fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n", FuncName.c_str(), Str1P, Str1P->getName().str().c_str(), diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index d00fd26f..bdafbe0b 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -339,7 +339,7 @@ static void __afl_map_shm(void) { if (__afl_area_ptr == MAP_FAILED) { - fprintf(stderr, "can not aquire mmap for address %p\n", + fprintf(stderr, "can not acquire mmap for address %p\n", (void *)__afl_map_addr); exit(1); diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index 617b55de..2e57a30a 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -1272,7 +1272,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { if (!be_quiet) { errs() << "Split-floatingpoint-compare-pass: " << count - << " FP comparisons splitted\n"; + << " FP comparisons split\n"; } @@ -1290,7 +1290,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { count = splitIntCompares(M, bitw); if (!be_quiet) errs() << "Split-integer-compare-pass " << bitw << "bit: " << count - << " splitted\n"; + << " split\n"; bitw >>= 1; #if LLVM_VERSION_MAJOR > 3 || \ @@ -1301,7 +1301,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { count = splitIntCompares(M, bitw); if (!be_quiet) errs() << "Split-integer-compare-pass " << bitw << "bit: " << count - << " splitted\n"; + << " split\n"; bitw >>= 1; #if LLVM_VERSION_MAJOR > 3 || \ @@ -1312,7 +1312,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { count = splitIntCompares(M, bitw); if (!be_quiet) errs() << "Split-integer-compare-pass " << bitw << "bit: " << count - << " splitted\n"; + << " split\n"; bitw >>= 1; break; diff --git a/qemu_mode/libcompcov/Makefile b/qemu_mode/libcompcov/Makefile index 9ed3e3fa..c2880b99 100644 --- a/qemu_mode/libcompcov/Makefile +++ b/qemu_mode/libcompcov/Makefile @@ -16,7 +16,7 @@ PREFIX ?= /usr/local HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH ?= $(PREFIX)/share/doc/afl -MAN_PATH ?= $(PREFIX)/man/man8 +MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) diff --git a/src/afl-as.c b/src/afl-as.c index 0ed47d8c..7d70bfcd 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -152,7 +152,7 @@ static void edit_params(int argc, char **argv) { /* The Apple case is a bit different... */ - if (!strcmp(argv[i], "-arch") && i + 1 < argc) { + if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) { if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7b7ba006..102f04b9 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -256,18 +256,18 @@ void bind_to_free_cpu(afl_state_t *afl) { } - for (i = 0; i < proccount; i++) { + for (i = 0; i < (s32)proccount; i++) { #if defined(__FreeBSD__) if (!strcmp(procs[i].ki_comm, "idle")) continue; // fix when ki_oncpu = -1 - int oncpu; + s32 oncpu; oncpu = procs[i].ki_oncpu; if (oncpu == -1) oncpu = procs[i].ki_lastcpu; - if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60) + if (oncpu != -1 && oncpu < (s32)sizeof(cpu_used) && procs[i].ki_pctcpu > 60) cpu_used[oncpu] = 1; #elif defined(__DragonFly__) @@ -1843,7 +1843,8 @@ void setup_stdio_file(afl_state_t *afl) { if (afl->file_extension) { - afl->fsrv.out_file = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension); + afl->fsrv.out_file = + alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension); } else { @@ -1851,11 +1852,15 @@ void setup_stdio_file(afl_state_t *afl) { } - unlink(afl->fsrv.out_file); /* Ignore errors */ + unlink(afl->fsrv.out_file); /* Ignore errors */ afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, 0600); - if (afl->fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); } + if (afl->fsrv.out_fd < 0) { + + PFATAL("Unable to create '%s'", afl->fsrv.out_file); + + } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1abd49d8..0df6c15c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -178,8 +178,9 @@ static void usage(u8 *argv0, int more_help) { "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" " the target was compiled for\n" - "AFL_MAX_DET_EXTRAS: if the dict/extras file contains more tokens than this threshold,\n" - " the tokens will sometimes be skipped during fuzzing.\n" + "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n" + " then they are randomly selected instead all of them being\n" + " used. Defaults to 200.\n" "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n" "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n" "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n" @@ -191,7 +192,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_QUIET: suppress forkserver status messages\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" - "AFL_SKIP_BIN_CHECK: skip the check, if the target is an excutable\n" + "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" diff --git a/src/afl-gcc.c b/src/afl-gcc.c index 22e6be8e..97564aea 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -415,7 +415,7 @@ int main(int argc, char **argv) { "AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n" "AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n"; - if (argc == 2 && strcmp(argv[1], "-h") == 0) { + if (argc == 2 && strncmp(argv[1], "-h", 2) == 0) { printf("afl-cc" VERSION " by Michal Zalewski\n\n"); printf("%s \n\n", argv[0]); diff --git a/src/afl-performance.c b/src/afl-performance.c index 0c1697a8..a9d7cefa 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -72,12 +72,12 @@ void jump(afl_state_t *afl) { static const uint64_t JUMP[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c}; - int i, b; + size_t i, b; uint64_t s0 = 0; uint64_t s1 = 0; uint64_t s2 = 0; uint64_t s3 = 0; - for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (i = 0; i < (sizeof(JUMP) / sizeof(*JUMP)); i++) for (b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) { @@ -110,12 +110,12 @@ void long_jump(afl_state_t *afl) { static const uint64_t LONG_JUMP[] = {0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635}; - int i, b; + size_t i, b; uint64_t s0 = 0; uint64_t s1 = 0; uint64_t s2 = 0; uint64_t s3 = 0; - for (i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) + for (i = 0; i < (sizeof(LONG_JUMP) / sizeof(*LONG_JUMP)); i++) for (b = 0; b < 64; b++) { if (LONG_JUMP[i] & UINT64_C(1) << b) { @@ -145,7 +145,7 @@ void long_jump(afl_state_t *afl) { u32 hash32(u8 *key, u32 len, u32 seed) { #else -u32 inline hash32(u8 *key, u32 len, u32 seed) { +inline u32 hash32(u8 *key, u32 len, u32 seed) { #endif @@ -157,7 +157,7 @@ u32 inline hash32(u8 *key, u32 len, u32 seed) { u64 hash64(u8 *key, u32 len, u64 seed) { #else -u64 inline hash64(u8 *key, u32 len, u64 seed) { +inline u64 hash64(u8 *key, u32 len, u64 seed) { #endif diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 64b52479..f4a7c336 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -636,6 +636,8 @@ static void usage(u8 *argv0) { "size\n" " the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" + "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during " + "startup (in milliseconds)\n" "AFL_QUIET: do not print extra informational output\n", argv0, MEM_LIMIT, doc_path); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 59269f45..e1d08054 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -846,6 +846,7 @@ static void usage(u8 *argv0) { " the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n" + "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); |