diff options
32 files changed, 262 insertions, 450 deletions
diff --git a/Dockerfile b/Dockerfile index c8e09b66..dec952af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ RUN apt-get update && \ python3 python3-dev python3-setuptools python-is-python3 \ libtool libtool-bin \ libglib2.0-dev \ - wget vim jupp nano bash-completion \ + wget vim jupp nano bash-completion less \ apt-utils apt-transport-https ca-certificates gnupg dialog \ libpixman-1-dev \ gnuplot-nox \ @@ -56,7 +56,7 @@ WORKDIR /AFLplusplus RUN export REAL_CXX=g++-10 && export CC=gcc-10 && \ export CXX=g++-10 && make clean && \ - make distrib && make install && make clean + make distrib CFLAGS="-O3 -funroll-loops -D_FORTIFY_SOURCE=2" && make install && make clean RUN echo 'alias joe="jupp --wordwrap"' >> ~/.bashrc RUN echo 'export PS1="[afl++]$PS1"' >> ~/.bashrc diff --git a/GNUmakefile b/GNUmakefile index a1af1fd5..7b05a1d5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -307,7 +307,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu .PHONY: llvm llvm: - -$(MAKE) -f GNUmakefile.llvm + -$(MAKE) -j -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 @@ -414,7 +414,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86 @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) -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 @@ -579,11 +579,11 @@ deepclean: clean .PHONY: distrib distrib: all - -$(MAKE) -f GNUmakefile.llvm + -$(MAKE) -j -f GNUmakefile.llvm -$(MAKE) -f GNUmakefile.gcc_plugin $(MAKE) -C utils/libdislocator $(MAKE) -C utils/libtokencap - $(MAKE) -C utils/aflpp_driver + -$(MAKE) -C utils/aflpp_driver $(MAKE) -C utils/afl_network_proxy $(MAKE) -C utils/socket_fuzzing $(MAKE) -C utils/argv_fuzzing @@ -602,11 +602,11 @@ binary-only: test_shm test_python ready $(PROGS) .PHONY: source-only source-only: all - -$(MAKE) -f GNUmakefile.llvm + -$(MAKE) -j -f GNUmakefile.llvm -$(MAKE) -f GNUmakefile.gcc_plugin $(MAKE) -C utils/libdislocator $(MAKE) -C utils/libtokencap - $(MAKE) -C utils/aflpp_driver + -$(MAKE) -C utils/aflpp_driver %.8: % @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@ diff --git a/README.md b/README.md index a0e7a7e4..bea673f9 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,8 @@ With afl++ 3.0 we introduced changes that break some previous afl and afl++ behaviours and defaults: * 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. + only one compiler: afl-cc. All previous compilers now symlink to this. + All instrumentation source code is now in the `instrumentation/` folder. * The gcc_plugin was replaced with a new version submitted by AdaCore that supports more features. thank you! * qemu_mode got upgraded to QEMU 5.1, but to be able to build this a current @@ -41,8 +40,9 @@ behaviours and defaults: qemu_mode also got new options like snapshotting, instrumenting specific shared libraries, etc. Additionally QEMU 5.1 supports more CPU targets so this is really 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. + * When instrumenting targets, afl-cc will not supersede optimizations anymore + if any were given. This allows to fuzz targets as same as they are built + for debug or release. * afl-fuzz: * if neither -M or -S is specified, `-S default` is assumed, so more fuzzers can easily be added later @@ -88,7 +88,7 @@ behaviours and defaults: | Ngram prev_loc Coverage | | x(6) | | | | | Context Coverage | | x(6) | | | | | Auto Dictionary | | x(7) | | | | - | Snapshot LKM Support | | x | x | (x)(5) | | + | Snapshot LKM Support | | x(8) | x(8) | (x)(5) | | 1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8 2. GCC creates non-performant code, hence it is disabled in gcc_plugin @@ -97,6 +97,7 @@ behaviours and defaults: 5. upcoming, development in the branch 6. not compatible with LTO instrumentation and needs at least LLVM >= 4.1 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` + 8. the snapshot LKM is currently unmaintained due to too many kernel changes coming too fast :-( Among others, the following features and patches have been integrated: @@ -139,9 +140,6 @@ behaviours and defaults: ## Help wanted -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. @@ -206,7 +204,7 @@ These build targets exist: afl++ binaries by passing the STATIC=1 argument to make: ```shell -make all STATIC=1 +make STATIC=1 ``` These build options exist: @@ -283,9 +281,9 @@ anything below 9 is not recommended. | v +--------------------------------+ - | 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) + | gcc 5+ is available | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast) + +--------------------------------+ 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 | @@ -298,17 +296,17 @@ Clickable README links for the chosen compiler: * [LTO mode - afl-clang-lto](instrumentation/README.lto.md) * [LLVM mode - afl-clang-fast](instrumentation/README.llvm.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 + * GCC/CLANG mode (afl-gcc/afl-clang) have no README as they have 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++, + 1. 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 + afl-gcc-fast, afl-g++-fast (recommended!) + 2. using the environment variable AFL_CC_COMPILER with MODE + 3. passing --afl-MODE command line options to the compiler via CFLAGS/CXXFLAGS/CPPFLAGS MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN -(afl-g*-fast) or GCC (afl-gcc/afl-g++). +(afl-g*-fast) or GCC (afl-gcc/afl-g++) or CLANG(afl-clang/afl-clang++). Because no afl specific command-line options are accepted (beside the --afl-MODE command), the compile-time tools make fairly broad use of environment @@ -338,14 +336,14 @@ The following options are available when you instrument with LTO mode (afl-clang You can read more about this in [instrumentation/README.cmplog.md](instrumentation/README.cmplog.md) 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 +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 instrumented. - For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if either the clang - version is below 7 or the CLASSIC instrumentation is used - just put one + For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode other than + DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one filename or function per line (no directory information necessary for filenames9, and either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or** `export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per @@ -353,10 +351,6 @@ are interested in: unless requested (ALLOWLIST). **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++'s format is more flexible. There are many more options and modes available however these are most of the time less effective. See: @@ -696,7 +690,7 @@ Note that there are also a lot of tools out there that help fuzzing with afl++ (some might be deprecated or unsupported): Minimization of test cases: - * [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin that tries to speed up the process of the minimization of test case by using many CPU cores. + * [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin that tries to speed up the process of minimization of a single test case by using many CPU cores. * [afl-ddmin-mod](https://github.com/MarkusTeufelberger/afl-ddmin-mod) - a variation of afl-tmin based on the ddmin algorithm. * [halfempty](https://github.com/googleprojectzero/halfempty) - is a fast utility for minimizing test cases by Tavis Ormandy based on parallelization. @@ -751,7 +745,7 @@ the speed compared to qemu_mode (but slower than persistent mode). ### Unicorn For non-Linux binaries you can use afl++'s unicorn mode which can emulate -anything you want - for the price of speed and the user writing scripts. +anything you want - for the price of speed and user written scripts. See [unicorn_mode](unicorn_mode/README.md). It can be easily built by: @@ -763,16 +757,16 @@ cd unicorn_mode ### Shared libraries If the goal is to fuzz a dynamic library then there are two options available. -For both you need to write a small hardness that loads and calls the library. +For both you need to write a small harness that loads and calls the library. Faster is the frida solution: [utils/afl_frida/README.md](utils/afl_frida/README.md) Another, less precise and slower option is using ptrace with debugger interrupt -instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md) +instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md). ### More A more comprehensive description of these and other options can be found in -[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md) +[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md). ## Challenges of guided fuzzing diff --git a/docs/Changelog.md b/docs/Changelog.md index cf9bfbe1..71846535 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. ### Version ++3.01a (release) + - Mac OS ARM64 support - afl-fuzz - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) @@ -22,7 +23,11 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang + - warn on any _AFL and __AFL env var + - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was + already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ + - Updated utils/afl_frida to be 5% faster ### Version ++3.00c (release) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e2fb0344..a99e4991 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -174,6 +174,10 @@ struct queue_entry { u8 *trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ +#ifdef INTROSPECTION + u32 bitsmap_size; +#endif + double perf_score, /* performance score */ weight; @@ -586,7 +590,8 @@ typedef struct afl_state { u32 rand_cnt; /* Random number counter */ - u64 rand_seed[3]; +/* unsigned long rand_seed[3]; would also work */ + AFL_RAND_RETURN rand_seed[3]; s64 init_seed; u64 total_cal_us, /* Total calibration time (us) */ @@ -640,7 +645,7 @@ typedef struct afl_state { unsigned long long int last_avg_exec_update; u32 last_avg_execs; - float last_avg_execs_saved; + double last_avg_execs_saved; /* foreign sync */ #define FOREIGN_SYNCS_MAX 32 @@ -734,6 +739,7 @@ typedef struct afl_state { char mutation[8072]; char m_tmp[4096]; FILE *introspection_file; + u32 bitsmap_size; #endif } afl_state_t; diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 8a91d196..c914da5f 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -363,7 +363,8 @@ static inline void *DFL_ck_realloc(void *orig, u32 size) { if (orig) { - memcpy((char *)ret + ALLOC_OFF_HEAD, (char *)orig + ALLOC_OFF_HEAD, MIN(size, old_size)); + memcpy((char *)ret + ALLOC_OFF_HEAD, (char *)orig + ALLOC_OFF_HEAD, + MIN(size, old_size)); memset((char *)orig + ALLOC_OFF_HEAD, 0xFF, old_size); ALLOC_C1((char *)orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; diff --git a/src/afl-analyze.c b/src/afl-analyze.c index a6825ef6..6dac415b 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -103,11 +103,11 @@ static u32 map_size = MAP_SIZE; /* Classify tuple counts. This is a slow & naive version, but good enough here. */ -#define TIMES4(x) x,x,x,x -#define TIMES8(x) TIMES4(x),TIMES4(x) -#define TIMES16(x) TIMES8(x),TIMES8(x) -#define TIMES32(x) TIMES16(x),TIMES16(x) -#define TIMES64(x) TIMES32(x),TIMES32(x) +#define TIMES4(x) x, x, x, x +#define TIMES8(x) TIMES4(x), TIMES4(x) +#define TIMES16(x) TIMES8(x), TIMES8(x) +#define TIMES32(x) TIMES16(x), TIMES16(x) +#define TIMES64(x) TIMES32(x), TIMES32(x) static u8 count_class_lookup[256] = { [0] = 0, @@ -121,6 +121,7 @@ static u8 count_class_lookup[256] = { [128] = TIMES64(128) }; + #undef TIMES64 #undef TIMES32 #undef TIMES16 diff --git a/src/afl-cc.c b/src/afl-cc.c index 66f4860f..e6a6718e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -879,7 +879,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { #ifndef __ANDROID__ - if (compiler_mode != GCC) { + if (compiler_mode != GCC && compiler_mode != CLANG) { switch (bit_mode) { @@ -1030,9 +1030,9 @@ int main(int argc, char **argv, char **envp) { compiler_mode = GCC; - } else if (strncmp(callname, "afl-clang", 9) == 0 && + } else if (strcmp(callname, "afl-clang") == 0 || - strstr(callname, "fast") == NULL) { + strcmp(callname, "afl-clang++") == 0) { compiler_mode = CLANG; @@ -1076,13 +1076,13 @@ int main(int argc, char **argv, char **envp) { } - if (strncmp(callname, "afl-clang", 9) == 0 && - strstr(callname, "fast") == NULL) { + if (strcmp(callname, "afl-clang") == 0 || + strcmp(callname, "afl-clang++") == 0) { clang_mode = 1; compiler_mode = CLANG; - if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; } + if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; } } @@ -1364,17 +1364,17 @@ int main(int argc, char **argv, char **envp) { if (clang_mode) { - instrument_mode = CLANG; + instrument_mode = INSTRUMENT_CLANG; } else { - instrument_mode = GCC; + instrument_mode = INSTRUMENT_GCC; } } - if (compiler_mode == CLANG) { instrument_mode = CLANG; } + if (compiler_mode == CLANG) { instrument_mode = INSTRUMENT_CLANG; } if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { diff --git a/src/afl-common.c b/src/afl-common.c index 6dc8abe0..1928663d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -432,7 +432,9 @@ void check_environment_vars(char **envp) { char *env, *val; while ((env = envp[index++]) != NULL) { - if (strncmp(env, "ALF_", 4) == 0) { + if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 || + strncmp(env, "__ALF", 5) == 0 || strncmp(env, "_AFL", 4) == 0 || + strncmp(env, "__AFL", 5) == 0) { WARNF("Potentially mistyped AFL environment variable: %s", env); issue_detected = 1; @@ -628,6 +630,10 @@ u8 *stringify_float(u8 *buf, size_t len, double val) { snprintf(buf, len, "%0.01f", val); + } else if (unlikely(isnan(val) || isinf(val))) { + + strcpy(buf, "inf"); + } else { stringify_int(buf, len, (u64)val); @@ -787,9 +793,9 @@ u8 *u_stringify_float(u8 *buf, double val) { sprintf(buf, "%0.01f", val); - } else if (unlikely(isnan(val) || isfinite(val))) { + } else if (unlikely(isnan(val) || isinf(val))) { - strcpy(buf, "999.9"); + strcpy(buf, "infinite"); } else { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 1cb9b15f..62a8211c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -26,7 +26,7 @@ #include "afl-fuzz.h" #include <limits.h> #if !defined NAME_MAX -#define NAME_MAX _XOPEN_NAME_MAX + #define NAME_MAX _XOPEN_NAME_MAX #endif /* Write bitmap to file. The bitmap is useful mostly for the secret @@ -143,12 +143,14 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) { and replacing it with 0x80 or 0x01 depending on whether the tuple is hit or not. Called on every new crash or timeout, should be reasonably fast. */ -#define TIMES4(x) x,x,x,x -#define TIMES8(x) TIMES4(x),TIMES4(x) -#define TIMES16(x) TIMES8(x),TIMES8(x) -#define TIMES32(x) TIMES16(x),TIMES16(x) -#define TIMES64(x) TIMES32(x),TIMES32(x) -#define TIMES255(x) TIMES64(x),TIMES64(x),TIMES64(x),TIMES32(x),TIMES16(x),TIMES8(x),TIMES4(x),x,x,x +#define TIMES4(x) x, x, x, x +#define TIMES8(x) TIMES4(x), TIMES4(x) +#define TIMES16(x) TIMES8(x), TIMES8(x) +#define TIMES32(x) TIMES16(x), TIMES16(x) +#define TIMES64(x) TIMES32(x), TIMES32(x) +#define TIMES255(x) \ + TIMES64(x), TIMES64(x), TIMES64(x), TIMES32(x), TIMES16(x), TIMES8(x), \ + TIMES4(x), x, x, x const u8 simplify_lookup[256] = { [0] = 1, [1] = TIMES255(128) @@ -172,6 +174,7 @@ const u8 count_class_lookup8[256] = { [128] = TIMES64(128) }; + #undef TIMES255 #undef TIMES64 #undef TIMES32 diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ec937f29..dbffa4f9 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1667,20 +1667,21 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (afl->in_place_resume && rmdir(fn)) { - time_t cur_t = time(0); - struct tm *t = localtime(&cur_t); + time_t cur_t = time(0); + struct tm t; + localtime_r(&cur_t, &t); #ifndef SIMPLE_FILES - u8 *nfn = alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); + u8 *nfn = + alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); #else - u8 *nfn = alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t->tm_year + 1900, - t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, - t->tm_sec); + u8 *nfn = + alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); #endif /* ^!SIMPLE_FILES */ @@ -1698,20 +1699,21 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (afl->in_place_resume && rmdir(fn)) { - time_t cur_t = time(0); - struct tm *t = localtime(&cur_t); + time_t cur_t = time(0); + struct tm t; + localtime_r(&cur_t, &t); #ifndef SIMPLE_FILES - u8 *nfn = alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); + u8 *nfn = + alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); #else - u8 *nfn = alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t->tm_year + 1900, - t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, - t->tm_sec); + u8 *nfn = + alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 54afa17c..9a0d199e 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -45,25 +45,19 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { double compute_weight(afl_state_t *afl, struct queue_entry *q, double avg_exec_us, double avg_bitmap_size) { - u32 hits; + double weight = 1.0; if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { - hits = afl->n_fuzz[q->n_fuzz_entry]; - if (hits == 0) { hits = 1; } - - } else { - - hits = 1; + u32 hits = afl->n_fuzz[q->n_fuzz_entry]; + if (likely(hits)) { weight *= log10(hits) + 1; } } - double weight = 1.0; weight *= avg_exec_us / q->exec_us; - weight *= log(q->bitmap_size) / avg_bitmap_size; - weight /= log10(hits) + 1; + weight *= (log(q->bitmap_size) / avg_bitmap_size); - if (q->favored) weight *= 5; + if (unlikely(q->favored)) weight *= 5; return weight; @@ -97,34 +91,43 @@ void create_alias_table(afl_state_t *afl) { double avg_exec_us = 0.0; double avg_bitmap_size = 0.0; + u32 active = 0; + for (i = 0; i < n; i++) { struct queue_entry *q = afl->queue_buf[i]; - avg_exec_us += q->exec_us; - avg_bitmap_size += log(q->bitmap_size); + + // disabled entries might have timings and bitmap values + if (likely(!q->disabled)) { + + avg_exec_us += q->exec_us; + avg_bitmap_size += log(q->bitmap_size); + ++active; + + } } - avg_exec_us /= afl->queued_paths; - avg_bitmap_size /= afl->queued_paths; + avg_exec_us /= active; + avg_bitmap_size /= active; for (i = 0; i < n; i++) { struct queue_entry *q = afl->queue_buf[i]; - if (!q->disabled) { + if (likely(!q->disabled)) { q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size); q->perf_score = calculate_score(afl, q); + sum += q->weight; } - sum += q->weight; - } for (i = 0; i < n; i++) { + // weight is always 0 for disabled entries P[i] = (afl->queue_buf[i]->weight * n) / sum; } @@ -143,8 +146,8 @@ void create_alias_table(afl_state_t *afl) { for (i = 0; i < n; i++) { - struct queue_entry *q = afl->queue_buf[i]; - P[i] = (q->perf_score * n) / sum; + // perf_score is always 0 for disabled entries + P[i] = (afl->queue_buf[i]->perf_score * n) / sum; } @@ -190,11 +193,39 @@ void create_alias_table(afl_state_t *afl) { while (nS) afl->alias_probability[S[--nS]] = 1; +#ifdef INTROSPECTION + u8 fn[PATH_MAX]; + snprintf(fn, PATH_MAX, "%s/introspection_corpus.txt", afl->out_dir); + FILE *f = fopen(fn, "a"); + if (f) { + + for (i = 0; i < n; i++) { + + struct queue_entry *q = afl->queue_buf[i]; + fprintf( + f, + "entry=%u name=%s favored=%s variable=%s disabled=%s len=%u " + "exec_us=%u " + "bitmap_size=%u bitsmap_size=%u tops=%u weight=%f perf_score=%f\n", + i, q->fname, q->favored ? "true" : "false", + q->var_behavior ? "true" : "false", q->disabled ? "true" : "false", + q->len, (u32)q->exec_us, q->bitmap_size, q->bitsmap_size, q->tc_ref, + q->weight, q->perf_score); + + } + + fprintf(f, "\n"); + fclose(f); + + } + +#endif + /* - fprintf(stderr, " entry alias probability perf_score filename\n"); - for (u32 i = 0; i < n; ++i) - fprintf(stderr, " %5u %5u %11u %0.9f %s\n", i, afl->alias_table[i], - afl->alias_probability[i], afl->queue_buf[i]->perf_score, + fprintf(stderr, " entry alias probability perf_score weight + filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u + %0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i], + afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight, afl->queue_buf[i]->fname); */ @@ -398,6 +429,10 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { q->trace_mini = NULL; q->testcase_buf = NULL; +#ifdef INTROSPECTION + q->bitsmap_size = afl->bitsmap_size; +#endif + if (q->depth > afl->max_depth) { afl->max_depth = q->depth; } if (afl->queue_top) { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9a9ac33f..37d66aef 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -456,7 +456,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - if (SHAPE_BYTES(h->shape) >= 1 && *status != 1) { + /* avoid CodeQL warning on unsigned overflow */ + if (/* SHAPE_BYTES(h->shape) >= 1 && */ *status != 1) { if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 32cca579..339fb9c3 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -29,7 +29,7 @@ #include <signal.h> #include <limits.h> #if !defined NAME_MAX -#define NAME_MAX _XOPEN_NAME_MAX + #define NAME_MAX _XOPEN_NAME_MAX #endif #include "cmplog.h" @@ -380,6 +380,10 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } +#ifdef INTROSPECTION + if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size; +#endif + classify_counts(&afl->fsrv); cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (q->exec_cksum != cksum) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 7053572b..34456c0d 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -100,7 +100,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->cal_cycles_long = CAL_CYCLES_LONG; afl->hang_tmout = EXEC_TIMEOUT; afl->stats_update_freq = 1; - afl->stats_avg_exec = -1; + afl->stats_avg_exec = 0; afl->skip_deterministic = 1; #ifndef NO_SPLICING afl->use_splicing = 1; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 50e2ef15..1c211da6 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -120,8 +120,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, cur_time - afl->last_avg_exec_update >= 60000))) { afl->last_avg_execs_saved = - (float)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) / - (float)(cur_time - afl->last_avg_exec_update); + (double)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) / + (double)(cur_time - afl->last_avg_exec_update); afl->last_avg_execs = afl->fsrv.total_execs; afl->last_avg_exec_update = cur_time; @@ -369,30 +369,37 @@ void show_stats(afl_state_t *afl) { /* Calculate smoothed exec speed stats. */ - if (!afl->stats_last_execs) { + if (unlikely(!afl->stats_last_execs)) { - if (unlikely(cur_ms == afl->start_time)) --afl->start_time; + if (likely(cur_ms != afl->start_time)) { - afl->stats_avg_exec = - ((double)afl->fsrv.total_execs) * 1000 / (cur_ms - afl->start_time); + afl->stats_avg_exec = + ((double)afl->fsrv.total_execs) * 1000 / (cur_ms - afl->start_time); + + } } else { - double cur_avg = ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * - 1000 / (cur_ms - afl->stats_last_ms); + if (likely(cur_ms != afl->stats_last_ms)) { - /* If there is a dramatic (5x+) jump in speed, reset the indicator - more quickly. */ + double cur_avg = + ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 / + (cur_ms - afl->stats_last_ms); - if (cur_avg * 5 < afl->stats_avg_exec || - cur_avg / 5 > afl->stats_avg_exec) { + /* If there is a dramatic (5x+) jump in speed, reset the indicator + more quickly. */ - afl->stats_avg_exec = cur_avg; + if (cur_avg * 5 < afl->stats_avg_exec || + cur_avg / 5 > afl->stats_avg_exec) { - } + afl->stats_avg_exec = cur_avg; - afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + - cur_avg * (1.0 / AVG_SMOOTHING); + } + + afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + + cur_avg * (1.0 / AVG_SMOOTHING); + + } } diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 16feaa80..fccdb1a5 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -45,6 +45,10 @@ #include <dirent.h> +#ifdef __APPLE__ + #include <sys/syslimits.h> +#endif + #define MAX_PARAM_COUNT 4096 static u8 **ld_params; /* Parameters passed to the real 'ld' */ diff --git a/src/afl-showmap.c b/src/afl-showmap.c index b891632a..355b2dc3 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -98,17 +98,23 @@ static sharedmem_t * shm_fuzz; /* Classify tuple counts. Instead of mapping to individual bits, as in afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ -#define TIMES4(x) x,x,x,x -#define TIMES8(x) TIMES4(x),TIMES4(x) -#define TIMES16(x) TIMES8(x),TIMES8(x) -#define TIMES32(x) TIMES16(x),TIMES16(x) -#define TIMES64(x) TIMES32(x),TIMES32(x) -#define TIMES96(x) TIMES64(x),TIMES32(x) -#define TIMES128(x) TIMES64(x),TIMES64(x) +#define TIMES4(x) x, x, x, x +#define TIMES8(x) TIMES4(x), TIMES4(x) +#define TIMES16(x) TIMES8(x), TIMES8(x) +#define TIMES32(x) TIMES16(x), TIMES16(x) +#define TIMES64(x) TIMES32(x), TIMES32(x) +#define TIMES96(x) TIMES64(x), TIMES32(x) +#define TIMES128(x) TIMES64(x), TIMES64(x) static const u8 count_class_human[256] = { - [0] = 0, [1] = 1, [2] = 2, [3] = 3, - [4] = TIMES4(4), [8] = TIMES8(5),[16] = TIMES16(6),[32] = TIMES96(7), + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = TIMES4(4), + [8] = TIMES8(5), + [16] = TIMES16(6), + [32] = TIMES96(7), [128] = TIMES128(8) }; @@ -126,6 +132,7 @@ static const u8 count_class_binary[256] = { [128] = TIMES64(128) }; + #undef TIMES128 #undef TIMES96 #undef TIMES64 diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 6cb0d458..ed928c7c 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -98,11 +98,11 @@ static sharedmem_t * shm_fuzz; /* Classify tuple counts. This is a slow & naive version, but good enough here. */ -#define TIMES4(x) x,x,x,x -#define TIMES8(x) TIMES4(x),TIMES4(x) -#define TIMES16(x) TIMES8(x),TIMES8(x) -#define TIMES32(x) TIMES16(x),TIMES16(x) -#define TIMES64(x) TIMES32(x),TIMES32(x) +#define TIMES4(x) x, x, x, x +#define TIMES8(x) TIMES4(x), TIMES4(x) +#define TIMES16(x) TIMES8(x), TIMES8(x) +#define TIMES32(x) TIMES16(x), TIMES16(x) +#define TIMES64(x) TIMES32(x), TIMES32(x) static const u8 count_class_lookup[256] = { [0] = 0, @@ -116,6 +116,7 @@ static const u8 count_class_lookup[256] = { [128] = TIMES64(128) }; + #undef TIMES64 #undef TIMES32 #undef TIMES16 diff --git a/test/test-basic.sh b/test/test-basic.sh index 2ddf14af..79f90ea0 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -71,7 +71,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}" @@ -191,7 +191,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}" diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh index 2b09e753..9fe63ea3 100755 --- a/test/test-gcc-plugin.sh +++ b/test/test-gcc-plugin.sh @@ -67,7 +67,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { echo 0 > in/in $ECHO "$GREY[*] running afl-fuzz for gcc_plugin, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain.gccpi >>errors 2>&1 + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain.gccpi >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with gcc_plugin" diff --git a/test/test-llvm.sh b/test/test-llvm.sh index 09ade0c3..e5005d72 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -71,7 +71,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for llvm_mode, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode" @@ -164,7 +164,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { echo ZZZZ > in/in $ECHO "$GREY[*] running afl-fuzz with floating point splitting, this will take max. 30 seconds" { - AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -s 1 -V30 -m ${MEM_LIMIT} -i in -o out -- ./test-floatingpoint >>errors 2>&1 + AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -s 1 -V30 -m ${MEM_LIMIT} -i in -o out -D -- ./test-floatingpoint >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:* 2>/dev/null )" && { $ECHO "$GREEN[+] llvm_mode laf-intel floatingpoint splitting feature works correctly" diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 99025a06..f5537ed8 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -8cca4801 +768e6bb2 diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index f1306a06..9407de3f 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -150,6 +150,7 @@ if [ $? -eq 0 ]; then echo "[*] initializing unicornafl submodule" git submodule init || exit 1 git submodule update ./unicornafl 2>/dev/null # ignore errors + git submodule sync ./unicornafl 2>/dev/null # ignore errors else echo "[*] cloning unicornafl" test -d unicornafl || { diff --git a/utils/afl_frida/GNUmakefile b/utils/afl_frida/GNUmakefile index c154f3a4..8b56415b 100644 --- a/utils/afl_frida/GNUmakefile +++ b/utils/afl_frida/GNUmakefile @@ -11,7 +11,7 @@ libfrida-gum.a: @exit 1 afl-frida: afl-frida.c libfrida-gum.a - $(CC) -g $(OPT) -o afl-frida -Wno-format -Wno-pointer-sign -I. -fpermissive -fPIC afl-frida.c ../../afl-llvm-rt.o libfrida-gum.a -ldl -lresolv -pthread + $(CC) -g $(OPT) -o afl-frida -Wno-format -Wno-pointer-sign -I. -fpermissive -fPIC afl-frida.c ../../afl-compiler-rt.o libfrida-gum.a -ldl -lresolv -pthread libtestinstr.so: libtestinstr.c $(CC) -g -O0 -fPIC -o libtestinstr.so -shared libtestinstr.c diff --git a/utils/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c index 31bf8f25..b5b8196d 100644 --- a/utils/afl_frida/afl-frida.c +++ b/utils/afl_frida/afl-frida.c @@ -37,7 +37,10 @@ #include <sys/shm.h> #include <dlfcn.h> -#ifndef __APPLE__ +#ifdef __APPLE__ + #include <mach/mach.h> + #include <mach-o/dyld_images.h> +#else #include <sys/wait.h> #include <sys/personality.h> #endif @@ -61,55 +64,12 @@ static void *(*o_function)(uint8_t *, int); #include "frida-gum.h" -G_BEGIN_DECLS - -#define GUM_TYPE_FAKE_EVENT_SINK (gum_fake_event_sink_get_type()) -G_DECLARE_FINAL_TYPE(GumFakeEventSink, gum_fake_event_sink, GUM, - FAKE_EVENT_SINK, GObject) - -struct _GumFakeEventSink { - - GObject parent; - GumEventType mask; - -}; - -GumEventSink *gum_fake_event_sink_new(void); -void gum_fake_event_sink_reset(GumFakeEventSink *self); - -G_END_DECLS - -static void gum_fake_event_sink_iface_init(gpointer g_iface, - gpointer iface_data); -static void gum_fake_event_sink_finalize(GObject *obj); -static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink); -static void gum_fake_event_sink_process(GumEventSink *sink, const GumEvent *ev); void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, gpointer user_data); void afl_setup(void); void afl_start_forkserver(void); int __afl_persistent_loop(unsigned int max_cnt); -static void gum_fake_event_sink_class_init(GumFakeEventSinkClass *klass) { - - GObjectClass *object_class = G_OBJECT_CLASS(klass); - object_class->finalize = gum_fake_event_sink_finalize; - -} - -static void gum_fake_event_sink_iface_init(gpointer g_iface, - gpointer iface_data) { - - GumEventSinkInterface *iface = (GumEventSinkInterface *)g_iface; - iface->query_mask = gum_fake_event_sink_query_mask; - iface->process = gum_fake_event_sink_process; - -} - -G_DEFINE_TYPE_EXTENDED(GumFakeEventSink, gum_fake_event_sink, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE(GUM_TYPE_EVENT_SINK, - gum_fake_event_sink_iface_init)) - #include "../../config.h" // Shared memory fuzzing. @@ -183,230 +143,6 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, } -static void gum_fake_event_sink_init(GumFakeEventSink *self) { - -} - -static void gum_fake_event_sink_finalize(GObject *obj) { - - G_OBJECT_CLASS(gum_fake_event_sink_parent_class)->finalize(obj); - -} - -GumEventSink *gum_fake_event_sink_new(void) { - - GumFakeEventSink *sink; - sink = (GumFakeEventSink *)g_object_new(GUM_TYPE_FAKE_EVENT_SINK, NULL); - return GUM_EVENT_SINK(sink); - -} - -void gum_fake_event_sink_reset(GumFakeEventSink *self) { - -} - -static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink) { - - return 0; - -} - -typedef struct library_list { - - uint8_t *name; - uint64_t addr_start, addr_end; - -} library_list_t; - -#define MAX_LIB_COUNT 256 -static library_list_t liblist[MAX_LIB_COUNT]; -static u32 liblist_cnt; - -void read_library_information() { - -#if defined(__linux__) - FILE *f; - u8 buf[1024], *b, *m, *e, *n; - - if ((f = fopen("/proc/self/maps", "r")) == NULL) { - - fprintf(stderr, "Error: cannot open /proc/self/maps\n"); - exit(-1); - - } - - if (debug) fprintf(stderr, "Library list:\n"); - while (fgets(buf, sizeof(buf), f)) { - - if (strstr(buf, " r-x")) { - - if (liblist_cnt >= MAX_LIB_COUNT) { - - fprintf( - stderr, - "Warning: too many libraries to old, maximum count of %d reached\n", - liblist_cnt); - return; - - } - - b = buf; - m = index(buf, '-'); - e = index(buf, ' '); - if ((n = rindex(buf, '/')) == NULL) n = rindex(buf, ' '); - if (n && - ((*n >= '0' && *n <= '9') || *n == '[' || *n == '{' || *n == '(')) - n = NULL; - else - n++; - if (b && m && e && n && *n) { - - *m++ = 0; - *e = 0; - if (n[strlen(n) - 1] == '\n') n[strlen(n) - 1] = 0; - - if (rindex(n, '/') != NULL) { - - n = rindex(n, '/'); - n++; - - } - - liblist[liblist_cnt].name = strdup(n); - liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); - liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); - if (debug) - fprintf( - stderr, "%s:%llx (%llx-%llx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_end - 1); - liblist_cnt++; - - } - - } - - } - - if (debug) fprintf(stderr, "\n"); - -#elif defined(__FreeBSD__) - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; - char * buf, *start, *end; - size_t miblen = sizeof(mib) / sizeof(mib[0]); - size_t len; - - if (debug) fprintf(stderr, "Library list:\n"); - if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { return; } - - len = len * 4 / 3; - - buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); - if (buf == MAP_FAILED) { return; } - if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) { - - munmap(buf, len); - return; - - } - - start = buf; - end = buf + len; - - while (start < end) { - - struct kinfo_vmentry *region = (struct kinfo_vmentry *)start; - size_t size = region->kve_structsize; - - if (size == 0) { break; } - - if ((region->kve_protection & KVME_PROT_READ) && - !(region->kve_protection & KVME_PROT_EXEC)) { - - liblist[liblist_cnt].name = - region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; - liblist[liblist_cnt].addr_start = region->kve_start; - liblist[liblist_cnt].addr_end = region->kve_end; - - if (debug) { - - fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_end - 1); - - } - - liblist_cnt++; - - } - - start += size; - - } - -#endif - -} - -library_list_t *find_library(char *name) { - - char *filename = rindex(name, '/'); - - if (filename) - filename++; - else - filename = name; - -#if defined(__linux__) - u32 i; - for (i = 0; i < liblist_cnt; i++) - if (strcmp(liblist[i].name, filename) == 0) return &liblist[i]; -#elif defined(__APPLE__) && defined(__LP64__) - kern_return_t err; - static library_list_t lib; - - // get the list of all loaded modules from dyld - // the task_info mach API will get the address of the dyld all_image_info - // struct for the given task from which we can get the names and load - // addresses of all modules - task_dyld_info_data_t task_dyld_info; - mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; - err = task_info(mach_task_self(), TASK_DYLD_INFO, - (task_info_t)&task_dyld_info, &count); - - const struct dyld_all_image_infos *all_image_infos = - (const struct dyld_all_image_infos *)task_dyld_info.all_image_info_addr; - const struct dyld_image_info *image_infos = all_image_infos->infoArray; - - for (size_t i = 0; i < all_image_infos->infoArrayCount; i++) { - - const char * image_name = image_infos[i].imageFilePath; - mach_vm_address_t image_load_address = - (mach_vm_address_t)image_infos[i].imageLoadAddress; - if (strstr(image_name, name)) { - - lib.name = name; - lib.addr_start = (u64)image_load_address; - lib.addr_end = 0; - return &lib; - - } - - } - -#endif - - return NULL; - -} - -static void gum_fake_event_sink_process(GumEventSink * sink, - const GumEvent *ev) { - -} - /* Because this CAN be called more than once, it will return the LAST range */ static int enumerate_ranges(const GumRangeDetails *details, gpointer user_data) { @@ -445,16 +181,6 @@ int main() { // END STEP 2 - read_library_information(); - library_list_t *lib = find_library(TARGET_LIBRARY); - - if (lib == NULL) { - - fprintf(stderr, "Could not find target library\n"); - exit(-1); - - } - gum_init_embedded(); if (!gum_stalker_is_supported()) { @@ -465,27 +191,29 @@ int main() { GumStalker *stalker = gum_stalker_new(); - /* - This does not work here as we load a shared library. pretty sure this - would also be easily solvable with frida gum, but I already have all the - code I need from afl-untracer - - GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY); + GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY); GumMemoryRange code_range; gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges, &code_range); - guint64 code_start = code_range.base_address - base_address; - guint64 code_end = (code_range.base_address + code_range.size) - base_address; - range_t instr_range = {base_address, code_start, code_end}; - */ - range_t instr_range = {0, lib->addr_start, lib->addr_end}; + + guint64 code_start = code_range.base_address; + guint64 code_end = code_range.base_address + code_range.size; + range_t instr_range = {0, code_start, code_end}; + + printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n", + base_address, code_start, code_end); + if (!code_start || !code_end) { + + fprintf(stderr, "Error: no valid memory address found for %s\n", + TARGET_LIBRARY); + exit(-1); + + } GumStalkerTransformer *transformer = gum_stalker_transformer_make_from_callback(instr_basic_block, &instr_range, NULL); - GumEventSink *event_sink = gum_fake_event_sink_new(); - // to ensure that the signatures are not optimized out memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1); memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR, @@ -497,7 +225,7 @@ int main() { // - put that here // - gum_stalker_follow_me(stalker, transformer, event_sink); + gum_stalker_follow_me(stalker, transformer, NULL); while (__afl_persistent_loop(UINT32_MAX) != 0) { @@ -533,7 +261,6 @@ int main() { g_object_unref(stalker); g_object_unref(transformer); - g_object_unref(event_sink); gum_deinit_embedded(); return 0; diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 017aa72b..c6f5a76c 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -26,10 +26,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { EOF # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c -# Build afl-llvm-rt.o.c from the AFL distribution. -clang -c -w $AFL_HOME/instrumentation/afl-llvm-rt.o.c -# Build this file, link it with afl-llvm-rt.o.o and the target code. -clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o +# Build afl-compiler-rt.o.c from the AFL distribution. +clang -c -w $AFL_HOME/instrumentation/afl-compiler-rt.o.c +# Build this file, link it with afl-compiler-rt.o.o and the target code. +clang++ afl_driver.cpp test_fuzzer.o afl-compiler-rt.o.o # Run AFL: rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out diff --git a/utils/libdislocator/Makefile b/utils/libdislocator/Makefile index 2942c3c3..f0b4bb72 100644 --- a/utils/libdislocator/Makefile +++ b/utils/libdislocator/Makefile @@ -19,7 +19,7 @@ HELPER_PATH = $(PREFIX)/lib/afl VERSION = $(shell grep '^\#define VERSION ' ../../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2 -CFLAGS += -I ../../include/ -Wall -g -Wno-pointer-sign +override CFLAGS += -I ../../include/ -Wall -g -Wno-pointer-sign CFLAGS_ADD=$(USEHUGEPAGE:1=-DUSEHUGEPAGE) CFLAGS += $(CFLAGS_ADD) diff --git a/utils/libdislocator/README.md b/utils/libdislocator/README.md index 1785463e..d0340af0 100644 --- a/utils/libdislocator/README.md +++ b/utils/libdislocator/README.md @@ -1,6 +1,6 @@ # libdislocator, an abusive allocator - (See ../README.md for the general instruction manual.) + (See ../../README.md for the general instruction manual.) This is a companion library that can be used as a drop-in replacement for the libc allocator in the fuzzed binaries. It improves the odds of bumping into diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index 2324e390..c2b200cb 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -345,10 +345,10 @@ void free(void *ptr) { len = PTR_L(ptr); total_mem -= len; + u8 * ptr_ = ptr; if (align_allocations && (len & (ALLOC_ALIGN_SIZE - 1))) { - u8 * ptr_ = ptr; size_t rlen = (len & ~(ALLOC_ALIGN_SIZE - 1)) + ALLOC_ALIGN_SIZE; for (; len < rlen; ++len) if (ptr_[len] != TAIL_ALLOC_CANARY) @@ -359,11 +359,13 @@ void free(void *ptr) { /* Protect everything. Note that the extra page at the end is already set as PROT_NONE, so we don't need to touch that. */ - ptr -= PAGE_SIZE * PG_COUNT(len + 8) - len - 8; + ptr_ -= PAGE_SIZE * PG_COUNT(len + 8) - len - 8; - if (mprotect(ptr - 8, PG_COUNT(len + 8) * PAGE_SIZE, PROT_NONE)) + if (mprotect(ptr_ - 8, PG_COUNT(len + 8) * PAGE_SIZE, PROT_NONE)) FATAL("mprotect() failed when freeing memory"); + ptr = ptr_; + /* Keep the mapping; this is wasteful, but prevents ptr reuse. */ } diff --git a/utils/libtokencap/Makefile b/utils/libtokencap/Makefile index 8bbdc259..b81e1729 100644 --- a/utils/libtokencap/Makefile +++ b/utils/libtokencap/Makefile @@ -21,7 +21,7 @@ MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^\#define VERSION ' ../../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2 -CFLAGS += -I ../../include/ -Wall -g -Wno-pointer-sign +override CFLAGS += -I ../../include/ -Wall -g -Wno-pointer-sign UNAME_S =$(shell uname -s)# GNU make diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md index 13a440da..a39ed3a5 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -1,6 +1,11 @@ # strcmp() / memcmp() token capture library - (See ../README.md for the general instruction manual.) + NOTE: libtokencap is only recommended for binary-only targets or targets that + do not compile with afl-clang-fast/afl-clang-lto. + The afl-clang-fast AFL_LLVM_DICT2FILE feature is much better, afl-clang-lto + has that feature automatically integrated. + + (See ../../README.md for the general instruction manual.) This companion library allows you to instrument `strcmp()`, `memcmp()`, and related functions to automatically extract syntax tokens passed to any of |