aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-04-20 11:38:09 +0200
committerGitHub <noreply@github.com>2021-04-20 11:38:09 +0200
commit48cef3c74727407f82c44800d382737265fe65b4 (patch)
tree07338ec82703c20cc1f78a235ac3ad16e2465bf1 /src
parentf7179e44f6c46fef318b6413d9c00693c1af4602 (diff)
parent3b5fa3632b0e482b2915709d7fbec827e1d997b9 (diff)
downloadafl++-48cef3c74727407f82c44800d382737265fe65b4.tar.gz
Merge pull request #871 from AFLplusplus/dev
push to stable
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c67
-rw-r--r--src/afl-as.c7
-rw-r--r--src/afl-cc.c88
-rw-r--r--src/afl-common.c63
-rw-r--r--src/afl-forkserver.c124
-rw-r--r--src/afl-fuzz-init.c30
-rw-r--r--src/afl-fuzz-mutators.c8
-rw-r--r--src/afl-fuzz-one.c666
-rw-r--r--src/afl-fuzz-queue.c6
-rw-r--r--src/afl-fuzz-redqueen.c26
-rw-r--r--src/afl-fuzz-run.c1
-rw-r--r--src/afl-fuzz-state.c16
-rw-r--r--src/afl-fuzz-stats.c138
-rw-r--r--src/afl-fuzz.c158
-rw-r--r--src/afl-ld-lto.c27
-rw-r--r--src/afl-showmap.c101
-rw-r--r--src/afl-tmin.c66
17 files changed, 1074 insertions, 518 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index e106cd31..aabdbf1a 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -83,6 +83,7 @@ static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_timed_out; /* Child timed out? */
static u8 *target_path;
+static u8 frida_mode;
static u8 qemu_mode;
static u32 map_size = MAP_SIZE;
@@ -717,9 +718,11 @@ static void handle_stop_sig(int sig) {
/* Do basic preparations - persistent fds, filenames, etc. */
-static void set_up_environment(void) {
+static void set_up_environment(char **argv) {
- u8 *x;
+ u8 * x;
+ char *afl_preload;
+ char *frida_afl_preload = NULL;
dev_null_fd = open("/dev/null", O_RDWR);
if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@@ -781,6 +784,18 @@ static void set_up_environment(void) {
}
+ x = get_afl_env("LSAN_OPTIONS");
+
+ if (x) {
+
+ if (!strstr(x, "symbolize=0")) {
+
+ FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+ }
+
+ }
+
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
@@ -818,12 +833,38 @@ static void set_up_environment(void) {
"handle_sigfpe=0:"
"handle_sigill=0", 0);
+ setenv("LSAN_OPTIONS",
+ "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+ "fast_unwind_on_malloc=0:"
+ "symbolize=0:"
+ "print_suppressions=0",
+ 0);
+
if (get_afl_env("AFL_PRELOAD")) {
if (qemu_mode) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
+ } else if (frida_mode) {
+
+ afl_preload = getenv("AFL_PRELOAD");
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ if (afl_preload) {
+
+ frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+ } else {
+
+ frida_afl_preload = alloc_printf("%s", frida_binary);
+
+ }
+
+ ck_free(frida_binary);
+
+ setenv("LD_PRELOAD", frida_afl_preload, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
} else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -831,8 +872,17 @@ static void set_up_environment(void) {
}
+ } else if (frida_mode) {
+
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ setenv("LD_PRELOAD", frida_binary, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+ ck_free(frida_binary);
+
}
+ if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
}
/* Setup signal handlers, duh. */
@@ -872,6 +922,7 @@ static void usage(u8 *argv0) {
" -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%u MB)\n"
+ " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
@@ -914,7 +965,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n");
- while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) {
switch (opt) {
@@ -1008,6 +1059,14 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'O': /* FRIDA mode */
+
+ if (frida_mode) { FATAL("Multiple -O options not supported"); }
+
+ frida_mode = 1;
+
+ break;
+
case 'Q':
if (qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1062,7 +1121,7 @@ int main(int argc, char **argv_orig, char **envp) {
atexit(at_exit_handler);
setup_signal_handlers();
- set_up_environment();
+ set_up_environment(argv);
target_path = find_binary(argv[optind]);
detect_file_args(argv + optind, prog_in, &use_stdin);
diff --git a/src/afl-as.c b/src/afl-as.c
index aebd0ac8..7119d630 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -517,11 +517,12 @@ static void add_instrumentation(void) {
} else {
char modeline[100];
- snprintf(modeline, sizeof(modeline), "%s%s%s%s",
+ snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
- getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
+ getenv("AFL_USE_UBSAN") ? ", UBSAN" : "",
+ getenv("AFL_USE_LSAN") ? ", LSAN" : "");
OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", ins_lines,
use_64bit ? "64" : "32", modeline, inst_ratio);
@@ -585,7 +586,7 @@ int main(int argc, char **argv) {
"AFL_QUIET: suppress verbose output\n"
"AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n"
"AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n"
- "AFL_HARDEN, AFL_USE_ASAN, AFL_USE_MSAN, AFL_USE_UBSAN:\n"
+ "AFL_HARDEN, AFL_USE_ASAN, AFL_USE_MSAN, AFL_USE_UBSAN, AFL_USE_LSAN:\n"
" used in the instrumentation summary message\n",
argv[0]);
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 80fc0742..1f89bac5 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -66,7 +66,6 @@ enum {
INSTRUMENT_CLASSIC = 1,
INSTRUMENT_AFL = 1,
INSTRUMENT_PCGUARD = 2,
- INSTRUMENT_INSTRIM = 3,
INSTRUMENT_CFG = 3,
INSTRUMENT_LTO = 4,
INSTRUMENT_LLVMNATIVE = 5,
@@ -431,9 +430,6 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
- if (lto_mode && plusplus_mode)
- cc_params[cc_par_cnt++] = "-lc++"; // needed by fuzzbench, early
-
if (lto_mode && have_instr_env) {
cc_params[cc_par_cnt++] = "-Xclang";
@@ -588,9 +584,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
- #ifdef __ANDROID__
+ #if defined __ANDROID__ || ANDROID
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
- instrument_mode != INSTRUMENT_LLVMNATIVE;
+ instrument_mode = INSTRUMENT_LLVMNATIVE;
#else
if (have_instr_list) {
@@ -639,12 +635,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
- if (instrument_mode == INSTRUMENT_CFG)
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/libLLVMInsTrim.so", obj_path);
- else
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/afl-llvm-pass.so", obj_path);
+ cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
}
@@ -825,6 +816,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
+ if (getenv("AFL_USE_LSAN")) {
+
+ cc_params[cc_par_cnt++] = "-fsanitize=leak";
+ cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h";
+ cc_params[cc_par_cnt++] = "-D__AFL_LEAK_CHECK()=__lsan_do_leak_check()";
+
+ }
+
if (getenv("AFL_USE_CFISAN")) {
if (!lto_mode) {
@@ -1252,8 +1251,9 @@ int main(int argc, char **argv, char **envp) {
strcasecmp(ptr, "CFG") == 0) {
- compiler_mode = LLVM;
- instrument_mode = INSTRUMENT_CFG;
+ FATAL(
+ "InsTrim instrumentation was removed. Use a modern LLVM and "
+ "PCGUARD (default in afl-cc).\n");
} else if (strcasecmp(ptr, "AFL") == 0 ||
@@ -1319,10 +1319,9 @@ int main(int argc, char **argv, char **envp) {
if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
getenv("INSTRIM_LIB")) {
- if (instrument_mode == 0)
- instrument_mode = INSTRUMENT_CFG;
- else if (instrument_mode != INSTRUMENT_CFG)
- FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
+ FATAL(
+ "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD "
+ "(default in afl-cc).\n");
}
@@ -1409,17 +1408,9 @@ int main(int argc, char **argv, char **envp) {
if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
- if (instrument_mode == INSTRUMENT_LTO) {
-
- instrument_mode = INSTRUMENT_CFG;
- lto_mode = 1;
-
- } else if (!instrument_mode || instrument_mode == INSTRUMENT_CFG)
-
- instrument_mode = INSTRUMENT_CFG;
- else
- FATAL("main instrumentation mode already set with %s",
- instrument_mode_string[instrument_mode]);
+ FATAL(
+ "InsTrim instrumentation was removed. Use a modern LLVM and "
+ "PCGUARD (default in afl-cc).\n");
}
@@ -1428,7 +1419,7 @@ int main(int argc, char **argv, char **envp) {
lto_mode = 1;
if (!instrument_mode || instrument_mode == INSTRUMENT_LTO)
instrument_mode = INSTRUMENT_LTO;
- else if (instrument_mode != INSTRUMENT_CFG)
+ else
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
@@ -1456,9 +1447,11 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0) {
+ if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 ||
+ strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 ||
+ strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) {
- u8 *ptr3 = ptr2 + strlen("ctx-");
+ u8 *ptr3 = ptr2;
while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9'))
ptr3++;
@@ -1494,7 +1487,7 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr2, "ctx", strlen("ctx")) == 0) {
+ if (strcasecmp(ptr2, "ctx") == 0) {
instrument_opt_mode |= INSTRUMENT_OPT_CTX;
setenv("AFL_LLVM_CTX", "1", 1);
@@ -1642,11 +1635,6 @@ int main(int argc, char **argv, char **envp) {
" - CALLER\n"
" - CTX\n"
" - NGRAM-{2-16}\n"
- " INSTRIM no yes module yes yes "
- " yes\n"
- " - NORMAL\n"
- " - CALLER\n"
- " - NGRAM-{2-16}\n"
" [GCC_PLUGIN] gcc plugin: %s%s\n"
" CLASSIC DEFAULT no yes no no no "
"yes\n"
@@ -1697,9 +1685,7 @@ int main(int argc, char **argv, char **envp) {
" CTX: CLASSIC + full callee context "
"(instrumentation/README.ctx.md)\n"
" NGRAM-x: CLASSIC + previous path "
- "((instrumentation/README.ngram.md)\n"
- " INSTRIM: Dominator tree (for LLVM <= 6.0) "
- "(instrumentation/README.instrim.md)\n\n");
+ "((instrumentation/README.ngram.md)\n\n");
#undef NATIVE_MSG
@@ -1749,7 +1735,8 @@ int main(int argc, char **argv, char **envp) {
" AFL_USE_ASAN: activate address sanitizer\n"
" AFL_USE_CFISAN: activate control flow sanitizer\n"
" AFL_USE_MSAN: activate memory sanitizer\n"
- " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n");
+ " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
+ " AFL_USE_LSAN: activate leak-checker sanitizer\n");
if (have_gcc_plugin)
SAYF(
@@ -1791,19 +1778,16 @@ int main(int argc, char **argv, char **envp) {
" AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen "
"mutator)\n"
" AFL_LLVM_INSTRUMENT: set instrumentation mode:\n"
- " CLASSIC, INSTRIM, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, "
- "NGRAM-2 ..-16\n"
+ " CLASSIC, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, NGRAM-2 "
+ "..-16\n"
" You can also use the old environment variables instead:\n"
" AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
- " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
- " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed "
- "(option to INSTRIM)\n"
" AFL_LLVM_CALLER: use single context sensitive coverage (for "
"CLASSIC)\n"
" AFL_LLVM_CTX: use full context sensitive coverage (for "
"CLASSIC)\n"
" AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for "
- "CLASSIC & INSTRIM)\n");
+ "CLASSIC)\n");
#ifdef AFL_CLANG_FLTO
if (have_lto)
@@ -1951,11 +1935,7 @@ int main(int argc, char **argv, char **envp) {
"(requires LLVM 11 or higher)");
#endif
- if (instrument_opt_mode && instrument_mode == INSTRUMENT_CFG &&
- instrument_opt_mode & INSTRUMENT_OPT_CTX)
- FATAL("CFG instrumentation mode supports NGRAM and CALLER, but not CTX.");
- else if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
- // we will drop CFG/INSTRIM in the future so do not advertise
+ if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
FATAL(
"CALLER, CTX and NGRAM instrumentation options can only be used with "
"the LLVM CLASSIC instrumentation mode.");
@@ -2023,7 +2003,7 @@ int main(int argc, char **argv, char **envp) {
if (!be_quiet && cmplog_mode)
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) && !defined(ANDROID)
ptr = find_object("afl-compiler-rt.o", argv[0]);
if (!ptr) {
diff --git a/src/afl-common.c b/src/afl-common.c
index 37b4788c..0fb1462e 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -70,31 +70,26 @@ void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
*use_stdin = false;
- if (prog_in[0] != 0) { // not afl-showmap special case
+ /* Be sure that we're always using fully-qualified paths. */
- u8 *n_arg;
+ *aa_loc = 0;
- /* Be sure that we're always using fully-qualified paths. */
+ /* Construct a replacement argv value. */
+ u8 *n_arg;
- *aa_loc = 0;
+ if (prog_in[0] == '/') {
- /* Construct a replacement argv value. */
+ n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
- if (prog_in[0] == '/') {
-
- n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
-
- } else {
-
- n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
-
- }
+ } else {
- ck_free(argv[i]);
- argv[i] = n_arg;
+ n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
}
+ ck_free(argv[i]);
+ argv[i] = n_arg;
+
}
i++;
@@ -287,12 +282,19 @@ u8 *find_binary(u8 *fname) {
u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
- u8 *afl_path = NULL, *target_path, *own_copy;
+ u8 *afl_path = NULL, *target_path, *own_copy, *tmp;
+ int perm = X_OK;
+
+ if ((tmp = strrchr(fname, '.'))) {
+
+ if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
+
+ }
if ((afl_path = getenv("AFL_PATH"))) {
target_path = alloc_printf("%s/%s", afl_path, fname);
- if (!access(target_path, X_OK)) {
+ if (!access(target_path, perm)) {
return target_path;
@@ -316,7 +318,7 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
target_path = alloc_printf("%s/%s", own_copy, fname);
ck_free(own_copy);
- if (!access(target_path, X_OK)) {
+ if (!access(target_path, perm)) {
return target_path;
@@ -334,8 +336,17 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
}
- target_path = alloc_printf("%s/%s", BIN_PATH, fname);
- if (!access(target_path, X_OK)) {
+ if (perm == X_OK) {
+
+ target_path = alloc_printf("%s/%s", BIN_PATH, fname);
+
+ } else {
+
+ target_path = alloc_printf("%s/%s", AFL_PATH, fname);
+
+ }
+
+ if (!access(target_path, perm)) {
return target_path;
@@ -345,7 +356,15 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
}
- return find_binary(fname);
+ if (perm == X_OK) {
+
+ return find_binary(fname);
+
+ } else {
+
+ FATAL("Library '%s' not found", fname);
+
+ }
}
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c2d552cd..727e7f8d 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -42,6 +42,7 @@
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
+#include <limits.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
@@ -126,7 +127,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->last_run_timed_out = 0;
fsrv_to->init_child_func = from->init_child_func;
- // Note: do not copy ->add_extra_func
+ // Note: do not copy ->add_extra_func or ->persistent_record*
list_append(&fsrv_list, fsrv_to);
@@ -364,6 +365,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
+#ifdef AFL_PERSISTENT_RECORD
+ if (unlikely(fsrv->persistent_record)) {
+
+ fsrv->persistent_record_data =
+ (u8 **)ck_alloc(fsrv->persistent_record * sizeof(u8 *));
+ fsrv->persistent_record_len =
+ (u32 *)ck_alloc(fsrv->persistent_record * sizeof(u32));
+
+ if (!fsrv->persistent_record_data || !fsrv->persistent_record_len) {
+
+ FATAL("Unable to allocate memory for persistent replay.");
+
+ }
+
+ }
+
+#endif
+
if (fsrv->use_fauxsrv) {
/* TODO: Come up with some nice way to initialize this all */
@@ -483,7 +502,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); }
- /* Set sane defaults for ASAN if nothing else specified. */
+ /* Set sane defaults for ASAN if nothing else is specified. */
if (!getenv("ASAN_OPTIONS"))
setenv("ASAN_OPTIONS",
@@ -500,7 +519,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"handle_sigill=0",
1);
- /* Set sane defaults for UBSAN if nothing else specified. */
+ /* Set sane defaults for UBSAN if nothing else is specified. */
if (!getenv("UBSAN_OPTIONS"))
setenv("UBSAN_OPTIONS",
@@ -538,6 +557,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"handle_sigill=0",
1);
+ /* LSAN, too, does not support abort_on_error=1. */
+
+ if (!getenv("LSAN_OPTIONS"))
+ setenv("LSAN_OPTIONS",
+ "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+ "fast_unwind_on_malloc=0:"
+ "symbolize=0:"
+ "print_suppressions=0",
+ 1);
+
fsrv->init_child_func(fsrv, argv);
/* Use a distinctive bitmap signature to tell the parent about execv()
@@ -792,7 +821,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (fsrv->last_run_timed_out) {
- FATAL("Timeout while initializing fork server (adjusting -t may help)");
+ FATAL(
+ "Timeout while initializing fork server (setting "
+ "AFL_FORKSRV_INIT_TMOUT may help)");
}
@@ -1032,6 +1063,32 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
+#ifdef AFL_PERSISTENT_RECORD
+ if (unlikely(fsrv->persistent_record)) {
+
+ fsrv->persistent_record_len[fsrv->persistent_record_idx] = len;
+ fsrv->persistent_record_data[fsrv->persistent_record_idx] = afl_realloc(
+ (void **)&fsrv->persistent_record_data[fsrv->persistent_record_idx],
+ len);
+
+ if (unlikely(!fsrv->persistent_record_data[fsrv->persistent_record_idx])) {
+
+ FATAL("allocating replay memory failed.");
+
+ }
+
+ memcpy(fsrv->persistent_record_data[fsrv->persistent_record_idx], buf, len);
+
+ if (unlikely(++fsrv->persistent_record_idx >= fsrv->persistent_record)) {
+
+ fsrv->persistent_record_idx = 0;
+
+ }
+
+ }
+
+#endif
+
if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
if (unlikely(len > MAX_FILE)) len = MAX_FILE;
@@ -1146,6 +1203,26 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
+#ifdef AFL_PERSISTENT_RECORD
+ // end of persistent loop?
+ if (unlikely(fsrv->persistent_record &&
+ fsrv->persistent_record_pid != fsrv->child_pid)) {
+
+ fsrv->persistent_record_pid = fsrv->child_pid;
+ u32 idx, val;
+ if (unlikely(!fsrv->persistent_record_idx))
+ idx = fsrv->persistent_record - 1;
+ else
+ idx = fsrv->persistent_record_idx - 1;
+ val = fsrv->persistent_record_len[idx];
+ memset((void *)fsrv->persistent_record_len, 0,
+ fsrv->persistent_record * sizeof(u32));
+ fsrv->persistent_record_len[idx] = val;
+
+ }
+
+#endif
+
if (fsrv->child_pid <= 0) {
if (*stop_soon_p) { return 0; }
@@ -1238,12 +1315,47 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (unlikely(
/* A normal crash/abort */
(WIFSIGNALED(fsrv->child_status)) ||
- /* special handling for msan */
- (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+ /* special handling for msan and lsan */
+ (fsrv->uses_asan &&
+ (WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||
+ WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||
/* the custom crash_exitcode was returned by the target */
(fsrv->uses_crash_exitcode &&
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
+#ifdef AFL_PERSISTENT_RECORD
+ if (unlikely(fsrv->persistent_record)) {
+
+ char fn[PATH_MAX];
+ u32 i, writecnt = 0;
+ for (i = 0; i < fsrv->persistent_record; ++i) {
+
+ u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record;
+ u8 *data = fsrv->persistent_record_data[entry];
+ u32 len = fsrv->persistent_record_len[entry];
+ if (likely(len && data)) {
+
+ snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u",
+ fsrv->persistent_record_dir, fsrv->persistent_record_cnt,
+ writecnt++);
+ int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd >= 0) {
+
+ ck_write(fd, data, len, fn);
+ close(fd);
+
+ }
+
+ }
+
+ }
+
+ ++fsrv->persistent_record_cnt;
+
+ }
+
+#endif
+
/* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
fsrv->last_kill_signal =
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 70a49a6b..b6bfbc29 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -881,7 +881,7 @@ void perform_dry_run(afl_state_t *afl) {
case FSRV_RUN_TMOUT:
- if (afl->timeout_given) {
+ if (afl->timeout_given && !afl->afl_env.afl_exit_on_seed_issues) {
/* if we have a timeout but a timeout value was given then always
skip. The '+' meaning has been changed! */
@@ -1036,6 +1036,12 @@ void perform_dry_run(afl_state_t *afl) {
}
+ if (afl->afl_env.afl_exit_on_seed_issues) {
+
+ FATAL("As AFL_EXIT_ON_SEED_ISSUES is set, afl-fuzz exits.");
+
+ }
+
/* Remove from fuzzing queue but keep for splicing */
struct queue_entry *p = afl->queue;
@@ -2490,6 +2496,18 @@ void check_asan_opts(afl_state_t *afl) {
}
+ x = get_afl_env("LSAN_OPTIONS");
+
+ if (x) {
+
+ if (!strstr(x, "symbolize=0")) {
+
+ FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+ }
+
+ }
+
}
/* Handle stop signal (Ctrl-C, etc). */
@@ -2692,7 +2710,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
#endif /* ^!__APPLE__ */
- if (!afl->fsrv.qemu_mode && !afl->unicorn_mode &&
+ if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
!afl->non_instrumented_mode &&
!memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
@@ -2720,7 +2738,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
- if ((afl->fsrv.qemu_mode) &&
+ if ((afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST
@@ -2735,7 +2753,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
if (memmem(f_data, f_len, "__asan_init", 11) ||
- memmem(f_data, f_len, "__msan_init", 11)) {
+ memmem(f_data, f_len, "__msan_init", 11) ||
+ memmem(f_data, f_len, "__lsan_init", 11)) {
afl->fsrv.uses_asan = 1;
@@ -2757,7 +2776,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
- if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+ if (afl->fsrv.frida_mode ||
+ memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
OKF(cPIN "Deferred forkserver binary detected.");
setenv(DEFER_ENV_VAR, "1", 1);
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index a47b4f5f..c99d9a4d 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -397,8 +397,14 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (likely(retlen && cksum == q->exec_cksum)) {
- q->len = retlen;
+ if (afl_realloc((void **)&in_buf, retlen) == NULL) {
+
+ FATAL("can not allocate memory for trim");
+
+ }
+
memcpy(in_buf, retbuf, retlen);
+ q->len = retlen;
/* Let's save a clean trace, which will be needed by
update_bitmap_score once we're done with the trimming stuff. */
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 4e8154cd..d72d4145 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1997,16 +1997,19 @@ havoc_stage:
/* We essentially just do several thousand runs (depending on perf_score)
where we take the input file and make random stacked tweaks. */
+#define MAX_HAVOC_ENTRY 59 /* 55 to 60 */
+
u32 r_max, r;
- r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
+ r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
+ (afl->a_extras_cnt ? 4 : 0);
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
/* add expensive havoc cases here, they are activated after a full
cycle without finds happened */
- r_max++;
+ r_max += 4;
}
@@ -2015,7 +2018,7 @@ havoc_stage:
/* add expensive havoc cases here if there is no findings in the last 5s */
- r_max++;
+ r_max += 4;
}
@@ -2069,7 +2072,7 @@ havoc_stage:
switch ((r = rand_below(afl, r_max))) {
- case 0:
+ case 0 ... 3: {
/* Flip a single bit somewhere. Spooky! */
@@ -2080,7 +2083,9 @@ havoc_stage:
FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
break;
- case 1:
+ }
+
+ case 4 ... 7: {
/* Set byte to interesting value. */
@@ -2092,63 +2097,77 @@ havoc_stage:
interesting_8[rand_below(afl, sizeof(interesting_8))];
break;
- case 2:
+ }
+
+ case 8 ... 9: {
/* Set word to interesting value, randomly choosing endian. */
if (temp_len < 2) { break; }
- if (rand_below(afl, 2)) {
-
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
- interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+ interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
- } else {
+ break;
+
+ }
+
+ case 10 ... 11: {
+
+ /* Set word to interesting value, randomly choosing endian. */
+
+ if (temp_len < 2) { break; }
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
- interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
-
- }
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
+ interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
break;
- case 3:
+ }
+
+ case 12 ... 13: {
/* Set dword to interesting value, randomly choosing endian. */
if (temp_len < 4) { break; }
- if (rand_below(afl, 2)) {
-
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
- interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+ interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
- } else {
+ break;
+
+ }
+
+ case 14 ... 15: {
+
+ /* Set dword to interesting value, randomly choosing endian. */
+
+ if (temp_len < 4) { break; }
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
- interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
-
- }
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
+ interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
break;
- case 4:
+ }
+
+ case 16 ... 19: {
/* Randomly subtract from byte. */
@@ -2159,7 +2178,9 @@ havoc_stage:
out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
break;
- case 5:
+ }
+
+ case 20 ... 23: {
/* Randomly add to byte. */
@@ -2170,139 +2191,165 @@ havoc_stage:
out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
break;
- case 6:
+ }
- /* Randomly subtract from word, random endian. */
+ case 24 ... 25: {
- if (temp_len < 2) { break; }
+ /* Randomly subtract from word, little endian. */
- if (rand_below(afl, 2)) {
+ if (temp_len < 2) { break; }
- u32 pos = rand_below(afl, temp_len - 1);
+ u32 pos = rand_below(afl, temp_len - 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+ *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
- } else {
+ break;
- u32 pos = rand_below(afl, temp_len - 1);
- u16 num = 1 + rand_below(afl, ARITH_MAX);
+ }
+
+ case 26 ... 27: {
+
+ /* Randomly subtract from word, big endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
- num);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + pos) =
- SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
-
- }
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
break;
- case 7:
+ }
- /* Randomly add to word, random endian. */
+ case 28 ... 29: {
- if (temp_len < 2) { break; }
+ /* Randomly add to word, little endian. */
- if (rand_below(afl, 2)) {
+ if (temp_len < 2) { break; }
- u32 pos = rand_below(afl, temp_len - 1);
+ u32 pos = rand_below(afl, temp_len - 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+ *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
- } else {
+ break;
+
+ }
+
+ case 30 ... 31: {
- u32 pos = rand_below(afl, temp_len - 1);
- u16 num = 1 + rand_below(afl, ARITH_MAX);
+ /* Randomly add to word, big endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
- num);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u16 *)(out_buf + pos) =
- SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
-
- }
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
break;
- case 8:
+ }
- /* Randomly subtract from dword, random endian. */
+ case 32 ... 33: {
- if (temp_len < 4) { break; }
+ /* Randomly subtract from dword, little endian. */
- if (rand_below(afl, 2)) {
+ if (temp_len < 4) { break; }
- u32 pos = rand_below(afl, temp_len - 3);
+ u32 pos = rand_below(afl, temp_len - 3);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+ *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
- } else {
+ break;
+
+ }
+
+ case 34 ... 35: {
+
+ /* Randomly subtract from dword, big endian. */
+
+ if (temp_len < 4) { break; }
- u32 pos = rand_below(afl, temp_len - 3);
- u32 num = 1 + rand_below(afl, ARITH_MAX);
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
- num);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + pos) =
- SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
-
- }
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
break;
- case 9:
+ }
- /* Randomly add to dword, random endian. */
+ case 36 ... 37: {
- if (temp_len < 4) { break; }
+ /* Randomly add to dword, little endian. */
- if (rand_below(afl, 2)) {
+ if (temp_len < 4) { break; }
- u32 pos = rand_below(afl, temp_len - 3);
+ u32 pos = rand_below(afl, temp_len - 3);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+ *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
- } else {
+ break;
+
+ }
+
+ case 38 ... 39: {
- u32 pos = rand_below(afl, temp_len - 3);
- u32 num = 1 + rand_below(afl, ARITH_MAX);
+ /* Randomly add to dword, big endian. */
+
+ if (temp_len < 4) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
- num);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- *(u32 *)(out_buf + pos) =
- SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
-
- }
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
break;
- case 10:
+ }
+
+ case 40 ... 43: {
/* Just set a random byte to a random value. Because,
why not. We use XOR with 1-255 to eliminate the
@@ -2315,67 +2362,64 @@ havoc_stage:
out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
break;
- case 11 ... 12: {
-
- /* Delete bytes. We're making this a bit more likely
- than insertion (the next option) in hopes of keeping
- files reasonably small. */
-
- u32 del_from, del_len;
+ }
- if (temp_len < 2) { break; }
+ case 44 ... 46: {
- /* Don't delete too much. */
+ if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
- del_len = choose_block_len(afl, temp_len - 1);
+ /* Clone bytes. */
- del_from = rand_below(afl, temp_len - del_len + 1);
+ u32 clone_len = choose_block_len(afl, temp_len);
+ u32 clone_from = rand_below(afl, temp_len - clone_len + 1);
+ u32 clone_to = rand_below(afl, temp_len);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
- del_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
+ "clone", clone_from, clone_to, clone_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memmove(out_buf + del_from, out_buf + del_from + del_len,
- temp_len - del_from - del_len);
+ u8 *new_buf =
+ afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
- temp_len -= del_len;
+ /* Head */
- break;
+ memcpy(new_buf, out_buf, clone_to);
- }
+ /* Inserted part */
- case 13:
+ memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
- if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+ /* Tail */
+ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
- /* Clone bytes (75%) or insert a block of constant bytes (25%). */
+ out_buf = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
- u8 actually_clone = rand_below(afl, 4);
- u32 clone_from, clone_to, clone_len;
- u8 *new_buf;
+ }
- if (likely(actually_clone)) {
+ break;
- clone_len = choose_block_len(afl, temp_len);
- clone_from = rand_below(afl, temp_len - clone_len + 1);
+ }
- } else {
+ case 47: {
- clone_len = choose_block_len(afl, HAVOC_BLK_XL);
- clone_from = 0;
+ if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
- }
+ /* Insert a block of constant bytes (25%). */
- clone_to = rand_below(afl, temp_len);
+ u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
+ u32 clone_to = rand_below(afl, temp_len);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
- actually_clone ? "clone" : "insert", clone_from, clone_to,
- clone_len);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u",
+ "insert", clone_to, clone_len);
strcat(afl->mutation, afl->m_tmp);
#endif
- new_buf =
+ u8 *new_buf =
afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
@@ -2385,18 +2429,10 @@ havoc_stage:
/* Inserted part */
- if (likely(actually_clone)) {
-
- memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
-
- } else {
-
- memset(new_buf + clone_to,
- rand_below(afl, 2) ? rand_below(afl, 256)
- : out_buf[rand_below(afl, temp_len)],
- clone_len);
-
- }
+ memset(new_buf + clone_to,
+ rand_below(afl, 2) ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ clone_len);
/* Tail */
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
@@ -2410,47 +2446,79 @@ havoc_stage:
break;
- case 14: {
+ }
- /* Overwrite bytes with a randomly selected chunk (75%) or fixed
- bytes (25%). */
+ case 48 ... 50: {
- u32 copy_from, copy_to, copy_len;
+ /* Overwrite bytes with a randomly selected chunk bytes. */
if (temp_len < 2) { break; }
- copy_len = choose_block_len(afl, temp_len - 1);
+ u32 copy_len = choose_block_len(afl, temp_len - 1);
+ u32 copy_from = rand_below(afl, temp_len - copy_len + 1);
+ u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+ if (likely(copy_from != copy_to)) {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_COPY-%u-%u-%u",
+ copy_from, copy_to, copy_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+
+ }
+
+ break;
+
+ }
- copy_from = rand_below(afl, temp_len - copy_len + 1);
- copy_to = rand_below(afl, temp_len - copy_len + 1);
+ case 51: {
- if (likely(rand_below(afl, 4))) {
+ /* Overwrite bytes with fixed bytes. */
- if (likely(copy_from != copy_to)) {
+ if (temp_len < 2) { break; }
+
+ u32 copy_len = choose_block_len(afl, temp_len - 1);
+ u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " OVERWRITE_COPY-%u-%u-%u", copy_from, copy_to,
- copy_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_FIXED-%u-%u",
+ copy_to, copy_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+ memset(out_buf + copy_to,
+ rand_below(afl, 2) ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ copy_len);
- }
+ break;
- } else {
+ }
+
+ // increase from 4 up to 8?
+ case 52 ... MAX_HAVOC_ENTRY: {
+
+ /* Delete bytes. We're making this a bit more likely
+ than insertion (the next option) in hopes of keeping
+ files reasonably small. */
+
+ if (temp_len < 2) { break; }
+
+ /* Don't delete too much. */
+
+ u32 del_len = choose_block_len(afl, temp_len - 1);
+ u32 del_from = rand_below(afl, temp_len - del_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " OVERWRITE_FIXED-%u-%u-%u", copy_from, copy_to, copy_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
+ del_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memset(out_buf + copy_to,
- rand_below(afl, 2) ? rand_below(afl, 256)
- : out_buf[rand_below(afl, temp_len)],
- copy_len);
+ memmove(out_buf + del_from, out_buf + del_from + del_len,
+ temp_len - del_from - del_len);
- }
+ temp_len -= del_len;
break;
@@ -2458,93 +2526,101 @@ havoc_stage:
default:
- if (likely(r <= 16 && (afl->extras_cnt || afl->a_extras_cnt))) {
-
- /* Values 15 and 16 can be selected only if there are any extras
- present in the dictionaries. */
+ r -= (MAX_HAVOC_ENTRY + 1);
- if (r == 15) {
+ if (afl->extras_cnt) {
- /* Overwrite bytes with an extra. */
-
- if (!afl->extras_cnt ||
- (afl->a_extras_cnt && rand_below(afl, 2))) {
+ if (r < 2) {
- /* No user-specified extras or odds in our favor. Let's use an
- auto-detected one. */
+ /* Use the dictionary. */
- u32 use_extra = rand_below(afl, afl->a_extras_cnt);
- u32 extra_len = afl->a_extras[use_extra].len;
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
- if (extra_len > temp_len) { break; }
+ if (extra_len > temp_len) { break; }
- u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_OVERWRITE-%u-%u",
+ insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
- extra_len);
-
- } else {
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+ extra_len);
- /* No auto extras or odds in our favor. Use the dictionary. */
+ break;
- u32 use_extra = rand_below(afl, afl->extras_cnt);
- u32 extra_len = afl->extras[use_extra].len;
+ } else if (r < 4) {
- if (extra_len > temp_len) { break; }
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+ if (temp_len + extra_len >= MAX_FILE) { break; }
- u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+ u8 *ptr = afl->extras[use_extra].data;
+ u32 insert_at = rand_below(afl, temp_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
+ insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memcpy(out_buf + insert_at, afl->extras[use_extra].data,
- extra_len);
- }
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
+
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
+ temp_len += extra_len;
break;
- } else { // case 16
+ } else {
- u32 use_extra, extra_len,
- insert_at = rand_below(afl, temp_len + 1);
- u8 *ptr;
+ r -= 4;
- /* Insert an extra. Do the same dice-rolling stuff as for the
- previous case. */
+ }
- if (!afl->extras_cnt ||
- (afl->a_extras_cnt && rand_below(afl, 2))) {
+ }
- use_extra = rand_below(afl, afl->a_extras_cnt);
- extra_len = afl->a_extras[use_extra].len;
- ptr = afl->a_extras[use_extra].data;
-#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
-#endif
+ if (afl->a_extras_cnt) {
- } else {
+ if (r < 2) {
- use_extra = rand_below(afl, afl->extras_cnt);
- extra_len = afl->extras[use_extra].len;
- ptr = afl->extras[use_extra].data;
+ /* Use the dictionary. */
+
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+
+ if (extra_len > temp_len) { break; }
+
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
- insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
- }
+ break;
+
+ } else if (r < 4) {
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
if (temp_len + extra_len >= MAX_FILE) { break; }
+ u8 *ptr = afl->a_extras[use_extra].data;
+ u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
if (unlikely(!out_buf)) { PFATAL("alloc"); }
@@ -2554,103 +2630,97 @@ havoc_stage:
/* Inserted part */
memcpy(out_buf + insert_at, ptr, extra_len);
-
temp_len += extra_len;
break;
- }
+ } else {
- } else {
+ r -= 4;
- /*
- switch (r) {
+ }
- case 15: // fall through
- case 16:
- case 17: {*/
+ }
- /* Overwrite bytes with a randomly selected chunk from another
- testcase or insert that chunk. */
+ /* Splicing otherwise if we are still here.
+ Overwrite bytes with a randomly selected chunk from another
+ testcase or insert that chunk. */
- /* Pick a random queue entry and seek to it. */
+ /* Pick a random queue entry and seek to it. */
- u32 tid;
- do {
+ u32 tid;
+ do {
- tid = rand_below(afl, afl->queued_paths);
+ tid = rand_below(afl, afl->queued_paths);
- } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+ } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
- /* Get the testcase for splicing. */
- struct queue_entry *target = afl->queue_buf[tid];
- u32 new_len = target->len;
- u8 * new_buf = queue_testcase_get(afl, target);
+ /* Get the testcase for splicing. */
+ struct queue_entry *target = afl->queue_buf[tid];
+ u32 new_len = target->len;
+ u8 * new_buf = queue_testcase_get(afl, target);
- if ((temp_len >= 2 && rand_below(afl, 2)) ||
- temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+ if ((temp_len >= 2 && r % 2) || temp_len + HAVOC_BLK_XL >= MAX_FILE) {
- /* overwrite mode */
+ /* overwrite mode */
- u32 copy_from, copy_to, copy_len;
+ u32 copy_from, copy_to, copy_len;
- copy_len = choose_block_len(afl, new_len - 1);
- if (copy_len > temp_len) copy_len = temp_len;
+ copy_len = choose_block_len(afl, new_len - 1);
+ if (copy_len > temp_len) copy_len = temp_len;
- copy_from = rand_below(afl, new_len - copy_len + 1);
- copy_to = rand_below(afl, temp_len - copy_len + 1);
+ copy_from = rand_below(afl, new_len - copy_len + 1);
+ copy_to = rand_below(afl, temp_len - copy_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
- copy_len, target->fname);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
+ copy_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
- } else {
+ } else {
- /* insert mode */
+ /* insert mode */
- u32 clone_from, clone_to, clone_len;
+ u32 clone_from, clone_to, clone_len;
- clone_len = choose_block_len(afl, new_len);
- clone_from = rand_below(afl, new_len - clone_len + 1);
- clone_to = rand_below(afl, temp_len + 1);
+ clone_len = choose_block_len(afl, new_len);
+ clone_from = rand_below(afl, new_len - clone_len + 1);
+ clone_to = rand_below(afl, temp_len + 1);
- u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
- temp_len + clone_len + 1);
- if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+ u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+ temp_len + clone_len + 1);
+ if (unlikely(!temp_buf)) { PFATAL("alloc"); }
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
- clone_len, target->fname);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
+ clone_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- /* Head */
-
- memcpy(temp_buf, out_buf, clone_to);
-
- /* Inserted part */
+ /* Head */
- memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
+ memcpy(temp_buf, out_buf, clone_to);
- /* Tail */
- memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
- temp_len - clone_to);
+ /* Inserted part */
- out_buf = temp_buf;
- afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
- temp_len += clone_len;
+ memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
- }
+ /* Tail */
+ memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
- break;
+ out_buf = temp_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
}
- // end of default:
+ break;
+
+ // end of default
}
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index e5f51a6c..811e805c 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -478,7 +478,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
u8 *fname_orig = NULL;
/* At the initialization stage, queue_cur is NULL */
- if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
+ if (afl->queue_cur && !afl->syncing_party) {
+
+ fname_orig = afl->queue_cur->fname;
+
+ }
el->afl_custom_queue_new_entry(el->data, fname, fname_orig);
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 9bfbf95b..cf1e5ea5 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -437,7 +437,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
if (taint) {
- if (afl->colorize_success &&
+ if (afl->colorize_success && afl->cmplog_lvl < 3 &&
(len / positions == 1 && positions > CMPLOG_POSITIONS_MAX &&
afl->active_paths / afl->colorize_success > CMPLOG_CORPUS_PERCENT)) {
@@ -1749,6 +1749,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#endif
+#ifdef _DEBUG
+ if (o->v0 != orig_o->v0 || o->v1 != orig_o->v1)
+ fprintf(stderr, "key=%u idx=%u o0=%llu v0=%llu o1=%llu v1=%llu\n", key,
+ idx, orig_o->v0, o->v0, orig_o->v1, o->v1);
+#endif
+
// even for u128 and _ExtInt we do cmp_extend_encoding() because
// if we got here their own special trials failed and it might just be
// a cast from e.g. u64 to u128 from the input data.
@@ -2365,6 +2371,24 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
status = 0;
+#ifdef _DEBUG
+ int w;
+ fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx,
+ SHAPE_BYTES(h->shape));
+ for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ fprintf(stderr, "%02x", orig_o->v0[w]);
+ fprintf(stderr, " v0=");
+ for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ fprintf(stderr, "%02x", o->v0[w]);
+ fprintf(stderr, " o1=");
+ for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ fprintf(stderr, "%02x", orig_o->v1[w]);
+ fprintf(stderr, " v1=");
+ for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ fprintf(stderr, "%02x", o->v1[w]);
+ fprintf(stderr, "\n");
+#endif
+
if (unlikely(rtn_extend_encoding(
afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape),
idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 83133dad..832f17bb 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -712,6 +712,7 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
afl->last_sync_time = get_cur_time();
+ afl->last_sync_cycle = afl->queue_cycle;
}
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 0ddf8cf3..28d3339a 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->stats_update_freq = 1;
afl->stats_avg_exec = 0;
afl->skip_deterministic = 1;
- afl->cmplog_lvl = 1;
+ afl->cmplog_lvl = 2;
#ifndef NO_SPLICING
afl->use_splicing = 1;
#endif
@@ -292,6 +292,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_autoresume =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_PERSISTENT_RECORD",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_persistent_record =
+ get_afl_env(afl_environment_variables[i]);
+
} else if (!strncmp(env, "AFL_CYCLE_SCHEDULES",
afl_environment_variable_len)) {
@@ -299,6 +306,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->cycle_schedules = afl->afl_env.afl_cycle_schedules =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_EXIT_ON_SEED_ISSUES",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_exit_on_seed_issues =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_EXPAND_HAVOC_NOW",
afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 2c814d90..22c0cbd2 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -355,18 +355,18 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
double eps) {
- if (unlikely(afl->stop_soon) ||
- unlikely(afl->plot_prev_qp == afl->queued_paths &&
- afl->plot_prev_pf == afl->pending_favored &&
- afl->plot_prev_pnf == afl->pending_not_fuzzed &&
- afl->plot_prev_ce == afl->current_entry &&
- afl->plot_prev_qc == afl->queue_cycle &&
- afl->plot_prev_uc == afl->unique_crashes &&
- afl->plot_prev_uh == afl->unique_hangs &&
- afl->plot_prev_md == afl->max_depth &&
- afl->plot_prev_ed == afl->fsrv.total_execs) ||
- unlikely(!afl->queue_cycle) ||
- unlikely(get_cur_time() - afl->start_time <= 60)) {
+ if (unlikely(!afl->force_ui_update &&
+ (afl->stop_soon ||
+ (afl->plot_prev_qp == afl->queued_paths &&
+ afl->plot_prev_pf == afl->pending_favored &&
+ afl->plot_prev_pnf == afl->pending_not_fuzzed &&
+ afl->plot_prev_ce == afl->current_entry &&
+ afl->plot_prev_qc == afl->queue_cycle &&
+ afl->plot_prev_uc == afl->unique_crashes &&
+ afl->plot_prev_uh == afl->unique_hangs &&
+ afl->plot_prev_md == afl->max_depth &&
+ afl->plot_prev_ed == afl->fsrv.total_execs) ||
+ !afl->queue_cycle || get_cur_time() - afl->start_time <= 60))) {
return;
@@ -531,7 +531,8 @@ void show_stats(afl_state_t *afl) {
/* Roughly every minute, update fuzzer stats and save auto tokens. */
- if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
+ if (unlikely(afl->force_ui_update ||
+ cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000)) {
afl->stats_last_stats_ms = cur_ms;
write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
@@ -543,7 +544,8 @@ void show_stats(afl_state_t *afl) {
if (unlikely(afl->afl_env.afl_statsd)) {
- if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) {
+ if (unlikely(afl->force_ui_update && cur_ms - afl->statsd_last_send_ms >
+ STATSD_UPDATE_SEC * 1000)) {
/* reset counter, even if send failed. */
afl->statsd_last_send_ms = cur_ms;
@@ -555,7 +557,8 @@ void show_stats(afl_state_t *afl) {
/* Every now and then, write plot data. */
- if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
+ if (unlikely(afl->force_ui_update ||
+ cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) {
afl->stats_last_plot_ms = cur_ms;
maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
@@ -564,14 +567,14 @@ void show_stats(afl_state_t *afl) {
/* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
- if (!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
- !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) {
+ if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
+ !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) {
afl->stop_soon = 2;
}
- if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) {
+ if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) {
afl->stop_soon = 2;
@@ -583,7 +586,7 @@ void show_stats(afl_state_t *afl) {
/* If we haven't started doing things, bail out. */
- if (!afl->queue_cur) { return; }
+ if (unlikely(!afl->queue_cur)) { return; }
/* Compute some mildly useful bitmap stats. */
@@ -602,7 +605,7 @@ void show_stats(afl_state_t *afl) {
SAYF(TERM_HOME);
- if (afl->term_too_small) {
+ if (unlikely(afl->term_too_small)) {
SAYF(cBRI
"Your terminal is too small to display the UI.\n"
@@ -861,9 +864,13 @@ void show_stats(afl_state_t *afl) {
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
" path geometry " bSTG bH5 bH2 bVL "\n");
- if (afl->skip_deterministic) {
+ if (unlikely(afl->custom_only)) {
- strcpy(tmp, "n/a, n/a, n/a");
+ strcpy(tmp, "disabled (custom-mutator-only mode)");
+
+ } else if (likely(afl->skip_deterministic)) {
+
+ strcpy(tmp, "disabled (default, enable with -D)");
} else {
@@ -881,7 +888,7 @@ void show_stats(afl_state_t *afl) {
" levels : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->max_depth));
- if (!afl->skip_deterministic) {
+ if (unlikely(!afl->skip_deterministic)) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
@@ -897,7 +904,7 @@ void show_stats(afl_state_t *afl) {
" pending : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
- if (!afl->skip_deterministic) {
+ if (unlikely(!afl->skip_deterministic)) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
@@ -913,7 +920,7 @@ void show_stats(afl_state_t *afl) {
" pend fav : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->pending_favored));
- if (!afl->skip_deterministic) {
+ if (unlikely(!afl->skip_deterministic)) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
@@ -929,7 +936,7 @@ void show_stats(afl_state_t *afl) {
" own finds : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->queued_discovered));
- if (!afl->skip_deterministic) {
+ if (unlikely(!afl->skip_deterministic)) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
@@ -939,6 +946,14 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
+ } else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
+
+ strcpy(tmp, "n/a");
+
+ } else {
+
+ strcpy(tmp, "havoc mode");
+
}
SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP
@@ -974,35 +989,57 @@ void show_stats(afl_state_t *afl) {
: cRST),
tmp);
- if (afl->shm.cmplog_mode) {
+ if (unlikely(afl->afl_env.afl_python_module)) {
- sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
+ sprintf(tmp, "%s/%s,",
u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
- u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
- u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
- u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
- u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
- u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
- u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
- u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+ u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]));
+
+ } else {
+
+ strcpy(tmp, "unused,");
+
+ }
+
+ if (unlikely(afl->afl_env.afl_custom_mutator_library)) {
- SAYF(bV bSTOP " custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
- tmp);
+ strcat(tmp, " ");
+ strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_PYTHON]));
+ strcat(tmp, "/");
+ strcat(tmp, u_stringify_int(IB(3), afl->stage_cycles[STAGE_PYTHON]));
+ strcat(tmp, ",");
} else {
- sprintf(tmp, "%s/%s, %s/%s",
- u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
- u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
- u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
- u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+ strcat(tmp, " unused,");
+
+ }
+
+ if (unlikely(afl->shm.cmplog_mode)) {
+
+ strcat(tmp, " ");
+ strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]));
+ strcat(tmp, "/");
+ strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]));
+ strcat(tmp, ", ");
+ strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]));
+ strcat(tmp, "/");
+ strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+
+ } else {
- SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
- tmp);
+ strcat(tmp, " unused, unused");
}
- if (!afl->bytes_trim_out) {
+ SAYF(bV bSTOP "py/custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
+ tmp);
+
+ if (likely(afl->disable_trim)) {
+
+ sprintf(tmp, "disabled, ");
+
+ } else if (unlikely(!afl->bytes_trim_out)) {
sprintf(tmp, "n/a, ");
@@ -1015,12 +1052,13 @@ void show_stats(afl_state_t *afl) {
}
- if (!afl->blocks_eff_total) {
+ if (likely(afl->skip_deterministic)) {
- u8 tmp2[128];
+ strcat(tmp, "disabled");
- sprintf(tmp2, "n/a");
- strcat(tmp, tmp2);
+ } else if (unlikely(!afl->blocks_eff_total)) {
+
+ strcat(tmp, "n/a");
} else {
@@ -1044,7 +1082,7 @@ void show_stats(afl_state_t *afl) {
//
//} else {
- SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, tmp);
+ SAYF(bV bSTOP " trim/eff : " cRST "%-36s " bSTG bV RESET_G1, tmp);
//}
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index d70ffd31..3606533d 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -109,6 +109,7 @@ static void usage(u8 *argv0, int more_help) {
"maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n"
+ " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
@@ -126,7 +127,7 @@ static void usage(u8 *argv0, int more_help) {
"it.\n"
" if using QEMU, just use -c 0.\n"
" -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
- " 1=small files (default), 2=larger files, 3=all "
+ " 1=small files, 2=larger files (default), 3=all "
"files,\n"
" A=arithmetic solving, T=transformational solving.\n\n"
"Fuzzing behavior settings:\n"
@@ -175,6 +176,14 @@ static void usage(u8 *argv0, int more_help) {
#define DYN_COLOR
#endif
+#ifdef AFL_PERSISTENT_RECORD
+ #define PERSISTENT_MSG \
+ "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
+ "out/crashes\n"
+#else
+ #define PERSISTENT_MSG
+#endif
+
SAYF(
"Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
@@ -222,6 +231,9 @@ static void usage(u8 *argv0, int more_help) {
"AFL_PATH: path to AFL support binaries\n"
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
"AFL_QUIET: suppress forkserver status messages\n"
+
+ PERSISTENT_MSG
+
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TARGET_ENV: pass extra environment variables to target\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
@@ -253,7 +265,13 @@ static void usage(u8 *argv0, int more_help) {
SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
(char *)PYTHON_VERSION);
#else
- SAYF("Compiled without python module support\n");
+ SAYF("Compiled without python module support.\n");
+#endif
+
+#ifdef AFL_PERSISTENT_RECORD
+ SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
+#else
+ SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
#endif
#ifdef USEMMAP
@@ -263,27 +281,27 @@ static void usage(u8 *argv0, int more_help) {
#endif
#ifdef ASAN_BUILD
- SAYF("Compiled with ASAN_BUILD\n\n");
+ SAYF("Compiled with ASAN_BUILD.\n");
#endif
#ifdef NO_SPLICING
- SAYF("Compiled with NO_SPLICING\n\n");
+ SAYF("Compiled with NO_SPLICING.\n");
#endif
#ifdef PROFILING
- SAYF("Compiled with PROFILING\n\n");
+ SAYF("Compiled with PROFILING.\n");
#endif
#ifdef INTROSPECTION
- SAYF("Compiled with INTROSPECTION\n\n");
+ SAYF("Compiled with INTROSPECTION.\n");
#endif
#ifdef _DEBUG
- SAYF("Compiled with _DEBUG\n\n");
+ SAYF("Compiled with _DEBUG.\n");
#endif
#ifdef _AFL_DOCUMENT_MUTATIONS
- SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS\n\n");
+ SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
#endif
SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
@@ -320,6 +338,8 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *extras_dir[4];
u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
extras_dir_cnt = 0 /*, have_p = 0*/;
+ char * afl_preload;
+ char * frida_afl_preload = NULL;
char **use_argv;
struct timeval tv;
@@ -363,7 +383,7 @@ int main(int argc, char **argv_orig, char **envp) {
while ((opt = getopt(
argc, argv,
- "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
+ "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
switch (opt) {
@@ -755,6 +775,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->use_banner = optarg;
break;
+ case 'O': /* FRIDA mode */
+
+ if (afl->fsrv.frida_mode) {
+
+ FATAL("Multiple -O options not supported");
+
+ }
+
+ afl->fsrv.frida_mode = 1;
+
+ break;
+
case 'Q': /* QEMU mode */
if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -831,6 +863,14 @@ int main(int argc, char **argv_orig, char **envp) {
break;
case '3':
afl->cmplog_lvl = 3;
+
+ if (!afl->disable_trim) {
+
+ ACTF("Deactivating trimming due CMPLOG level 3");
+ afl->disable_trim = 1;
+
+ }
+
break;
case 'a':
case 'A':
@@ -1023,6 +1063,30 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (unlikely(afl->afl_env.afl_persistent_record)) {
+
+ #ifdef AFL_PERSISTENT_RECORD
+
+ afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
+
+ if (afl->fsrv.persistent_record < 2) {
+
+ FATAL(
+ "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is "
+ "100 or 1000.");
+
+ }
+
+ #else
+
+ FATAL(
+ "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in "
+ "config.h!");
+
+ #endif
+
+ }
+
if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
@@ -1085,6 +1149,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->non_instrumented_mode) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
+ if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
@@ -1289,6 +1354,25 @@ int main(int argc, char **argv_orig, char **envp) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
+ } else if (afl->fsrv.frida_mode) {
+
+ afl_preload = getenv("AFL_PRELOAD");
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ if (afl_preload) {
+
+ frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+ } else {
+
+ frida_afl_preload = alloc_printf("%s", frida_binary);
+
+ }
+
+ ck_free(frida_binary);
+
+ setenv("LD_PRELOAD", frida_afl_preload, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
} else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -1296,6 +1380,13 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else if (afl->fsrv.frida_mode) {
+
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ setenv("LD_PRELOAD", frida_binary, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+ ck_free(frida_binary);
+
}
if (getenv("AFL_LD_PRELOAD")) {
@@ -1479,7 +1570,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
+ if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode &&
+ !afl->non_instrumented_mode) {
check_binary(afl, afl->cmplog_binary);
@@ -1489,6 +1581,23 @@ int main(int argc, char **argv_orig, char **envp) {
check_binary(afl, argv[optind]);
+ #ifdef AFL_PERSISTENT_RECORD
+ if (unlikely(afl->fsrv.persistent_record)) {
+
+ if (!getenv(PERSIST_ENV_VAR)) {
+
+ FATAL(
+ "Target binary is not compiled in persistent mode, "
+ "AFL_PERSISTENT_RECORD makes no sense.");
+
+ }
+
+ afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
+
+ }
+
+ #endif
+
if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
afl->start_time = get_cur_time();
@@ -1513,7 +1622,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->unicorn_mode) {
+ if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
+ afl->fsrv.frida_mode || afl->unicorn_mode) {
map_size = afl->fsrv.map_size = MAP_SIZE;
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
@@ -1773,6 +1883,14 @@ int main(int argc, char **argv_orig, char **envp) {
runs_in_current_cycle > afl->queued_paths) ||
(afl->old_seed_selection && !afl->queue_cur))) {
+ if (unlikely((afl->last_sync_cycle < afl->queue_cycle ||
+ (!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
+ afl->sync_id)) {
+
+ sync_fuzzers(afl);
+
+ }
+
++afl->queue_cycle;
runs_in_current_cycle = (u32)-1;
afl->cur_skipped_paths = 0;
@@ -1886,6 +2004,13 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ #ifdef INTROSPECTION
+ fprintf(afl->introspection_file,
+ "CYCLE cycle=%llu cycle_wo_finds=%llu expand_havoc=%u queue=%u\n",
+ afl->queue_cycle, afl->cycles_wo_finds, afl->expand_havoc,
+ afl->queued_paths);
+ #endif
+
if (afl->cycle_schedules) {
/* we cannot mix non-AFLfast schedules with others */
@@ -1937,13 +2062,6 @@ int main(int argc, char **argv_orig, char **envp) {
prev_queued = afl->queued_paths;
- if (afl->sync_id && afl->queue_cycle == 1 &&
- afl->afl_env.afl_import_first) {
-
- sync_fuzzers(afl);
-
- }
-
}
++runs_in_current_cycle;
@@ -2023,12 +2141,10 @@ int main(int argc, char **argv_orig, char **envp) {
}
write_bitmap(afl);
- maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
stop_fuzzing:
- write_stats_file(afl, 0, 0, 0, 0);
afl->force_ui_update = 1; // ensure the screen is reprinted
show_stats(afl); // print the screen one last time
@@ -2074,6 +2190,8 @@ stop_fuzzing:
}
+ if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
fclose(afl->fsrv.plot_file);
destroy_queue(afl);
destroy_extras(afl);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 0a978653..d0113af9 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -73,8 +73,8 @@ static u32 ld_param_cnt = 1; /* Number of params to 'ld' */
so we exploit this property to keep the code "simple". */
static void edit_params(int argc, char **argv) {
- u32 i, instrim = 0, gold_pos = 0, gold_present = 0, rt_present = 0,
- rt_lto_present = 0, inst_present = 0;
+ u32 i, gold_pos = 0, gold_present = 0, rt_present = 0, rt_lto_present = 0,
+ inst_present = 0;
char *ptr;
ld_params = ck_alloc(4096 * sizeof(u8 *));
@@ -186,17 +186,18 @@ static void edit_params(int argc, char **argv) {
}
- if (getenv("AFL_LLVM_INSTRIM"))
- instrim = 1;
- else if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) &&
- (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0))
- instrim = 1;
+ if (getenv("AFL_LLVM_INSTRIM") ||
+ ((ptr = getenv("AFL_LLVM_INSTRUMENT")) &&
+ (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0)))
+ FATAL(
+ "InsTrim was removed because it is not effective. Use a modern LLVM "
+ "and PCGUARD (which is the default in afl-cc).\n");
if (debug)
DEBUGF(
- "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s "
+ "passthrough=%s, gold_pos=%u, gold_present=%s "
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
- passthrough ? "true" : "false", instrim, gold_pos,
+ passthrough ? "true" : "false", gold_pos,
gold_present ? "true" : "false", inst_present ? "true" : "false",
rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
@@ -230,12 +231,8 @@ static void edit_params(int argc, char **argv) {
if (!inst_present) {
- if (instrim)
- ld_params[ld_param_cnt++] =
- alloc_printf("-mllvm=-load=%s/afl-llvm-lto-instrim.so", afl_path);
- else
- ld_params[ld_param_cnt++] = alloc_printf(
- "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path);
+ ld_params[ld_param_cnt++] = alloc_printf(
+ "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path);
}
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 077c9248..946b19cd 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -72,8 +72,7 @@ static u8 *in_data, /* Input data */
static u64 total; /* tuple content information */
static u32 tcnt, highest; /* tuple content information */
-static u32 in_len, /* Input data length */
- arg_offset; /* Total number of execs */
+static u32 in_len; /* Input data length */
static u32 map_size = MAP_SIZE;
@@ -556,8 +555,10 @@ static void handle_stop_sig(int sig) {
/* Do basic preparations - persistent fds, filenames, etc. */
-static void set_up_environment(afl_forkserver_t *fsrv) {
+static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
+ char *afl_preload;
+ char *frida_afl_preload = NULL;
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
@@ -571,6 +572,13 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
"handle_sigill=0",
0);
+ setenv("LSAN_OPTIONS",
+ "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+ "fast_unwind_on_malloc=0:"
+ "symbolize=0:"
+ "print_suppressions=0",
+ 0);
+
setenv("UBSAN_OPTIONS",
"halt_on_error=1:"
"abort_on_error=1:"
@@ -601,6 +609,25 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
+ } else if (fsrv->frida_mode) {
+
+ afl_preload = getenv("AFL_PRELOAD");
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ if (afl_preload) {
+
+ frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+ } else {
+
+ frida_afl_preload = alloc_printf("%s", frida_binary);
+
+ }
+
+ ck_free(frida_binary);
+
+ setenv("LD_PRELOAD", frida_afl_preload, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
} else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -608,8 +635,17 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
}
+ } else if (fsrv->frida_mode) {
+
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ setenv("LD_PRELOAD", frida_binary, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+ ck_free(frida_binary);
+
}
+ if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
}
/* Setup signal handlers, duh. */
@@ -656,6 +692,7 @@ static void usage(u8 *argv0) {
"Execution control settings:\n"
" -t msec - timeout for each run (none)\n"
" -m megs - memory limit for child process (%u MB)\n"
+ " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use Unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
@@ -724,7 +761,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrsh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) {
switch (opt) {
@@ -858,6 +895,14 @@ int main(int argc, char **argv_orig, char **envp) {
at_file = optarg;
break;
+ case 'O': /* FRIDA mode */
+
+ if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
+
+ fsrv->frida_mode = 1;
+
+ break;
+
case 'Q':
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -944,7 +989,7 @@ int main(int argc, char **argv_orig, char **envp) {
shm.cmplog_mode = 0;
setup_signal_handlers();
- set_up_environment(fsrv);
+ set_up_environment(fsrv, argv);
fsrv->target_path = find_binary(argv[optind]);
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
@@ -958,10 +1003,27 @@ int main(int argc, char **argv_orig, char **envp) {
if (in_dir) {
- detect_file_args(argv + optind, "", &fsrv->use_stdin);
+ /* If we don't have a file name chosen yet, use a safe default. */
+ u8 *use_dir = ".";
+
+ if (access(use_dir, R_OK | W_OK | X_OK)) {
+
+ use_dir = get_afl_env("TMPDIR");
+ if (!use_dir) { use_dir = "/tmp"; }
+
+ }
+
+ stdin_file = at_file ? strdup(at_file)
+ : (char *)alloc_printf("%s/.afl-showmap-temp-%u",
+ use_dir, (u32)getpid());
+ unlink(stdin_file);
+
+ // If @@ are in the target args, replace them and also set use_stdin=false.
+ detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
} else {
+ // If @@ are in the target args, replace them and also set use_stdin=false.
detect_file_args(argv + optind, at_file, &fsrv->use_stdin);
}
@@ -986,14 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- i = 0;
- while (use_argv[i] != NULL && !arg_offset) {
-
- if (strcmp(use_argv[i], "@@") == 0) { arg_offset = i; }
- i++;
-
- }
-
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
/* initialize cmplog_mode */
@@ -1104,31 +1158,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
- u8 *use_dir = ".";
-
- if (access(use_dir, R_OK | W_OK | X_OK)) {
-
- use_dir = get_afl_env("TMPDIR");
- if (!use_dir) { use_dir = "/tmp"; }
-
- }
-
- stdin_file = at_file ? strdup(at_file)
- : (char *)alloc_printf("%s/.afl-showmap-temp-%u",
- use_dir, (u32)getpid());
- unlink(stdin_file);
atexit(at_exit_handler);
fsrv->out_file = stdin_file;
fsrv->out_fd =
open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
- if (arg_offset && use_argv[arg_offset] != stdin_file) {
-
- use_argv[arg_offset] = strdup(stdin_file);
-
- }
-
if (get_afl_env("AFL_DEBUG")) {
int j = optind;
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index fc974262..6656712a 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -640,9 +640,11 @@ static void handle_stop_sig(int sig) {
/* Do basic preparations - persistent fds, filenames, etc. */
-static void set_up_environment(afl_forkserver_t *fsrv) {
+static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
- u8 *x;
+ u8 * x;
+ char *afl_preload;
+ char *frida_afl_preload = NULL;
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@@ -712,6 +714,18 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
}
+ x = get_afl_env("LSAN_OPTIONS");
+
+ if (x) {
+
+ if (!strstr(x, "symbolize=0")) {
+
+ FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+ }
+
+ }
+
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
@@ -749,12 +763,38 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
"handle_sigfpe=0:"
"handle_sigill=0", 0);
+ setenv("LSAN_OPTIONS",
+ "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+ "fast_unwind_on_malloc=0:"
+ "symbolize=0:"
+ "print_suppressions=0",
+ 0);
+
if (get_afl_env("AFL_PRELOAD")) {
if (fsrv->qemu_mode) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
+ } else if (fsrv->frida_mode) {
+
+ afl_preload = getenv("AFL_PRELOAD");
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ if (afl_preload) {
+
+ frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+ } else {
+
+ frida_afl_preload = alloc_printf("%s", frida_binary);
+
+ }
+
+ ck_free(frida_binary);
+
+ setenv("LD_PRELOAD", frida_afl_preload, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
} else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -762,8 +802,17 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
}
+ } else if (fsrv->frida_mode) {
+
+ u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+ setenv("LD_PRELOAD", frida_binary, 1);
+ setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+ ck_free(frida_binary);
+
}
+ if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
}
/* Setup signal handlers, duh. */
@@ -804,6 +853,7 @@ static void usage(u8 *argv0) {
" -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%u MB)\n"
+ " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
@@ -859,7 +909,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeOQUWHh")) > 0) {
switch (opt) {
@@ -971,6 +1021,14 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'O': /* FRIDA mode */
+
+ if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
+
+ fsrv->frida_mode = 1;
+
+ break;
+
case 'Q':
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1054,7 +1112,7 @@ int main(int argc, char **argv_orig, char **envp) {
atexit(at_exit_handler);
setup_signal_handlers();
- set_up_environment(fsrv);
+ set_up_environment(fsrv, argv);
fsrv->target_path = find_binary(argv[optind]);
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);