diff options
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rwxr-xr-x | afl-cmin | 65 | ||||
-rwxr-xr-x | afl-cmin.bash | 3 | ||||
-rw-r--r-- | docs/Changelog.md | 4 | ||||
-rw-r--r-- | include/alloc-inl.h | 3 | ||||
-rw-r--r-- | llvm_mode/afl-clang-fast.c | 4 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-pass.so.cc | 4 | ||||
-rw-r--r-- | llvm_mode/compare-transform-pass.so.cc | 2 | ||||
-rw-r--r-- | llvm_mode/split-compares-pass.so.cc | 11 | ||||
-rw-r--r-- | llvm_mode/split-switches-pass.so.cc | 5 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-tcg-runtime-inl.h | 4 | ||||
-rw-r--r-- | src/afl-as.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 12 | ||||
-rw-r--r-- | src/afl-fuzz.c | 54 | ||||
-rw-r--r-- | src/afl-gcc.c | 54 | ||||
-rw-r--r-- | src/afl-showmap.c | 16 | ||||
-rwxr-xr-x | test/test.sh | 62 | ||||
-rw-r--r-- | unicorn_mode/samples/c/harness.c | 2 |
19 files changed, 222 insertions, 109 deletions
diff --git a/Makefile b/Makefile index 1e8a894b..b9d4bf5a 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) override CFLAGS += -Wall -g -Wno-pointer-sign -I include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ - -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function + -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) @@ -200,7 +200,14 @@ help: @echo "help: shows these build options :-)" @echo "==========================================" @echo "Recommended: \"distrib\" or \"source-only\", then \"install\"" - + @echo + @echo Known build environment options: + @echo "==========================================" + @echo STATIC - compile AFL++ static + @echo ASAN_BUILD - compiles with memory sanitizer for debug purposes + @echo AFL_NO_X86 - if compiling on non-intel/amd platforms + @echo "==========================================" + @echo e.g.: make ASAN_BUILD=1 ifndef AFL_NO_X86 @@ -321,7 +328,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_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_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 ) ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr @rm -f test-instr diff --git a/README.md b/README.md index 8c759779..ec1d5ba9 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ $ make source-only ``` is what you should choose. -These build options exist: +These build targets exist: * all: just the main afl++ binaries * binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa @@ -128,6 +128,15 @@ afl++ binaries by passing the STATIC=1 argument to make: $ make all STATIC=1 ``` +These build options exist: + +* STATIC - compile AFL++ static +* ASAN_BUILD - compiles with memory sanitizer for debug purposes +* AFL_NO_X86 - if compiling on non-intel/amd platforms + +e.g.: make ASAN_BUILD=1 + + Note that afl++ is faster and better the newer the compilers used are. Hence gcc-9 and especially llvm-9 should be the compilers of choice. If your distribution does not have them, you can use the Dockerfile: diff --git a/afl-cmin b/afl-cmin index 44a84735..9570bc93 100755 --- a/afl-cmin +++ b/afl-cmin @@ -287,7 +287,8 @@ BEGIN { system("rm -rf "trace_dir" 2>/dev/null"); system("rm "out_dir"/id[:_]* 2>/dev/null") - if (0 == system( "test -d "out_dir" -a -e "out_dir"/*" )) { + "ls "out_dir"/* 2>/dev/null | wc -l" | getline noofentries + if (0 == system( "test -d "out_dir" -a "noofentries" -gt 0" )) { print "[-] Error: directory '"out_dir"' exists and is not empty - delete it first." > "/dev/stderr" exit 1 } @@ -318,7 +319,7 @@ BEGIN { print "[-] Error: can't find 'afl-showmap' - please set AFL_PATH." > "/dev/stderr" exit 1 } - + # get list of input filenames sorted by size i = 0 # yuck, gnu stat is option incompatible to bsd stat @@ -330,8 +331,10 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} \\; | sort -n | cut -d' ' -f2-" + cmdline = "cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} \\; | sort -k1n -k2r" + cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format") | sort -k1n -k2r" while (cmdline | getline) { + sub(/^[0-9]+ (\.\/)?/,"",$0) infilesSmallToBig[i++] = $0 } in_count = i @@ -390,10 +393,10 @@ BEGIN { cur = 0; if (!stdin_file) { - printf " Processing "in_count" files (forkserver mode)..." + print " Processing "in_count" files (forkserver mode)..." system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string) } else { - printf " Processing "in_count" files (forkserver mode)..." + print " Processing "in_count" files (forkserver mode)..." system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string" </dev/null") } @@ -410,6 +413,9 @@ BEGIN { out_count = 0 tuple_count = 0 + # from rare to frequent new tuples + # get the best (smallest) file for it + # and copy it while (cur < in_count) { fn = infilesSmallToBig[cur] ++cur @@ -426,17 +432,54 @@ BEGIN { if (! (key in best_file)) { # this is the best file for this key best_file[key] = fn - # copy file unless already done - if (! (fn in file_already_copied)) { - system(cp_tool" "in_dir"/"fn" "out_dir"/"fn) - file_already_copied[fn] = "" - ++out_count - } +#printf "BEST_FILE[%d]=\"%s\"\n",key,fn | "sort -t'[' -k2 > "trace_dir"/.candidate_script" } +#printf "%d %s\n",key,fn > trace_dir"/.candidate_list" } close(tracefile_path) } + print "" + + # sort keys + sortedKeys = trace_dir"/.all_uniq" + sortKeysCmd = "sort -k1n > "sortedKeys + for (key in key_count) { + printf "%7d %s\n",key_count[key],key | sortKeysCmd + } + close(sortKeysCmd) + + # iterate over keys from rare to frequent and + # copy best file + while ((getline < sortedKeys) > 0) { + + # split + nrFields = split($0, field, / +/) +#print nrFields" Felder: '"field[0]"', '"field[1]"', '"field[2]"', '"field[3]"'" + key = field[nrFields] + ++tcnt; + printf "\r Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." + if (key in keyAlreadyKnown) { + continue + } + + fn = best_file[key] + # gather all tuples from the best file for this key + tracedfn = trace_dir"/"fn + while ((getline < tracedfn) > 0) { + keyAlreadyKnown[$0] = "" + } + close(tracedfn) + + # copy file unless already done + if (! (fn in file_already_copied)) { + system(cp_tool" "in_dir"/"fn" "out_dir"/"fn) + file_already_copied[fn] = "" + ++out_count + #printf "tuple nr %d (%d cnt=%d) -> %s\n",tcnt,key,key_count[key],fn > trace_dir"/.log" + } + } + close(sortedKeys) print "" print "[+] Found "tuple_count" unique tuples across "in_count" files." diff --git a/afl-cmin.bash b/afl-cmin.bash index 1dd782d8..94c02fda 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -435,7 +435,7 @@ touch "$TRACE_DIR/.already_have" while read -r cnt tuple; do CUR=$((CUR+1)) - printf "\\r Processing tuple $CUR/$TUPLE_COUNT... " + printf "\\r Processing tuple $CUR/$TUPLE_COUNT with count $cnt... " # If we already have this tuple, skip it. @@ -443,6 +443,7 @@ while read -r cnt tuple; do FN=${BEST_FILE[tuple]} +# echo "tuple nr $CUR ($tuple cnt=$cnt) -> $FN" >> "$TRACE_DIR/.log" $CP_TOOL "$IN_DIR/$FN" "$OUT_DIR/$FN" if [ "$((CUR % 5))" = "0" ]; then diff --git a/docs/Changelog.md b/docs/Changelog.md index 4ee83ecd..5d781545 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - use -march=native if available - most tools now check for mistyped environment variables + - gcc 10 is now supported - the memory safety checks are now disabled for a little more speed during fuzzing (only affects creating queue entries), can be toggled in config.h - afl-fuzz: @@ -26,6 +27,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. (which is pointless) to total execs per second - bugfix for dictionary insert stage count (fix via Google repo PR) - added warning if -M is used together with custom mutators with _ONLY option + - AFL_TMPDIR checks are now later and better explained if they fail - llvm_mode InsTrim: no pointless instrumentation of 1 block functions - afl-clang-fast: - show in the help output for which llvm version it was compiled for @@ -37,6 +39,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - experimental support for undefined behaviour sanitizer UBSAN (set AFL_USE_UBSAN=1) - the instrumentation summary output now also lists activated sanitizers + - afl-as: added isatty(2) check back in + - added AFL_DEBUG (for upcoming merge) - qemu_mode: - persistent mode is now also available for arm and aarch64 - CmpLog instrumentation for QEMU (-c afl-fuzz command line option) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index ada08b69..5764e30b 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -141,8 +141,7 @@ static inline void* DFL_ck_realloc(void* orig, u32 size) { static inline void* DFL_ck_realloc_block(void* orig, u32 size) { - if (orig) - size += ALLOC_BLK_INC; + if (orig) size += ALLOC_BLK_INC; return DFL_ck_realloc(orig, size); diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 0ec68ab5..683b6bee 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -494,7 +494,9 @@ int main(int argc, char** argv, char** envp) { exit(1); - } else if (isatty(2) && !getenv("AFL_QUIET")) { + } else if ((isatty(2) && !getenv("AFL_QUIET")) || + + getenv("AFL_DEBUG") != NULL) { #ifdef USE_TRACE_PC SAYF(cCYA "afl-clang-fast" VERSION cRST diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 555510cc..133c64b4 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -145,11 +145,11 @@ bool AFLCoverage::runOnModule(Module &M) { char be_quiet = 0; - if (isatty(2) && !getenv("AFL_QUIET")) { + if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { SAYF(cCYA "afl-llvm-pass" VERSION cRST " by <lszekeres@google.com>\n"); - } else if (getenv("AFL_QUIET")) + } else be_quiet = 1; diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index e1332a9d..94b256f7 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -496,7 +496,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, bool CompareTransform::runOnModule(Module &M) { - if (getenv("AFL_QUIET") == NULL) + if (isatty(2) && getenv("AFL_QUIET") == NULL) llvm::errs() << "Running compare-transform-pass by laf.intel@gmail.com, " "extended by heiko@hexco.de\n"; transformCmps(M, true, true, true, true, true); diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index e16993d6..fe021071 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -1243,13 +1243,16 @@ bool SplitComparesTransform::runOnModule(Module &M) { simplifyIntSignedness(M); - if (getenv("AFL_QUIET") == NULL) + if (isatty(2) && getenv("AFL_QUIET") == NULL) { + errs() << "Split-compare-pass by laf.intel@gmail.com, extended by " "heiko@hexco.de\n"; - if (enableFPSplit) - errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M) - << " FP comparisons splitted\n"; + if (enableFPSplit) + errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M) + << " FP comparisons splitted\n"; + + } switch (bitw) { diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc index 9101dc26..d2ba28cb 100644 --- a/llvm_mode/split-switches-pass.so.cc +++ b/llvm_mode/split-switches-pass.so.cc @@ -491,7 +491,8 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { * less, don't bother with the code below. */ if (!SI->getNumCases() || bitw <= 8) { - if (getenv("AFL_QUIET") == NULL) errs() << "skip trivial switch..\n"; + if (isatty(2) && getenv("AFL_QUIET") == NULL) + errs() << "skip trivial switch..\n"; continue; } @@ -556,7 +557,7 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { bool SplitSwitchesTransform::runOnModule(Module &M) { - if (getenv("AFL_QUIET") == NULL) + if (isatty(2) && getenv("AFL_QUIET") == NULL) llvm::errs() << "Running split-switches-pass by laf.intel@gmail.com\n"; splitSwitches(M); verifyModule(M); diff --git a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h index 6339d41c..2bb0ac9e 100644 --- a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h +++ b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h @@ -35,9 +35,9 @@ #include "tcg.h" void HELPER(afl_entry_routine)(CPUArchState *env) { - + afl_forkserver(ENV_GET_CPU(env)); - + } void HELPER(afl_compcov_16)(target_ulong cur_loc, target_ulong arg1, diff --git a/src/afl-as.c b/src/afl-as.c index c116ac10..72a27cd2 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -510,7 +510,7 @@ int main(int argc, char** argv) { clang_mode = !!getenv(CLANG_ENV_VAR); - if (!getenv("AFL_QUIET")) { + if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n"); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index bafb1d63..2176c5cf 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -603,9 +603,11 @@ void perform_dry_run(char** argv) { "binary. Also,\n" " if you are using ASAN, see %s/notes_for_asan.md.\n\n" - " - In QEMU persistent mode the selected address(es) for the loop are not\n" + " - In QEMU persistent mode the selected address(es) for the " + "loop are not\n" " properly cleaning up variables and memory. Try adding\n" - " AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in the binary.\n\n" + " AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in " + "the binary.\n\n" MSG_FORK_ON_APPLE @@ -628,9 +630,11 @@ void perform_dry_run(char** argv) { "interesting\n" " inputs - but not ones that cause an outright crash.\n\n" - " - In QEMU persistent mode the selected address(es) for the loop are not\n" + " - In QEMU persistent mode the selected address(es) for the " + "loop are not\n" " properly cleaning up variables and memory. Try adding\n" - " AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in the binary.\n\n" + " AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in " + "the binary.\n\n" MSG_FORK_ON_APPLE diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index eeb660f7..a9a6db97 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -113,7 +113,8 @@ static void usage(u8* argv0) { " pacemaker mode (minutes of no new paths, 0 = " "immediately).\n" " a recommended value is 10-60. see docs/README.MOpt\n" - " -c program - enable CmpLog by specifying a binary compiled for it.\n" + " -c program - enable CmpLog by specifying a binary compiled for " + "it.\n" " if using QEMU, just use -c 0.\n\n" "Fuzzing behavior settings:\n" @@ -654,25 +655,6 @@ int main(int argc, char** argv, char** envp) { if (!strcmp(in_dir, out_dir)) FATAL("Input and output directories can't be the same"); - if ((tmp_dir = getenv("AFL_TMPDIR")) != NULL) { - - char tmpfile[file_extension - ? strlen(tmp_dir) + 1 + 10 + 1 + strlen(file_extension) + 1 - : strlen(tmp_dir) + 1 + 10 + 1]; - if (file_extension) { - sprintf(tmpfile, "%s/.cur_input.%s", tmp_dir, file_extension); - } else { - sprintf(tmpfile, "%s/.cur_input", tmp_dir); - } - if (access(tmpfile, F_OK) != - -1) // there is still a race condition here, but well ... - FATAL("AFL_TMPDIR already has an existing temporary input file: %s", - tmpfile); - - } else - - tmp_dir = out_dir; - if (dumb_mode) { if (crash_mode) FATAL("-C and -n are mutually exclusive"); @@ -846,6 +828,32 @@ int main(int argc, char** argv, char** envp) { if (!timeout_given) find_timeout(); + if ((tmp_dir = getenv("AFL_TMPDIR")) != NULL && !in_place_resume) { + + char tmpfile[file_extension + ? strlen(tmp_dir) + 1 + 10 + 1 + strlen(file_extension) + 1 + : strlen(tmp_dir) + 1 + 10 + 1]; + if (file_extension) { + + sprintf(tmpfile, "%s/.cur_input.%s", tmp_dir, file_extension); + + } else { + + sprintf(tmpfile, "%s/.cur_input", tmp_dir); + + } + + if (access(tmpfile, F_OK) != + -1) // there is still a race condition here, but well ... + FATAL( + "AFL_TMPDIR already has an existing temporary input file: %s - if " + "this is not from another instance, then just remove the file.", + tmpfile); + + } else + + tmp_dir = out_dir; + /* If we don't have a file name chosen yet, use a safe default. */ if (!out_file) { @@ -883,11 +891,13 @@ int main(int argc, char** argv, char** envp) { if (!out_file) setup_stdio_file(); if (cmplog_binary) { + if (unicorn_mode) FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry"); - if (!qemu_mode) - check_binary(cmplog_binary); + if (!qemu_mode) check_binary(cmplog_binary); + } + check_binary(argv[optind]); start_time = get_cur_time(); diff --git a/src/afl-gcc.c b/src/afl-gcc.c index ff53cc8d..5baec062 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -342,31 +342,30 @@ static void edit_params(u32 argc, char** argv) { int main(int argc, char** argv) { - char *env_info = - "Environment variables used by afl-gcc:\n" - "AFL_CC: path to the C compiler to use\n" - "AFL_CXX: path to the C++ compiler to use\n" - "AFL_GCJ: path to the java compiler to use\n" - "AFL_PATH: path to the instrumenting assembler\n" - "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" - "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" - "AFL_QUIET: suppress verbose output\n" - "AFL_CAL_FAST: speed up the initial calibration\n" - "AFL_HARDEN: adds code hardening to catch memory bugs\n" - "AFL_USE_ASAN: activate address sanitizer\n" - "AFL_USE_MSAN: activate memory sanitizer\n" - "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" - - "\nEnvironment variables used by afl-as (called by afl-gcc):\n" - "AFL_AS: path to the assembler to use\n" - "TMPDIR: set the directory for temporary files of afl-as\n" - "TEMP: fall back path to directory for temporary files\n" - "TMP: fall back path to directory for temporary files\n" - "AFL_INST_RATIO: percentage of branches to instrument\n" - "AFL_QUIET: suppress verbose output\n" - "AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n" - "AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n" - ; + char* env_info = + "Environment variables used by afl-gcc:\n" + "AFL_CC: path to the C compiler to use\n" + "AFL_CXX: path to the C++ compiler to use\n" + "AFL_GCJ: path to the java compiler to use\n" + "AFL_PATH: path to the instrumenting assembler\n" + "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" + "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" + "AFL_QUIET: suppress verbose output\n" + "AFL_CAL_FAST: speed up the initial calibration\n" + "AFL_HARDEN: adds code hardening to catch memory bugs\n" + "AFL_USE_ASAN: activate address sanitizer\n" + "AFL_USE_MSAN: activate memory sanitizer\n" + "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" + + "\nEnvironment variables used by afl-as (called by afl-gcc):\n" + "AFL_AS: path to the assembler to use\n" + "TMPDIR: set the directory for temporary files of afl-as\n" + "TEMP: fall back path to directory for temporary files\n" + "TMP: fall back path to directory for temporary files\n" + "AFL_INST_RATIO: percentage of branches to instrument\n" + "AFL_QUIET: suppress verbose output\n" + "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) { @@ -380,7 +379,7 @@ int main(int argc, char** argv) { } - if (isatty(2) && !getenv("AFL_QUIET")) { + if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { SAYF(cCYA "afl-cc" VERSION cRST " by Michal Zalewski\n"); SAYF(cYEL "[!] " cBRI "NOTE: " cRST @@ -410,7 +409,8 @@ int main(int argc, char** argv) { "Setting AFL_HARDEN enables hardening optimizations in the compiled " "code.\n\n%s" - , BIN_PATH, BIN_PATH, env_info); + , + BIN_PATH, BIN_PATH, env_info); exit(1); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index a46645ab..cd4f2b7b 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -80,7 +80,7 @@ u8 *out_file, /* Trace output file */ *stdin_file, /* stdin file */ *in_dir, /* input folder */ *doc_path, /* Path to docs */ - *at_file; /* Substitution string for @@ */ + *at_file = NULL; /* Substitution string for @@ */ static u8* in_data; /* Input data */ @@ -901,11 +901,13 @@ int main(int argc, char** argv, char** envp) { if (in_dir) { if (at_file) PFATAL("Options -A and -i are mutually exclusive"); - at_file = "@@"; + detect_file_args(argv + optind, ""); - } + } else { - detect_file_args(argv + optind, ""); + detect_file_args(argv + optind, at_file); + + } for (i = optind; i < argc; i++) if (strcmp(argv[i], "@@") == 0) arg_offset = i; @@ -1014,12 +1016,12 @@ int main(int argc, char** argv, char** envp) { tcnt, highest, total, out_file); } - + if (stdin_file) { - + unlink(stdin_file); stdin_file = NULL; - + } exit(child_crashed * 2 + child_timed_out); diff --git a/test/test.sh b/test/test.sh index 5c4c7cb5..f3b5798f 100755 --- a/test/test.sh +++ b/test/test.sh @@ -65,6 +65,8 @@ unset AFL_PYTHON_MODULE unset AFL_PRELOAD unset LD_PRELOAD +rm -rf in in2 out + export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:symbolize=0 # on OpenBSD we need to work with llvm from /usr/local/bin @@ -87,7 +89,7 @@ RED="\\033[0;31m" YELLOW="\\033[1;93m" RESET="\\033[0m" -MEM_LIMIT=150 +MEM_LIMIT=none export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin @@ -172,7 +174,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc echo 000000000000000000000000 > in/in2 echo 111 > in/in3 mkdir -p in2 - ../afl-cmin -i in -o in2 -- ./test-instr.plain >/dev/null 2>&1 # why is afl-forkserver writing to stderr? + ../afl-cmin -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null 2>&1 # why is afl-forkserver writing to stderr? CNT=`ls in2/* 2>/dev/null | wc -l` case "$CNT" in *2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;; @@ -181,7 +183,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc ;; esac rm -f in2/in* - AFL_PATH=`pwd`/.. ../afl-cmin.bash -i in -o in2 -- ./test-instr.plain >/dev/null + AFL_PATH=`pwd`/.. ../afl-cmin.bash -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null CNT=`ls in2/* 2>/dev/null | wc -l` case "$CNT" in *2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;; @@ -189,7 +191,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 ;; esac - ../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 + ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'` test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase" test "$SIZE" = 1 || { @@ -230,7 +232,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { } || { $ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly" TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` - test "$TUPLES" -gt 3 -a "$TUPLES" -lt 6 && { + test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && { $ECHO "$GREEN[+] llvm_mode run reported $TUPLES instrumented locations which is fine" } || { $ECHO "$RED[!] llvm_mode instrumentation produces weird numbers: $TUPLES" @@ -288,7 +290,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { echo 000000000000000000000000 > in/in2 echo 111 > in/in3 mkdir -p in2 - ../afl-cmin -i in -o in2 -- ./test-instr.plain >/dev/null 2>&1 # why is afl-forkserver writing to stderr? + ../afl-cmin -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null 2>&1 # why is afl-forkserver writing to stderr? CNT=`ls in2/* 2>/dev/null | wc -l` case "$CNT" in *2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;; @@ -297,7 +299,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { ;; esac rm -f in2/in* - AFL_PATH=`pwd`/.. ../afl-cmin.bash -i in -o in2 -- ./test-instr.plain >/dev/null + AFL_PATH=`pwd`/.. ../afl-cmin.bash -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null CNT=`ls in2/* 2>/dev/null | wc -l` case "$CNT" in *2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;; @@ -305,7 +307,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 ;; esac - ../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 + ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'` test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase" test "$SIZE" = 1 || { @@ -332,7 +334,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 } rm -f test-compcov.instrim test.out - AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > /dev/null 2> test.out + AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > /dev/null 2> test.out test -e test-compcov.compcov && { grep -Eq " [3-9][0-9] location" test.out && { $ECHO "$GREEN[+] llvm_mode laf-intel/compcov feature works correctly" @@ -346,7 +348,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { } rm -f test-compcov.compcov test.out echo foobar.c > whitelist.txt - AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1 + AFL_DEBUG=1 AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1 test -e test-compcov && { grep -q "No instrumentation targets found" test.out && { $ECHO "$GREEN[+] llvm_mode whitelist feature works correctly" @@ -361,7 +363,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { rm -f test-compcov test.out whitelist.txt ../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { - echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && { + echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { $ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly" } || { $ECHO "$RED[!] llvm_mode persistent mode feature failed to work" @@ -470,7 +472,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { rm -f test-compcov test.out whitelist.txt ../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { - echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && { + echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { $ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly" } || { $ECHO "$RED[!] gcc_plugin persistent mode feature failed to work" @@ -568,7 +570,7 @@ test -e ../afl-qemu-trace && { echo 0 > in/in $ECHO "$GREY[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds" { - ../afl-fuzz -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/queue/id:000002* 2> /dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode" @@ -582,12 +584,35 @@ test -e ../afl-qemu-trace && { } rm -f errors + $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds" + { + { + export AFL_ENTRYPOINT=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//')` + $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(m test-instr | grep "T main") - $(file ./test-instr) + ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr + unset AFL_ENTRYPOINT + } >>errors 2>&1 + } >>errors 2>&1 + test -n "$( ls out/queue/id:000001* 2> /dev/null )" && { + $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode AFL_ENTRYPOINT" + RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'` + } || { + echo CUT------------------------------------------------------------------CUT + cat errors + echo CUT------------------------------------------------------------------CUT + $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode AFL_ENTRYPOINT" + CODE=1 + } + rm -f errors + test -e ../libcompcov.so && { $ECHO "$GREY[*] running afl-fuzz for qemu_mode libcompcov, this will take approx 10 seconds" { export AFL_PRELOAD=../libcompcov.so export AFL_COMPCOV_LEVEL=2 - ../afl-fuzz -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1 + unset AFL_PRELOAD + unset AFL_COMPCOV_LEVEL } >>errors 2>&1 test -n "$( ls out/queue/id:000002* 2> /dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode libcompcov" @@ -611,7 +636,8 @@ test -e ../afl-qemu-trace && { export AFL_QEMU_PERSISTENT_GPR=1 $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')" file test-instr - ../afl-fuzz -V10 -Q -i in -o out -- ./test-instr + ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr + unset AFL_QEMU_PERSISTENT_ADDR } >>errors 2>&1 test -n "$( ls out/queue/id:000002* 2> /dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with persistent qemu_mode" @@ -684,6 +710,7 @@ test -e ../afl-qemu-trace && { } CODE=1 } + unset LD_PRELOAD } || { echo CUT------------------------------------------------------------------CUT cat errors @@ -725,7 +752,7 @@ test -d ../unicorn_mode/unicornafl && { { $ECHO "$GREY[*] running afl-fuzz for unicorn_mode, this will take approx 25 seconds" { - ../afl-fuzz -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/queue/id:000002* 2> /dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode" @@ -744,7 +771,8 @@ test -d ../unicorn_mode/unicornafl && { $ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 35 seconds" { export AFL_COMPCOV_LEVEL=2 - ../afl-fuzz -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1 + unset AFL_COMPCOV_LEVEL } >>errors 2>&1 test -n "$( ls out/queue/id:000001* 2> /dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov" diff --git a/unicorn_mode/samples/c/harness.c b/unicorn_mode/samples/c/harness.c index 2eddeb8e..eb226f9a 100644 --- a/unicorn_mode/samples/c/harness.c +++ b/unicorn_mode/samples/c/harness.c @@ -203,7 +203,7 @@ int main(int argc, char **argv, char **envp) { // Setup the Stack mem_map_checked(uc, STACK_ADDRESS - STACK_SIZE, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE); uint64_t stack_val = STACK_ADDRESS; - printf("%lu", stack_val); + //printf("Stack at %lu\n", stack_val); uc_reg_write(uc, UC_X86_REG_RSP, &stack_val); // reserve some space for our input data |