From 8e809d8593d9230c123aa22c8cd0b695e54d7c68 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 30 Jul 2020 17:51:32 +0200 Subject: added NULL check --- src/afl-common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index c023789b..367dec72 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -145,7 +145,8 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); u8 * tmp, *cp = NULL, *rsl, *own_copy; - memcpy(new_argv + 3, argv + 1, (int)(sizeof(char *)) * argc); + memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); + new_argv[argc - 1] = NULL; new_argv[2] = *target_path_p; new_argv[1] = "--"; @@ -226,7 +227,8 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); u8 * tmp, *cp = NULL, *rsl, *own_copy; - memcpy(new_argv + 2, argv + 1, (int)(sizeof(char *)) * argc); + memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); + new_argv[argc - 1] = NULL; new_argv[1] = *target_path_p; -- cgit 1.4.1 From e4a0237cbc745552a5b21a2450d7ab55ee98759d Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 9 Aug 2020 00:35:12 +0200 Subject: step 1 --- GNUmakefile | 2 +- include/afl-fuzz.h | 6 ++++++ include/forkserver.h | 2 ++ qemu_taint/README.md | 2 +- src/afl-common.c | 1 + src/afl-forkserver.c | 15 +++++++++++++-- src/afl-fuzz-bitmap.c | 32 ++++++++++++++++++++++++++++++++ src/afl-fuzz-run.c | 13 +++++++++++++ src/afl-fuzz.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 9 files changed, 116 insertions(+), 8 deletions(-) (limited to 'src/afl-common.c') diff --git a/GNUmakefile b/GNUmakefile index 9b064eb6..4d0c434e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -98,7 +98,7 @@ ifneq "$(shell uname -m)" "x86_64" endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -override CFLAGS += -Wall -Wextra -Werror -g -Wno-pointer-sign \ +override CFLAGS += -g -Wno-pointer-sign \ -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \ -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index bb1bb314..eb7f8ca5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -371,6 +371,8 @@ typedef struct afl_state { afl_env_vars_t afl_env; char **argv; /* argv if needed */ + + char **argv_taint; /* argv for taint mode */ /* MOpt: Lots of globals, but mostly for the status UI and other things where it @@ -581,6 +583,9 @@ typedef struct afl_state { char * cmplog_binary; afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */ + /* Taint mode */ + afl_forkserver_t taint_fsrv; /* taint mode has its own little forkserver */ + /* Custom mutators */ struct custom_mutator *mutator; @@ -889,6 +894,7 @@ u32 calculate_score(afl_state_t *, struct queue_entry *); void write_bitmap(afl_state_t *); u32 count_bits(afl_state_t *, u8 *); +u32 count_bits_len(afl_state_t *, u8 *, u32); u32 count_bytes(afl_state_t *, u8 *); u32 count_non_255_bytes(afl_state_t *, u8 *); #ifdef WORD_SIZE_64 diff --git a/include/forkserver.h b/include/forkserver.h index 717493db..a5fca30e 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -79,6 +79,8 @@ typedef struct afl_forkserver { u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ u8 qemu_mode; /* if running in qemu mode or not */ + + u8 taint_mode; /* if running taint analysis or not */ u32 *shmem_fuzz_len; /* length of the fuzzing test case */ diff --git a/qemu_taint/README.md b/qemu_taint/README.md index c842da0e..6a7d19af 100644 --- a/qemu_taint/README.md +++ b/qemu_taint/README.md @@ -18,7 +18,7 @@ Only touched bytes are then fuzzed by afl-fuzz ## How to use -Add the -T flag to afl-fuzz +Add the -A flag to afl-fuzz ## Caveats diff --git a/src/afl-common.c b/src/afl-common.c index 367dec72..134d3180 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -138,6 +138,7 @@ void argv_cpy_free(char **argv) { } + /* Rewrite argv for QEMU. */ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 752641d7..b4f92e5b 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -481,6 +481,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_sigill=0", 0); +fprintf(stderr, "init %p\n", fsrv->init_child_func); fsrv->init_child_func(fsrv, argv); /* Use a distinctive bitmap signature to tell the parent about execv() @@ -496,10 +497,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, char pid_buf[16]; sprintf(pid_buf, "%d", fsrv->fsrv_pid); - if (fsrv->cmplog_binary) + + if (fsrv->qemu_mode == 2) { + + setenv("__AFL_TARGET_PID3", pid_buf, 1); + + } else if (fsrv->cmplog_binary) { + setenv("__AFL_TARGET_PID2", pid_buf, 1); - else + + } else { + setenv("__AFL_TARGET_PID1", pid_buf, 1); + + } /* Close the unneeded endpoints. */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index aa8d5a18..9cb1b83f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -177,6 +177,38 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { } +u32 count_bits_len(afl_state_t *afl, u8 *mem, u32 len) { + + u32 *ptr = (u32 *)mem; + u32 i = (len >> 2); + u32 ret = 0; + + if (len % 4) i++; + + while (i--) { + + u32 v = *(ptr++); + + /* This gets called on the inverse, virgin bitmap; optimize for sparse + data. */ + + if (v == 0xffffffff) { + + ret += 32; + continue; + + } + + v -= ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; + + } + + return ret; + +} + /* Count the number of bytes set in the bitmap. Called fairly sporadically, mostly to update the status screen or calibrate and examine confirmed new paths. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 8d652155..207b3046 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -471,6 +471,19 @@ abort_calibration: afl->stage_cur = old_sc; afl->stage_max = old_sm; + /* if taint mode was selected, run the taint */ + + if (afl->fsrv.taint_mode) { + write_to_testcase(afl, use_mem, q->len); + if (afl_fsrv_run_target(&afl->taint_fsrv, use_tmout, &afl->stop_soon) == 0) { + u32 len = q->len / 8; + if (q->len % 8) len++; + u32 bits = count_bits_len(afl, afl->taint_fsrv.trace_bits, len); + if (afl->debug) fprintf(stderr, "Debug: tainted bytes: %u\n", bits); + + } + } + if (!first_run) { show_stats(afl); } return fault; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 031c4049..bc780b55 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -53,6 +53,9 @@ static void at_exit() { ptr = getenv("__AFL_TARGET_PID2"); if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL); + ptr = getenv("__AFL_TARGET_PID3"); + if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL); + i = 0; while (list[i] != NULL) { @@ -89,6 +92,7 @@ static void usage(u8 *argv0, int more_help) { " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" + " -A - use first level taint analysis (see qemu_taint/README.md)\n" " -p schedule - power schedules compute a seed's performance score. " " 0) { + "+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QANUWe:p:s:V:E:L:hRP:")) > 0) { switch (opt) { + case 'A': + afl->fsrv.taint_mode = 1; + if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; } + break; + case 'I': afl->infoexec = optarg; break; @@ -485,7 +494,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!optarg) { FATAL("Wrong usage of -m"); } - if (!strcmp(optarg, "none")) { + if (!strcmp(optarg, "none") || !strcmp(optarg, "0")) { afl->fsrv.mem_limit = 0; break; @@ -815,6 +824,14 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->fsrv.taint_mode && afl->fsrv.map_size < (MAX_FILE / 8) + 1) { + + afl->shm.map_size = (MAX_FILE / 8); + if (MAX_FILE % 8) afl->shm.map_size++; + afl->fsrv.map_size = afl->shm.map_size; + + } + if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " @@ -869,6 +886,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->crash_mode) { FATAL("-C 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"); } + if (afl->fsrv.taint_mode) { FATAL("-A and -n are mutually exclusive"); } } @@ -969,7 +987,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->afl_env.afl_preload) { - if (afl->fsrv.qemu_mode) { + if (afl->fsrv.qemu_mode || afl->fsrv.taint_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -1220,7 +1238,6 @@ int main(int argc, char **argv_orig, char **envp) { ACTF("Spawning cmplog forkserver"); afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv); - // TODO: this is semi-nice afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; @@ -1230,6 +1247,29 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Cmplog forkserver successfully started"); } + + if (afl->fsrv.taint_mode) { + + ACTF("Spawning qemu_taint forkserver"); + afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv); + afl->taint_fsrv.qemu_mode = 2; + afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits; + ck_free(afl->taint_fsrv.target_path); + afl->taint_fsrv.target_path = ck_strdup(afl->fsrv.target_path); + afl->argv_taint = get_qemu_argv(argv[0], &afl->taint_fsrv.target_path, + argc - optind, argv + optind); + u32 len = strlen(afl->taint_fsrv.target_path); + strcpy(afl->taint_fsrv.target_path + len - 5, "taint"); + strcpy((afl->argv_taint[0]) + len - 5, "taint"); + if (afl->fsrv.use_stdin) + unsetenv("AFL_TAINT_INPUT"); + else + setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1); + afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon, + afl->afl_env.afl_debug_child_output); + OKF("Taint forkserver successfully started"); + + } perform_dry_run(afl); @@ -1493,8 +1533,11 @@ stop_fuzzing: } + if (afl->cmplog_binary) afl_fsrv_deinit(&afl->cmplog_fsrv); + if (afl->fsrv.taint_mode) afl_fsrv_deinit(&afl->taint_fsrv); afl_fsrv_deinit(&afl->fsrv); if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } + if (afl->argv_taint) { ck_free(afl->argv_taint); } ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); ck_free(afl->sync_id); -- cgit 1.4.1 From 0bb59ba11606e0382126304f78507efe7d62fd6b Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 9 Aug 2020 01:09:26 +0200 Subject: code format --- include/afl-fuzz.h | 2 +- include/common.h | 1 + include/forkserver.h | 2 +- src/afl-common.c | 140 +++++++++++++++++---------------------------------- src/afl-forkserver.c | 11 ++-- src/afl-fuzz-run.c | 8 ++- src/afl-fuzz.c | 25 ++++++--- 7 files changed, 78 insertions(+), 111 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index eb7f8ca5..37e2dc6c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -371,7 +371,7 @@ typedef struct afl_state { afl_env_vars_t afl_env; char **argv; /* argv if needed */ - + char **argv_taint; /* argv for taint mode */ /* MOpt: diff --git a/include/common.h b/include/common.h index 87a7425b..42c79c62 100644 --- a/include/common.h +++ b/include/common.h @@ -55,6 +55,7 @@ extern u8 *doc_path; /* path to documentation dir */ @returns the path, allocating the string */ u8 *find_binary(u8 *fname); +u8 *find_binary_own_loc(u8 *fname, u8 *own_loc); /* Read a bitmap from file fname to memory This is for the -B option again. */ diff --git a/include/forkserver.h b/include/forkserver.h index a5fca30e..89f23ab7 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -79,7 +79,7 @@ typedef struct afl_forkserver { u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ u8 qemu_mode; /* if running in qemu mode or not */ - + u8 taint_mode; /* if running taint analysis or not */ u32 *shmem_fuzz_len; /* length of the fuzzing test case */ diff --git a/src/afl-common.c b/src/afl-common.c index 134d3180..c0202821 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -138,32 +138,19 @@ void argv_cpy_free(char **argv) { } +u8 *find_binary_own_loc(u8 *fname, u8 *own_loc) { -/* Rewrite argv for QEMU. */ - -char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { - - char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); - u8 * tmp, *cp = NULL, *rsl, *own_copy; - - memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc - 1] = NULL; - - new_argv[2] = *target_path_p; - new_argv[1] = "--"; - - /* Now we need to actually find the QEMU binary to put in argv[0]. */ + u8 *tmp, *rsl, *own_copy, *cp; tmp = getenv("AFL_PATH"); if (tmp) { - cp = alloc_printf("%s/afl-qemu-trace", tmp); + cp = alloc_printf("%s/%s", tmp, fname); if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - *target_path_p = new_argv[0] = cp; - return new_argv; + return cp; } @@ -174,15 +161,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { *rsl = 0; - cp = alloc_printf("%s/afl-qemu-trace", own_copy); + cp = alloc_printf("%s/%s", own_copy, fname); ck_free(own_copy); - if (!access(cp, X_OK)) { - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } + if (!access(cp, X_OK)) { return cp; } } else { @@ -190,11 +172,35 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { + cp = alloc_printf("%s/%s", BIN_PATH, fname); + if (!access(cp, X_OK)) { return cp; } + + ck_free(cp); + + return NULL; - if (cp) { ck_free(cp); } - *target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); +} + +/* Rewrite argv for QEMU. */ + +char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + + char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); + u8 * cp = NULL; + + memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); + new_argv[argc - 1] = NULL; + new_argv[2] = *target_path_p; + new_argv[1] = "--"; + + /* Now we need to actually find the QEMU binary to put in argv[0]. */ + + cp = find_binary_own_loc("afl-qemu-trace", own_loc); + + if (cp) { + + *target_path_p = new_argv[0] = cp; return new_argv; } @@ -235,66 +241,16 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - tmp = getenv("AFL_PATH"); - - if (tmp) { + cp = find_binary_own_loc("afl-qemu-trace", own_loc); - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } + if (cp) { ck_free(cp); + cp = find_binary_own_loc("afl-wine-trace", own_loc); - cp = alloc_printf("%s/afl-wine-trace", tmp); + if (cp) { - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - - if (cp && !access(cp, X_OK)) { - - ck_free(cp); - - cp = alloc_printf("%s/afl-wine-trace", own_copy); - - if (!access(cp, X_OK)) { - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - } - - ck_free(own_copy); - - } else { - - ck_free(own_copy); - - } - - u8 *ncp = BIN_PATH "/afl-qemu-trace"; - - if (!access(ncp, X_OK)) { - - ncp = BIN_PATH "/afl-wine-trace"; - - if (!access(ncp, X_OK)) { - - *target_path_p = new_argv[0] = ck_strdup(ncp); + *target_path_p = new_argv[0] = cp; return new_argv; } @@ -302,25 +258,21 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the '%s' binary. The binary must be " - "built\n" - " separately by following the instructions in " - "qemu_mode/README.md. " - "If you\n" - " already have the binary installed, you may need to specify " - "AFL_PATH in the\n" - " environment.\n\n" - + "Oops, unable to find the afl-qemu-trace and afl-wine-trace binaries.\n" + "The afl-qemu-trace binary must be built separately by following the " + "instructions\n" + "in qemu_mode/README.md. If you already have the binary installed, you " + "may need\n" + "to specify the location via AFL_PATH in the environment.\n\n" " Of course, even without QEMU, afl-fuzz can still work with " "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" " traditional non-instrumented fuzzer by specifying '-n' in the " "command " - "line.\n", - ncp); + "line.\n"); - FATAL("Failed to locate '%s'.", ncp); + FATAL("Failed to locate 'afl-qemu-trace' and 'afl-wine-trace'."); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b4f92e5b..eeb2f8c3 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -481,7 +481,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_sigill=0", 0); -fprintf(stderr, "init %p\n", fsrv->init_child_func); fsrv->init_child_func(fsrv, argv); /* Use a distinctive bitmap signature to tell the parent about execv() @@ -497,19 +496,19 @@ fprintf(stderr, "init %p\n", fsrv->init_child_func); char pid_buf[16]; sprintf(pid_buf, "%d", fsrv->fsrv_pid); - + if (fsrv->qemu_mode == 2) { setenv("__AFL_TARGET_PID3", pid_buf, 1); } else if (fsrv->cmplog_binary) { - + setenv("__AFL_TARGET_PID2", pid_buf, 1); - + } else { - + setenv("__AFL_TARGET_PID1", pid_buf, 1); - + } /* Close the unneeded endpoints. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 207b3046..badc2239 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -472,16 +472,20 @@ abort_calibration: afl->stage_max = old_sm; /* if taint mode was selected, run the taint */ - + if (afl->fsrv.taint_mode) { + write_to_testcase(afl, use_mem, q->len); - if (afl_fsrv_run_target(&afl->taint_fsrv, use_tmout, &afl->stop_soon) == 0) { + if (afl_fsrv_run_target(&afl->taint_fsrv, use_tmout, &afl->stop_soon) == + 0) { + u32 len = q->len / 8; if (q->len % 8) len++; u32 bits = count_bits_len(afl, afl->taint_fsrv.trace_bits, len); if (afl->debug) fprintf(stderr, "Debug: tainted bytes: %u\n", bits); } + } if (!first_run) { show_stats(afl); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bc780b55..684b123e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -92,7 +92,8 @@ static void usage(u8 *argv0, int more_help) { " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" - " -A - use first level taint analysis (see qemu_taint/README.md)\n" + " -A - use first level taint analysis (see " + "qemu_taint/README.md)\n" " -p schedule - power schedules compute a seed's performance score. " "fsrv.taint_mode) { ACTF("Spawning qemu_taint forkserver"); @@ -1256,11 +1257,21 @@ int main(int argc, char **argv_orig, char **envp) { afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits; ck_free(afl->taint_fsrv.target_path); afl->taint_fsrv.target_path = ck_strdup(afl->fsrv.target_path); - afl->argv_taint = get_qemu_argv(argv[0], &afl->taint_fsrv.target_path, - argc - optind, argv + optind); - u32 len = strlen(afl->taint_fsrv.target_path); - strcpy(afl->taint_fsrv.target_path + len - 5, "taint"); - strcpy((afl->argv_taint[0]) + len - 5, "taint"); + afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind)); + afl->argv_taint[0] = find_binary_own_loc("afl-qemu-taint", argv[0]); + if (!afl->argv_taint[0]) + FATAL( + "Cannot find 'afl-qemu-taint', read qemu_taint/README.md on how to " + "build it."); + u32 idx = optind - 1, offset = 0; + do { + + idx++; + offset++; + afl->argv_taint[offset] = argv[idx]; + + } while (argv[idx] != NULL); + if (afl->fsrv.use_stdin) unsetenv("AFL_TAINT_INPUT"); else -- cgit 1.4.1 From b60663c0318b8baf21b36b549d765ddd2eeeb54e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 9 Aug 2020 18:48:12 +0200 Subject: taint integration done --- include/afl-fuzz.h | 15 +++-- llvm_mode/afl-llvm-rt.o.c | 10 +++ src/afl-common.c | 2 +- src/afl-forkserver.c | 3 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-init.c | 28 ++++++++- src/afl-fuzz-queue.c | 151 ++++++++++++++++++++++++++++++++++++++++++++-- src/afl-fuzz-run.c | 83 ++++++++++++------------- src/afl-fuzz.c | 25 ++++++-- 9 files changed, 255 insertions(+), 64 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 328c8405..19807880 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -133,8 +133,10 @@ extern s32 struct queue_entry { - u8 *fname; /* File name for the test case */ - u32 len; /* Input length */ + u8 * fname; /* File name for the test case */ + u8 * fname_taint; /* File name for taint data */ + u32 len; /* Input length */ + struct queue_entry *prev; /* previous queue entry, if any */ u8 cal_failed, /* Calibration failed? */ trim_done, /* Trimmed? */ @@ -148,7 +150,10 @@ struct queue_entry { is_ascii; /* Is the input just ascii text? */ u32 bitmap_size, /* Number of bits set in bitmap */ - fuzz_level; /* Number of fuzzing iterations */ + fuzz_level, /* Number of fuzzing iterations */ + taint_bytes_all, /* Number of tainted bytes */ + taint_bytes_new, /* Number of new tainted bytes */ + taint_bytes_highest; /* highest offset in input */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ @@ -885,7 +890,7 @@ void deinit_py(void *); void mark_as_det_done(afl_state_t *, struct queue_entry *); void mark_as_variable(afl_state_t *, struct queue_entry *); void mark_as_redundant(afl_state_t *, struct queue_entry *, u8); -void add_to_queue(afl_state_t *, u8 *, u32, u8); +void add_to_queue(afl_state_t *, u8 *, u8 *, u32, struct queue_entry *, u8); void destroy_queue(afl_state_t *); void update_bitmap_score(afl_state_t *, struct queue_entry *); void cull_queue(afl_state_t *); @@ -975,6 +980,8 @@ void check_if_tty(afl_state_t *); void setup_signal_handlers(void); void save_cmdline(afl_state_t *, u32, char **); void read_foreign_testcases(afl_state_t *, int); +void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, + u8 *mem, u32 len); /* CmpLog */ diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 8cc59cbb..5ffae39c 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -831,6 +831,16 @@ void __afl_manual_init(void) { static u8 init_done; + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { + + init_done = 1; + if (getenv("AFL_DEBUG")) + fprintf(stderr, + "DEBUG: disabled instrumenation because of " + "AFL_DISABLE_LLVM_INSTRUMENTATION\n"); + + } + if (!init_done) { __afl_map_shm(); diff --git a/src/afl-common.c b/src/afl-common.c index c0202821..e01bde3c 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -232,7 +232,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); - u8 * tmp, *cp = NULL, *rsl, *own_copy; + u8 * cp = NULL; memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); new_argv[argc - 1] = NULL; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index eeb2f8c3..4dc5e438 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -933,7 +933,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } else { - s32 fd = fsrv->out_fd; + s32 fd; if (fsrv->out_file) { @@ -952,6 +952,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } else { + fd = fsrv->out_fd; lseek(fd, 0, SEEK_SET); } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 11a3f121..d4ee36e1 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -648,7 +648,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #endif /* ^!SIMPLE_FILES */ - add_to_queue(afl, queue_fn, len, 0); + add_to_queue(afl, queue_fn, mem, len, afl->queue_top, 0); if (hnb == 2) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 350a8599..350a3b4c 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -712,7 +712,7 @@ void read_testcases(afl_state_t *afl) { if (!access(dfn, F_OK)) { passed_det = 1; } - add_to_queue(afl, fn2, st.st_size, passed_det); + add_to_queue(afl, fn2, NULL, st.st_size, NULL, passed_det); } @@ -960,6 +960,9 @@ void perform_dry_run(afl_state_t *afl) { } + /* perform taint gathering on the input seed */ + perform_taint_run(afl, q, q->fname, use_mem, q->len); + q = q->next; } @@ -1438,6 +1441,10 @@ static void handle_existing_out_dir(afl_state_t *afl) { u8 *orig_q = alloc_printf("%s/queue", afl->out_dir); + u8 *fnt = alloc_printf("%s/taint", afl->out_dir); + mkdir(fnt, 0755); // ignore errors + ck_free(fnt); + afl->in_dir = alloc_printf("%s/_resume", afl->out_dir); rename(orig_q, afl->in_dir); /* Ignore errors */ @@ -1494,6 +1501,15 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); + if (afl->fsrv.taint_mode) { + + fn = alloc_printf("%s/taint", afl->out_dir); + mkdir(fn, 0755); // ignore errors + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + ck_free(fn); + + } + /* All right, let's do out_dir>/crashes/id:* and * out_dir>/hangs/id:*. */ @@ -1721,6 +1737,16 @@ void setup_dirs_fds(afl_state_t *afl) { if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); + /* Taint directory if taint_mode. */ + + if (afl->fsrv.taint_mode) { + + tmp = alloc_printf("%s/taint", afl->out_dir); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } + ck_free(tmp); + + } + /* Top-level directory for queue metadata used for session resume and related tasks. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f35df914..36ec0896 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -103,6 +103,139 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } +void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, + u8 *mem, u32 len) { + + u8 * ptr, *fn = fname; + u32 bytes = 0, plen = len; + s32 fd = -1; + struct queue_entry *prev = q->prev; + + if (plen % 4) plen = plen + 4 - (len % 4); + + if ((ptr = strrchr(fname, '/')) != NULL) fn = ptr + 1; + q->fname_taint = alloc_printf("%s/taint/%s", afl->out_dir, fn); + + if (q->fname_taint) { + + afl->taint_fsrv.map_size = plen; // speed :) + write_to_testcase(afl, mem, len); + if (afl_fsrv_run_target(&afl->taint_fsrv, afl->fsrv.exec_tmout, + &afl->stop_soon) == 0) { + + bytes = count_bytes_len(afl, afl->taint_fsrv.trace_bits, plen); + if (afl->debug) + fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, len); + + if (bytes) { + + s32 i = len; + while (i > 0 && !afl->taint_fsrv.trace_bits[i - 1]) + i--; + q->taint_bytes_highest = i; + + } + + } + + if (((bytes * 100) / len) < 90) { + + // we only use the taint havoc mode if the entry has less than 90% of + // overall tainted bytes + q->taint_bytes_all = bytes; + + // save the bytes away + int w = open(q->fname_taint, O_CREAT | O_WRONLY, 0644); + if (w >= 0) { + + ck_write(w, afl->taint_fsrv.trace_bits, plen, q->fname_taint); + close(w); + + } else { + + FATAL("could not create %s", q->fname_taint); + bytes = 0; + + } + + if (bytes && prev && prev->taint_bytes_all) { + + // check if there are new bytes in the taint vs the previous + int r = open(prev->fname_taint, O_RDONLY); + + if (r >= 0) { + + u8 *bufr = mmap(0, prev->len, PROT_READ, MAP_PRIVATE, r, 0); + + if ((size_t)bufr != -1) { + + u32 i; + u8 *tmp = ck_maybe_grow(BUF_PARAMS(in_scratch), plen); + memset(tmp, 0, plen); + + for (i = 0; i < len; i++) + if (afl->taint_fsrv.trace_bits[i] && (i >= prev->len || !bufr[i])) + tmp[i] = 1; + + q->taint_bytes_new = count_bytes_len(afl, tmp, plen); + + if (q->taint_bytes_new) { + + u8 *fnw = alloc_printf("%s.new", q->fname_taint); + int w = open(fnw, O_CREAT | O_WRONLY, 0644); + if (w >= 0) { + + ck_write(w, tmp, plen, fnw); + close(w); + + } else { + + q->taint_bytes_new = 0; + + } + + ck_free(fnw); + + } + + munmap(bufr, prev->len); + + } + + close(r); + + } + + } + + } else { + + bytes = 0; + + } + + } + + if (!bytes) { + + q->taint_bytes_highest = q->taint_bytes_all = q->taint_bytes_new = 0; + + if (q->fname_taint) { + + ck_free(q->fname_taint); + q->fname_taint = NULL; + + } + + } else { + + if (q->taint_bytes_all && !q->taint_bytes_new) + q->taint_bytes_new = q->taint_bytes_all; + + } + +} + /* check if ascii or UTF-8 */ static u8 check_if_text(struct queue_entry *q) { @@ -212,10 +345,12 @@ static u8 check_if_text(struct queue_entry *q) { /* Append new test case to the queue. */ -void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { +void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len, + struct queue_entry *prev_q, u8 passed_det) { struct queue_entry *q = ck_alloc(sizeof(struct queue_entry)); + q->prev = prev_q; q->fname = fname; q->len = len; q->depth = afl->cur_depth + 1; @@ -254,6 +389,17 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { afl->last_path_time = get_cur_time(); + /* trigger the tain gathering if this is not a dry run */ + if (afl->fsrv.taint_mode && mem) { + + perform_taint_run(afl, q, fname, mem, len); + + } + + /* only redqueen currently uses is_ascii */ + if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q); + + /* run custom mutators afl_custom_queue_new_entry() */ if (afl->custom_mutators_count) { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { @@ -273,9 +419,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } - /* only redqueen currently uses is_ascii */ - if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q); - } /* Destroy the entire queue. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 89ae0424..ddbd5524 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -471,24 +471,6 @@ abort_calibration: afl->stage_cur = old_sc; afl->stage_max = old_sm; - /* if taint mode was selected, run the taint */ - - if (afl->fsrv.taint_mode) { - - write_to_testcase(afl, use_mem, q->len); - if (afl_fsrv_run_target(&afl->taint_fsrv, use_tmout, &afl->stop_soon) == - 0) { - - u32 len = q->len; - if (len % 4) len = len + 4 - (q->len % 4); - u32 bytes = count_bytes_len(afl, afl->taint_fsrv.trace_bits, len); - if (afl->debug) - fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, q->len); - - } - - } - if (!first_run) { show_stats(afl); } return fault; @@ -770,56 +752,65 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { while (remove_pos < q->len) { u32 trim_avail = MIN(remove_len, q->len - remove_pos); - u64 cksum; - write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); + if (likely((!q->taint_bytes_highest) || + (q->len - trim_avail > q->taint_bytes_highest))) { - fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); - ++afl->trim_execs; + u64 cksum; - if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } + write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); - /* Note that we don't keep track of crashes or hangs here; maybe TODO? - */ + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + ++afl->trim_execs; - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } - /* If the deletion had no impact on the trace, make it permanent. This - isn't perfect for variable-path inputs, but we're just making a - best-effort pass, so it's not a big deal if we end up with false - negatives every now and then. */ + /* Note that we don't keep track of crashes or hangs here; maybe TODO? + */ - if (cksum == q->exec_cksum) { + cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - u32 move_tail = q->len - remove_pos - trim_avail; + /* If the deletion had no impact on the trace, make it permanent. This + isn't perfect for variable-path inputs, but we're just making a + best-effort pass, so it's not a big deal if we end up with false + negatives every now and then. */ - q->len -= trim_avail; - len_p2 = next_pow2(q->len); + if (cksum == q->exec_cksum) { - memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, - move_tail); + u32 move_tail = q->len - remove_pos - trim_avail; - /* Let's save a clean trace, which will be needed by - update_bitmap_score once we're done with the trimming stuff. */ + q->len -= trim_avail; + len_p2 = next_pow2(q->len); - if (!needs_write) { + memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, + move_tail); - needs_write = 1; - memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); + /* Let's save a clean trace, which will be needed by + update_bitmap_score once we're done with the trimming stuff. */ + + if (!needs_write) { + + needs_write = 1; + memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); + + } + + } else { + + remove_pos += remove_len; } + /* Since this can be slow, update the screen every now and then. */ + if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } + ++afl->stage_cur; + } else { remove_pos += remove_len; } - /* Since this can be slow, update the screen every now and then. */ - - if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } - ++afl->stage_cur; - } remove_len >>= 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 93ab90e2..6f143db7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -244,9 +244,10 @@ static int stricmp(char const *a, char const *b) { int main(int argc, char **argv_orig, char **envp) { - s32 opt; - u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE; + s32 opt; + u64 prev_queued = 0; + u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE, + real_map_size = 0; u8 * extras_dir = 0; u8 mem_limit_given = 0, exit_1 = 0, debug = 0; char **use_argv; @@ -827,6 +828,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.taint_mode && afl->fsrv.map_size < MAX_FILE) { + real_map_size = map_size; map_size = afl->fsrv.map_size = afl->shm.map_size = MAX_FILE; } @@ -840,8 +842,7 @@ int main(int argc, char **argv_orig, char **envp) { OKF("afl++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); OKF("Power schedules from github.com/mboehme/aflfast"); - OKF("Python Mutator and llvm_mode instrument file list from " - "github.com/choller/afl"); + OKF("Python Mutator from github.com/choller/afl"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->is_main_node && @@ -1088,6 +1089,13 @@ int main(int argc, char **argv_orig, char **envp) { memset(afl->virgin_tmout, 255, afl->fsrv.map_size); memset(afl->virgin_crash, 255, afl->fsrv.map_size); + if (map_size != real_map_size) { + + afl->fsrv.map_size = real_map_size; + if (afl->cmplog_binary) afl->cmplog_fsrv.map_size; + + } + init_count_class16(); if (afl->is_main_node && check_main_node_exists(afl) == 1) { @@ -1252,12 +1260,16 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.taint_mode) { ACTF("Spawning qemu_taint forkserver"); + u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); + setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv); afl->taint_fsrv.qemu_mode = 2; + afl->taint_fsrv.taint_mode = 1; afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits; ck_free(afl->taint_fsrv.target_path); - afl->taint_fsrv.target_path = ck_strdup(afl->fsrv.target_path); afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind)); + afl->taint_fsrv.target_path = + find_binary_own_loc("afl-qemu-taint", argv[0]); afl->argv_taint[0] = find_binary_own_loc("afl-qemu-taint", argv[0]); if (!afl->argv_taint[0]) FATAL( @@ -1278,6 +1290,7 @@ int main(int argc, char **argv_orig, char **envp) { setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1); afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon, afl->afl_env.afl_debug_child_output); + if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); OKF("Taint forkserver successfully started"); } -- cgit 1.4.1 From 3ecafde29deac10bb41c6c9b7370f7cef951ef11 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 10 Aug 2020 13:59:30 +0200 Subject: increase stack size --- src/afl-common.c | 4 ++-- src/afl-fuzz-run.c | 2 +- src/afl-fuzz.c | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index e01bde3c..dabeeedd 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -467,8 +467,8 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { u64 get_cur_time(void) { - struct timeval tv; - struct timezone tz; + static struct timeval tv; + static struct timezone tz; gettimeofday(&tv, &tz); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 7180d255..0aef1c9e 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -885,7 +885,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u32 i, taint = 0; for (i = 0; i < new_len; i++) { - if (i > afl->taint_len || afl->taint_map[i] || i > afl->queue_cur->len) + if (i >= afl->taint_len || i >= afl->queue_cur->len || afl->taint_map[i]) new_buf[i] = out_buf[taint++]; else new_buf[i] = afl->taint_src[i]; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5cdd0292..783da6e0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1305,6 +1305,12 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Taint forkserver successfully started"); + const rlim_t kStackSize = 64L * 1024L * 1024L; // min stack size = 64 Mb + struct rlimit rl; + rl.rlim_cur = kStackSize; + if (getrlimit(RLIMIT_STACK, &rl) != 0) + WARNF("Setting a higher stack size failed!"); + #define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size u8 *tmp1 = ck_maybe_grow(BUF_PARAMS(eff), MAX_FILE + 4096); u8 *tmp2 = ck_maybe_grow(BUF_PARAMS(ex), MAX_FILE + 4096); @@ -1312,7 +1318,6 @@ int main(int argc, char **argv_orig, char **envp) { u8 *tmp4 = ck_maybe_grow(BUF_PARAMS(out), MAX_FILE + 4096); u8 *tmp5 = ck_maybe_grow(BUF_PARAMS(out_scratch), MAX_FILE + 4096); #undef BUF_PARAMS - if (!tmp1 || !tmp2 || !tmp3 || !tmp4 || !tmp5) FATAL("memory issues. me hungry, feed me!"); -- cgit 1.4.1 From 0ba09ee85a65878e70d1a224f9d41fcbac3ff1e5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 11 Aug 2020 10:24:45 +0200 Subject: enhancements --- examples/aflpp_driver/aflpp_driver.c | 14 ++++++++------ include/common.h | 2 +- llvm_mode/afl-llvm-rt.o.c | 7 +++---- src/afl-common.c | 30 +++++++++++++++++------------- src/afl-fuzz-one.c | 11 +++++------ src/afl-fuzz.c | 11 +++++------ 6 files changed, 39 insertions(+), 36 deletions(-) (limited to 'src/afl-common.c') diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c index 2b7be45f..81782c67 100644 --- a/examples/aflpp_driver/aflpp_driver.c +++ b/examples/aflpp_driver/aflpp_driver.c @@ -306,10 +306,13 @@ int main(int argc, char **argv) { else if (argc > 1) { if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { + munmap(__afl_area_ptr, MAX_DUMMY_SIZE); // we need to free 0x10000 __afl_area_ptr = NULL; __afl_manual_init(); + } + return ExecuteFilesOnyByOne(argc, argv); } @@ -317,11 +320,14 @@ int main(int argc, char **argv) { assert(N > 0); if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { + munmap(__afl_area_ptr, MAX_DUMMY_SIZE); __afl_area_ptr = NULL; fprintf(stderr, "performing manual init\n"); - __afl_manual_init(); + __afl_manual_init(); + } + fprintf(stderr, "map is now at %p\n", __afl_area_ptr); // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization @@ -333,11 +339,7 @@ int main(int argc, char **argv) { ssize_t r = read(0, buf, sizeof(buf)); - if (r > 0) { - - LLVMFuzzerTestOneInput(buf, r); - - } + if (r > 0) { LLVMFuzzerTestOneInput(buf, r); } } diff --git a/include/common.h b/include/common.h index 42c79c62..c7d57e07 100644 --- a/include/common.h +++ b/include/common.h @@ -55,7 +55,7 @@ extern u8 *doc_path; /* path to documentation dir */ @returns the path, allocating the string */ u8 *find_binary(u8 *fname); -u8 *find_binary_own_loc(u8 *fname, u8 *own_loc); +u8 *find_afl_binary(u8 *fname, u8 *own_loc); /* Read a bitmap from file fname to memory This is for the -B option again. */ diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index c69d8bb7..20151aea 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -847,9 +847,8 @@ void __afl_manual_init(void) { init_done = 1; is_persistent = 0; __afl_sharedmem_fuzzing = 0; - if (__afl_area_ptr == NULL) - __afl_area_ptr = __afl_area_initial; - + if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial; + if (getenv("AFL_DEBUG")) fprintf(stderr, "DEBUG: disabled instrumenation because of " @@ -886,7 +885,7 @@ __attribute__((constructor(0))) void __afl_auto_early(void) { is_persistent = !!getenv(PERSIST_ENV_VAR); - __afl_map_shm(); + __afl_map_shm(); } diff --git a/src/afl-common.c b/src/afl-common.c index dabeeedd..c1302080 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -138,7 +138,7 @@ void argv_cpy_free(char **argv) { } -u8 *find_binary_own_loc(u8 *fname, u8 *own_loc) { +u8 *find_afl_binary(u8 *fname, u8 *own_loc) { u8 *tmp, *rsl, *own_copy, *cp; @@ -154,21 +154,25 @@ u8 *find_binary_own_loc(u8 *fname, u8 *own_loc) { } - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); + if (own_loc) { - if (rsl) { + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); - *rsl = 0; + if (rsl) { - cp = alloc_printf("%s/%s", own_copy, fname); - ck_free(own_copy); + *rsl = 0; - if (!access(cp, X_OK)) { return cp; } + cp = alloc_printf("%s/%s", own_copy, fname); + ck_free(own_copy); - } else { + if (!access(cp, X_OK)) { return cp; } + + } else { - ck_free(own_copy); + ck_free(own_copy); + + } } @@ -196,7 +200,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - cp = find_binary_own_loc("afl-qemu-trace", own_loc); + cp = find_afl_binary("afl-qemu-trace", own_loc); if (cp) { @@ -241,12 +245,12 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - cp = find_binary_own_loc("afl-qemu-trace", own_loc); + cp = find_afl_binary("afl-qemu-trace", own_loc); if (cp) { ck_free(cp); - cp = find_binary_own_loc("afl-wine-trace", own_loc); + cp = find_afl_binary("afl-wine-trace", own_loc); if (cp) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 9f38b8f8..2f724569 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2236,8 +2236,8 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), - temp_len + clone_len); + new_buf = + ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); /* Head */ @@ -2403,8 +2403,7 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) { break; } - out_buf = - ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); /* Tail */ memmove(out_buf + insert_at + extra_len, out_buf + insert_at, @@ -2499,8 +2498,8 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - u8 *temp_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), - temp_len + clone_len); + u8 *temp_buf = + ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); /* Head */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 11db004d..d2b2c2d9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1274,9 +1274,8 @@ int main(int argc, char **argv_orig, char **envp) { ck_free(afl->taint_fsrv.target_path); afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind)); - afl->taint_fsrv.target_path = - find_binary_own_loc("afl-qemu-taint", argv[0]); - afl->argv_taint[0] = find_binary_own_loc("afl-qemu-taint", argv[0]); + afl->taint_fsrv.target_path = find_afl_binary("afl-qemu-taint", argv[0]); + afl->argv_taint[0] = find_afl_binary("afl-qemu-taint", argv[0]); if (!afl->argv_taint[0]) FATAL( "Cannot find 'afl-qemu-taint', read qemu_taint/README.md on how to " @@ -1308,19 +1307,19 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Taint forkserver successfully started"); - const rlim_t kStackSize = 256L * 1024L * 1024L; // min stack size = 256 Mb + const rlim_t kStackSize = 256L * 1024L * 1024L; // min stack size = 256 Mb struct rlimit rl; rl.rlim_cur = kStackSize; if (getrlimit(RLIMIT_STACK, &rl) != 0) WARNF("Setting a higher stack size failed!"); -#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + #define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size u8 *tmp1 = ck_maybe_grow(BUF_PARAMS(eff), MAX_FILE + 4096); u8 *tmp2 = ck_maybe_grow(BUF_PARAMS(ex), MAX_FILE + 4096); u8 *tmp3 = ck_maybe_grow(BUF_PARAMS(in_scratch), MAX_FILE + 4096); u8 *tmp4 = ck_maybe_grow(BUF_PARAMS(out), MAX_FILE + 4096); u8 *tmp5 = ck_maybe_grow(BUF_PARAMS(out_scratch), MAX_FILE + 4096); -#undef BUF_PARAMS + #undef BUF_PARAMS if (!tmp1 || !tmp2 || !tmp3 || !tmp4 || !tmp5) FATAL("memory issues. me hungry, feed me!"); -- cgit 1.4.1 From 4f695b6f4c3ced165703363904e42492fca82112 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 11 Aug 2020 11:16:48 +0200 Subject: fixes --- include/afl-fuzz.h | 2 +- src/afl-common.c | 4 +-- src/afl-fuzz-bitmap.c | 2 ++ src/afl-fuzz-queue.c | 78 +++++++++++++++++++++++++++++++++++---------------- src/afl-fuzz-stats.c | 5 ++-- 5 files changed, 62 insertions(+), 29 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 02c36861..c578c583 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -506,7 +506,7 @@ typedef struct afl_state { var_byte_count, /* Bitmap bytes with var behavior */ current_entry, /* Current queue entry ID */ havoc_div, /* Cycle count divisor for havoc */ - taint_len; + taint_len, taint_count; u64 total_crashes, /* Total number of crashes */ unique_crashes, /* Crashes with unique signatures */ diff --git a/src/afl-common.c b/src/afl-common.c index c1302080..cefed8dc 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -471,8 +471,8 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { u64 get_cur_time(void) { - static struct timeval tv; - static struct timezone tz; + struct timeval tv; + struct timezone tz; gettimeofday(&tv, &tz); diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 9f58d604..d273818d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -245,6 +245,8 @@ u32 count_bytes_len(afl_state_t *afl, u8 *mem, u32 len) { (void)(afl); + if (len % 4) i++; + while (i--) { u32 v = *(ptr++); diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f4b58a9d..b56e10f8 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -125,42 +125,64 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, if (afl_fsrv_run_target(&afl->taint_fsrv, afl->fsrv.exec_tmout, &afl->stop_soon) == 0) { - bytes = count_bytes_len(afl, afl->taint_fsrv.trace_bits, plen); + bytes = q->taint_bytes_all = + count_bytes_len(afl, afl->taint_fsrv.trace_bits, plen); if (afl->debug) fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, len); - if (bytes) { + /* DEBUG FIXME TODO XXX */ + u32 i; + for (i = 0; i < len; i++) { - s32 i = len; - while (i > 0 && !afl->taint_fsrv.trace_bits[i - 1]) - i--; - q->taint_bytes_highest = i; + if (afl->taint_fsrv.trace_bits[i] && + afl->taint_fsrv.trace_bits[i] != '!') + FATAL("invalid taint map value %02x at pos %d", + afl->taint_fsrv.trace_bits[i], i); } - } + if (len < plen) + for (i = len; i < plen; i++) { - if (((bytes * 100) / len) < 90) { + if (afl->taint_fsrv.trace_bits[i]) + FATAL("invalid taint map value %02x in padding at pos %d", + afl->taint_fsrv.trace_bits[i], i); - // we only use the taint havoc mode if the entry has less than 90% of - // overall tainted bytes - q->taint_bytes_all = bytes; + } + + } + + // if all is tainted we do not need to write taint data away + if (bytes && bytes < len) { // save the bytes away int w = open(q->fname_taint, O_CREAT | O_WRONLY, 0644); if (w >= 0) { - ck_write(w, afl->taint_fsrv.trace_bits, plen, q->fname_taint); + ck_write(w, afl->taint_fsrv.trace_bits, len, q->fname_taint); close(w); + // find the highest tainted offset in the input (for trim opt) + s32 i = len; + while (i > 0 && !afl->taint_fsrv.trace_bits[i - 1]) + i--; + q->taint_bytes_highest = i; + + afl->taint_count++; + } else { FATAL("could not create %s", q->fname_taint); - bytes = 0; + q->taint_bytes_all = bytes = 0; } - if (bytes && prev && prev->taint_bytes_all) { + // it is possible that there is no main taint file - if the whole file + // is tainted - but a .new taint file if it had new tainted bytes + + // check if there is a previous queue entry and if it had taint + if (bytes && prev && prev->taint_bytes_all && + prev->taint_bytes_all < prev->len) { // check if there are new bytes in the taint vs the previous int r = open(prev->fname_taint, O_RDONLY); @@ -181,14 +203,28 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, q->taint_bytes_new = count_bytes_len(afl, tmp, plen); + if (afl->debug) + fprintf(stderr, "Debug: %u new taint out of %u bytes\n", bytes, + len); + if (q->taint_bytes_new) { u8 *fnw = alloc_printf("%s.new", q->fname_taint); - int w = open(fnw, O_CREAT | O_WRONLY, 0644); - if (w >= 0) { + if (fnw) { + + int w = open(fnw, O_CREAT | O_WRONLY, 0644); + if (w >= 0) { + + ck_write(w, tmp, plen, fnw); + close(w); - ck_write(w, tmp, plen, fnw); - close(w); + } else { + + q->taint_bytes_new = 0; + + } + + ck_free(fnw); } else { @@ -196,8 +232,6 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, } - ck_free(fnw); - } munmap(bufr, prev->len); @@ -210,10 +244,6 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, } - } else { - - bytes = 0; - } memcpy(afl->taint_fsrv.trace_bits, save, afl->fsrv.map_size); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index aeb290bd..0cc06e12 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -116,6 +116,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "edges_found : %u\n" "var_byte_count : %u\n" "havoc_expansion : %u\n" + "tainted_inputs : %u\n" "afl_banner : %s\n" "afl_version : " VERSION "\n" @@ -149,8 +150,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, #else -1, #endif - t_bytes, afl->var_byte_count, afl->expand_havoc, afl->use_banner, - afl->unicorn_mode ? "unicorn" : "", + t_bytes, afl->var_byte_count, afl->expand_havoc, afl->taint_count, + afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", -- cgit 1.4.1 From af14acf2c148b1aef10414d1dd6c929c49abc11e Mon Sep 17 00:00:00 2001 From: root Date: Fri, 14 Aug 2020 14:35:05 +0200 Subject: Revert "Merge branch 'debug' into dev" This reverts commit a7537b5511ad767d2240cf2dc6d3e261daa676f9, reversing changes made to 15e799f7ae666418e75c6a79db833c5316b21f97. --- GNUmakefile | 3 - README.md | 33 ---- afl_driver.cpp | 191 ----------------------- examples/aflpp_driver/aflpp_driver.c | 40 ++--- include/afl-fuzz.h | 36 +---- include/common.h | 1 - include/envs.h | 1 - include/forkserver.h | 2 - qemu_taint/README.md | 42 ------ qemu_taint/build_qemu_taint.sh | 7 - qemu_taint/clean.sh | 3 - src/afl-common.c | 155 ++++++++++++------- src/afl-forkserver.c | 17 +-- src/afl-fuzz-bitmap.c | 62 +------- src/afl-fuzz-init.c | 42 +----- src/afl-fuzz-one.c | 284 ++++------------------------------- src/afl-fuzz-queue.c | 177 +--------------------- src/afl-fuzz-run.c | 99 ++++-------- src/afl-fuzz-state.c | 30 ++-- src/afl-fuzz-stats.c | 5 +- src/afl-fuzz.c | 127 ++-------------- 21 files changed, 223 insertions(+), 1134 deletions(-) delete mode 100644 afl_driver.cpp delete mode 100644 qemu_taint/README.md delete mode 100755 qemu_taint/build_qemu_taint.sh delete mode 100755 qemu_taint/clean.sh (limited to 'src/afl-common.c') diff --git a/GNUmakefile b/GNUmakefile index ae529ece..f9020a90 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -521,7 +521,6 @@ clean: $(MAKE) -C examples/argv_fuzzing clean $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean - test -d qemu_taint/qemu && { cd qemu_taint ; ./clean.sh ; } rm -rf qemu_mode/qemu-3.1.1 ifeq "$(IN_REPO)" "1" test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl clean || true @@ -532,7 +531,6 @@ endif deepclean: clean rm -rf qemu_mode/qemu-3.1.1.tar.xz - rm -rf qemu_taint/qemu rm -rf unicorn_mode/unicornafl git reset --hard >/dev/null 2>&1 || true @@ -590,7 +588,6 @@ install: all $(MANPAGES) install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) rm -f $${DESTDIR}$(BIN_PATH)/afl-as if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi - if [ -f afl-qemu-taint ]; then install -m 755 afl-qemu-taint $${DESTDIR}$(BIN_PATH); fi if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi diff --git a/README.md b/README.md index b3dc5e45..97c0a0d7 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,3 @@ -# qemu_taint variant. - -UPDATE: **WORKS NOW** **PLEASE TEST** **:-)** - -## HOWTO - -cd qemu_taint && ./build_qemu_taint.sh - -afl-fuzz -A ... - -## CAVEATS - - * llvm shmem persistent mode does not and can not not work - * MOpt works but totally ignores the taint information, so disabled here - * custom mutators? dunno if they work or not. depends on how they work. - * not tested with qemu_mode - * there are several debug checks to ensure the data is fine which slows down - fuzzing, if the beta experiment runs fine these will be improved and it - will result in quite a speed gain. - -## THE TAINT - -taint can be seen in out/taint/ - -the id:000 mirrors the out/queue entry, except the content it 0x00 for -untainted bytes and '!' for tainted bytes. -If a file has new tainted bytes compared to from which previous entry it -was created then there is a id:000[...].new file where the new bytes are -marked '!'. - -the mutation switches between fuzzing all tainted bytes in one cycle and -only new bytes in the other cycle. - # American Fuzzy Lop plus plus (afl++) AFL++ Logo diff --git a/afl_driver.cpp b/afl_driver.cpp deleted file mode 100644 index 7d6a6fd4..00000000 --- a/afl_driver.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -// Platform detection. Copied from FuzzerInternal.h -#ifdef __linux__ -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __APPLE__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __NetBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __FreeBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 -#elif __OpenBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 -#else -#error "Support for your platform has not been implemented" -#endif - -// libFuzzer interface is thin, so we don't include any libFuzzer headers. -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); - -// Notify AFL about persistent mode. -static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -int __afl_persistent_loop(unsigned int); -static volatile char suppress_warning2 = AFL_PERSISTENT[0]; - -// Notify AFL about deferred forkserver. -static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -void __afl_manual_init(); -static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; - -// Input buffer. -static const size_t kMaxAflInputSize = 1024000; -static uint8_t AflInputBuf[kMaxAflInputSize]; - -// Use this optionally defined function to output sanitizer messages even if -// user asks to close stderr. -__attribute__((weak)) void __sanitizer_set_report_fd(void *); - -// Keep track of where stderr content is being written to, so that -// dup_and_close_stderr can use the correct one. -static FILE *output_file = stderr; - -// Experimental feature to use afl_driver without AFL's deferred mode. -// Needs to run before __afl_auto_init. -__attribute__((constructor(0))) static void __decide_deferred_forkserver(void) { - if (getenv("AFL_DRIVER_DONT_DEFER")) { - if (unsetenv("__AFL_DEFER_FORKSRV")) { - perror("Failed to unset __AFL_DEFER_FORKSRV"); - abort(); - } - } -} - -// If the user asks us to duplicate stderr, then do it. -static void maybe_duplicate_stderr() { - char *stderr_duplicate_filename = - getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - - if (!stderr_duplicate_filename) - return; - - FILE *stderr_duplicate_stream = - freopen(stderr_duplicate_filename, "a+", stderr); - - if (!stderr_duplicate_stream) { - fprintf( - stderr, - "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - abort(); - } - output_file = stderr_duplicate_stream; -} - -// Most of these I/O functions were inspired by/copied from libFuzzer's code. -static void discard_output(int fd) { - FILE *temp = fopen("/dev/null", "w"); - if (!temp) - abort(); - dup2(fileno(temp), fd); - fclose(temp); -} - -static void close_stdout() { discard_output(STDOUT_FILENO); } - -// Prevent the targeted code from writing to "stderr" but allow sanitizers and -// this driver to do so. -static void dup_and_close_stderr() { - int output_fileno = fileno(output_file); - int output_fd = dup(output_fileno); - if (output_fd <= 0) - abort(); - FILE *new_output_file = fdopen(output_fd, "w"); - if (!new_output_file) - abort(); - if (!__sanitizer_set_report_fd) - return; - __sanitizer_set_report_fd(reinterpret_cast(output_fd)); - discard_output(output_fileno); -} - -// Close stdout and/or stderr if user asks for it. -static void maybe_close_fd_mask() { - char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK"); - if (!fd_mask_str) - return; - int fd_mask = atoi(fd_mask_str); - if (fd_mask & 2) - dup_and_close_stderr(); - if (fd_mask & 1) - close_stdout(); -} - -// Define LLVMFuzzerMutate to avoid link failures for targets that use it -// with libFuzzer's LLVMFuzzerCustomMutator. -size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); - return 0; -} - -int main(int argc, char **argv) { - printf( - "======================= INFO =========================\n" - "This binary is built for AFL-fuzz.\n" - "To run the target function on individual input(s) execute this:\n" - " %s < INPUT_FILE\n" - "To fuzz with afl-fuzz execute this:\n" - " afl-fuzz [afl-flags] %s [-N]\n" - "afl-fuzz will run N iterations before " - "re-spawning the process (default: 1000)\n" - "======================================================\n", - argv[0], argv[0]); - - maybe_duplicate_stderr(); - maybe_close_fd_mask(); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - // Do any other expensive one-time initialization here. - - int N = 100000; - if (argc == 2 && argv[1][0] == '-') - N = atoi(argv[1] + 1); - else if(argc == 2 && (N = atoi(argv[1])) > 0) - printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); - - assert(N > 0); - - if (!getenv("AFL_DRIVER_DONT_DEFER")) - __afl_manual_init(); - - // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization - // on the first execution of LLVMFuzzerTestOneInput is ignored. - uint8_t dummy_input[1] = {0}; - LLVMFuzzerTestOneInput(dummy_input, 1); - - while (__afl_persistent_loop(N)) { - ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); - if (n_read > 0) { - LLVMFuzzerTestOneInput(AflInputBuf, n_read); - } - } - - printf("%s: successfully executed input(s)\n", argv[0]); -} diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c index 8e0b554a..b764338e 100644 --- a/examples/aflpp_driver/aflpp_driver.c +++ b/examples/aflpp_driver/aflpp_driver.c @@ -106,7 +106,10 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both. #error "Support for your platform has not been implemented" #endif -int __afl_sharedmem_fuzzing = 0; +int __afl_sharedmem_fuzzing = 1; +extern unsigned int * __afl_fuzz_len; +extern unsigned char *__afl_fuzz_ptr; +// extern struct cmp_map *__afl_cmp_map; // libFuzzer interface is thin, so we don't include any libFuzzer headers. int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); @@ -272,7 +275,6 @@ int main(int argc, char **argv) { // Do any other expensive one-time initialization here. uint8_t dummy_input[64] = {0}; - uint8_t buf[1024000]; memcpy(dummy_input, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT)); memcpy(dummy_input + 32, (void *)AFL_DEFER_FORKSVR, sizeof(AFL_DEFER_FORKSVR)); @@ -283,24 +285,16 @@ int main(int argc, char **argv) { printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); else if (argc > 1) { - if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { - - __afl_manual_init(); - - } - + __afl_sharedmem_fuzzing = 0; + __afl_manual_init(); return ExecuteFilesOnyByOne(argc, argv); } assert(N > 0); - if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { - - fprintf(stderr, "performing manual init\n"); - __afl_manual_init(); - - } + // if (!getenv("AFL_DRIVER_DONT_DEFER")) + __afl_manual_init(); // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization // on the first execution of LLVMFuzzerTestOneInput is ignored. @@ -309,13 +303,25 @@ int main(int argc, char **argv) { int num_runs = 0; while (__afl_persistent_loop(N)) { - ssize_t r = read(0, buf, sizeof(buf)); +#ifdef _DEBUG + fprintf(stderr, "CLIENT crc: %016llx len: %u\n", + hash64(__afl_fuzz_ptr, *__afl_fuzz_len, 0xa5b35705), + *__afl_fuzz_len); + fprintf(stderr, "RECV:"); + for (int i = 0; i < *__afl_fuzz_len; i++) + fprintf(stderr, "%02x", __afl_fuzz_ptr[i]); + fprintf(stderr, "\n"); +#endif + if (*__afl_fuzz_len) { + + num_runs++; + LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len); - if (r > 0) { LLVMFuzzerTestOneInput(buf, r); } + } } - printf("%s: successfully executed input(s)\n", argv[0]); + printf("%s: successfully executed %d input(s)\n", argv[0], num_runs); } diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index ad7b0cd6..ca7d10fe 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -133,10 +133,8 @@ extern s32 struct queue_entry { - u8 * fname; /* File name for the test case */ - u8 * fname_taint; /* File name for taint data */ - u32 len; /* Input length */ - struct queue_entry *prev; /* previous queue entry, if any */ + u8 *fname; /* File name for the test case */ + u32 len; /* Input length */ u8 cal_failed, /* Calibration failed? */ trim_done, /* Trimmed? */ @@ -150,10 +148,7 @@ struct queue_entry { is_ascii; /* Is the input just ascii text? */ u32 bitmap_size, /* Number of bits set in bitmap */ - fuzz_level, /* Number of fuzzing iterations */ - taint_bytes_all, /* Number of tainted bytes */ - taint_bytes_new, /* Number of new tainted bytes */ - taint_bytes_highest; /* highest offset in input */ + fuzz_level; /* Number of fuzzing iterations */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ @@ -385,8 +380,6 @@ typedef struct afl_state { char **argv; /* argv if needed */ - char **argv_taint; /* argv for taint mode */ - /* MOpt: Lots of globals, but mostly for the status UI and other things where it really makes no sense to haul them around as function parameters. */ @@ -438,9 +431,7 @@ typedef struct afl_state { *in_bitmap, /* Input bitmap */ *file_extension, /* File extension */ *orig_cmdline, /* Original command line */ - *infoexec, /* Command to execute on a new crash */ - *taint_input_file, /* fuzz_input_one input file */ - *taint_src, *taint_map; + *infoexec; /* Command to execute on a new crash */ u32 hang_tmout; /* Timeout used for hang det (ms) */ @@ -451,9 +442,7 @@ typedef struct afl_state { custom_only, /* Custom mutator only mode */ python_only, /* Python-only mode */ is_main_node, /* if this is the main node */ - is_secondary_node, /* if this is a secondary instance */ - taint_needs_splode, /* explode fuzz input */ - taint_mode; + is_secondary_node; /* if this is a secondary instance */ u32 stats_update_freq; /* Stats update frequency (execs) */ @@ -514,8 +503,7 @@ typedef struct afl_state { useless_at_start, /* Number of useless starting paths */ var_byte_count, /* Bitmap bytes with var behavior */ current_entry, /* Current queue entry ID */ - havoc_div, /* Cycle count divisor for havoc */ - taint_len, taint_count; + havoc_div; /* Cycle count divisor for havoc */ u64 total_crashes, /* Total number of crashes */ unique_crashes, /* Crashes with unique signatures */ @@ -602,9 +590,6 @@ typedef struct afl_state { char * cmplog_binary; afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */ - /* Taint mode */ - afl_forkserver_t taint_fsrv; /* taint mode has its own little forkserver */ - /* Custom mutators */ struct custom_mutator *mutator; @@ -856,8 +841,7 @@ struct custom_mutator { }; -void afl_state_init_1(afl_state_t *, uint32_t map_size); -void afl_state_init_2(afl_state_t *, uint32_t map_size); +void afl_state_init(afl_state_t *, uint32_t map_size); void afl_state_deinit(afl_state_t *); /* Set stop_soon flag on all childs, kill all childs */ @@ -903,7 +887,7 @@ void deinit_py(void *); void mark_as_det_done(afl_state_t *, struct queue_entry *); void mark_as_variable(afl_state_t *, struct queue_entry *); void mark_as_redundant(afl_state_t *, struct queue_entry *, u8); -void add_to_queue(afl_state_t *, u8 *, u8 *, u32, struct queue_entry *, u8); +void add_to_queue(afl_state_t *, u8 *, u32, u8); void destroy_queue(afl_state_t *); void update_bitmap_score(afl_state_t *, struct queue_entry *); void cull_queue(afl_state_t *); @@ -913,9 +897,7 @@ u32 calculate_score(afl_state_t *, struct queue_entry *); void write_bitmap(afl_state_t *); u32 count_bits(afl_state_t *, u8 *); -u32 count_bits_len(afl_state_t *, u8 *, u32); u32 count_bytes(afl_state_t *, u8 *); -u32 count_bytes_len(afl_state_t *, u8 *, u32); u32 count_non_255_bytes(afl_state_t *, u8 *); #ifdef WORD_SIZE_64 void simplify_trace(afl_state_t *, u64 *); @@ -993,8 +975,6 @@ void check_if_tty(afl_state_t *); void setup_signal_handlers(void); void save_cmdline(afl_state_t *, u32, char **); void read_foreign_testcases(afl_state_t *, int); -void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, - u8 *mem, u32 len); /* CmpLog */ diff --git a/include/common.h b/include/common.h index c7d57e07..87a7425b 100644 --- a/include/common.h +++ b/include/common.h @@ -55,7 +55,6 @@ extern u8 *doc_path; /* path to documentation dir */ @returns the path, allocating the string */ u8 *find_binary(u8 *fname); -u8 *find_afl_binary(u8 *fname, u8 *own_loc); /* Read a bitmap from file fname to memory This is for the -B option again. */ diff --git a/include/envs.h b/include/envs.h index bd97b9cd..96ae91ba 100644 --- a/include/envs.h +++ b/include/envs.h @@ -123,7 +123,6 @@ static char *afl_environment_variables[] = { "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", - "AFL_TAINT_INPUT", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", diff --git a/include/forkserver.h b/include/forkserver.h index 59a9f150..0a7390ed 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -80,8 +80,6 @@ typedef struct afl_forkserver { u8 qemu_mode; /* if running in qemu mode or not */ - u8 taint_mode; /* if running taint analysis or not */ - u32 *shmem_fuzz_len; /* length of the fuzzing test case */ u8 *shmem_fuzz; /* allocated memory for fuzzing */ diff --git a/qemu_taint/README.md b/qemu_taint/README.md deleted file mode 100644 index 6a7d19af..00000000 --- a/qemu_taint/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# qemu_taint - -First level taint implementation with qemu for linux user mode - -**THIS IS NOT WORKING YET** **WIP** - -## What is this for - -On new queue entries (newly discovered paths into the target) this tainter -is run with the new input and the data gathered which bytes in the input -file are actually touched. - -Only touched bytes are then fuzzed by afl-fuzz - -## How to build - -./build_qemu_taint.sh - -## How to use - -Add the -A flag to afl-fuzz - -## Caveats - -For some targets this is amazing and improves fuzzing a lot, but if a target -copies all input bytes first (e.g. for creating a crc checksum or just to -safely work with the data), then this is not helping at all. - -## Future - -Two fuzz modes for a queue entry which will be switched back and forth: - - 1. fuzz all touched bytes - 2. fuzz only bytes that are newly touched (compared to the one this queue - entry is based on) - -## TODO - - * Direct trim: trim to highest touched byte, that is all we need to do - * add 5-25% dummy bytes to the queue entries? (maybe create a 2nd one?) - * Disable trim? - diff --git a/qemu_taint/build_qemu_taint.sh b/qemu_taint/build_qemu_taint.sh deleted file mode 100755 index b54c3e04..00000000 --- a/qemu_taint/build_qemu_taint.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -test -d qemu || git clone https://github.com/vanhauser-thc/qemu_taint qemu || exit 1 -cd qemu || exit 1 -test -d .git && { git stash ; git pull ; } -cp -fv ../../include/config.h ../../include/types.h . || exit 1 -./build.sh || exit 1 -cp -fv ./afl-qemu-taint ../.. diff --git a/qemu_taint/clean.sh b/qemu_taint/clean.sh deleted file mode 100755 index 10c44cac..00000000 --- a/qemu_taint/clean.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -rm -f afl-qemu-taint qemu/afl-qemu-taint ../afl-qemu-taint -test -d qemu && { cd qemu ; ./clean.sh ; } diff --git a/src/afl-common.c b/src/afl-common.c index cefed8dc..367dec72 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -138,73 +138,62 @@ void argv_cpy_free(char **argv) { } -u8 *find_afl_binary(u8 *fname, u8 *own_loc) { - - u8 *tmp, *rsl, *own_copy, *cp; - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/%s", tmp, fname); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - return cp; +/* Rewrite argv for QEMU. */ - } +char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { - if (own_loc) { + char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); + u8 * tmp, *cp = NULL, *rsl, *own_copy; - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); + memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); + new_argv[argc - 1] = NULL; - if (rsl) { + new_argv[2] = *target_path_p; + new_argv[1] = "--"; - *rsl = 0; + /* Now we need to actually find the QEMU binary to put in argv[0]. */ - cp = alloc_printf("%s/%s", own_copy, fname); - ck_free(own_copy); + tmp = getenv("AFL_PATH"); - if (!access(cp, X_OK)) { return cp; } + if (tmp) { - } else { + cp = alloc_printf("%s/afl-qemu-trace", tmp); - ck_free(own_copy); + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - } + *target_path_p = new_argv[0] = cp; + return new_argv; } - cp = alloc_printf("%s/%s", BIN_PATH, fname); - if (!access(cp, X_OK)) { return cp; } + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); - ck_free(cp); + if (rsl) { - return NULL; + *rsl = 0; -} + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + ck_free(own_copy); -/* Rewrite argv for QEMU. */ + if (!access(cp, X_OK)) { -char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + *target_path_p = new_argv[0] = cp; + return new_argv; - char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); - u8 * cp = NULL; + } - memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc - 1] = NULL; + } else { - new_argv[2] = *target_path_p; - new_argv[1] = "--"; + ck_free(own_copy); - /* Now we need to actually find the QEMU binary to put in argv[0]. */ + } - cp = find_afl_binary("afl-qemu-trace", own_loc); + if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - if (cp) { + if (cp) { ck_free(cp); } + *target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); - *target_path_p = new_argv[0] = cp; return new_argv; } @@ -236,7 +225,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); - u8 * cp = NULL; + u8 * tmp, *cp = NULL, *rsl, *own_copy; memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); new_argv[argc - 1] = NULL; @@ -245,16 +234,66 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - cp = find_afl_binary("afl-qemu-trace", own_loc); + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/afl-qemu-trace", tmp); - if (cp) { + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } ck_free(cp); - cp = find_afl_binary("afl-wine-trace", own_loc); - if (cp) { + cp = alloc_printf("%s/afl-wine-trace", tmp); - *target_path_p = new_argv[0] = cp; + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } + + *target_path_p = new_argv[0] = cp; + return new_argv; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + + if (cp && !access(cp, X_OK)) { + + ck_free(cp); + + cp = alloc_printf("%s/afl-wine-trace", own_copy); + + if (!access(cp, X_OK)) { + + *target_path_p = new_argv[0] = cp; + return new_argv; + + } + + } + + ck_free(own_copy); + + } else { + + ck_free(own_copy); + + } + + u8 *ncp = BIN_PATH "/afl-qemu-trace"; + + if (!access(ncp, X_OK)) { + + ncp = BIN_PATH "/afl-wine-trace"; + + if (!access(ncp, X_OK)) { + + *target_path_p = new_argv[0] = ck_strdup(ncp); return new_argv; } @@ -262,21 +301,25 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the afl-qemu-trace and afl-wine-trace binaries.\n" - "The afl-qemu-trace binary must be built separately by following the " - "instructions\n" - "in qemu_mode/README.md. If you already have the binary installed, you " - "may need\n" - "to specify the location via AFL_PATH in the environment.\n\n" + "Oops, unable to find the '%s' binary. The binary must be " + "built\n" + " separately by following the instructions in " + "qemu_mode/README.md. " + "If you\n" + " already have the binary installed, you may need to specify " + "AFL_PATH in the\n" + " environment.\n\n" + " Of course, even without QEMU, afl-fuzz can still work with " "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" " traditional non-instrumented fuzzer by specifying '-n' in the " "command " - "line.\n"); + "line.\n", + ncp); - FATAL("Failed to locate 'afl-qemu-trace' and 'afl-wine-trace'."); + FATAL("Failed to locate '%s'.", ncp); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 173cc70f..25983f26 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -498,21 +498,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, char pid_buf[16]; sprintf(pid_buf, "%d", fsrv->fsrv_pid); - - if (fsrv->taint_mode) { - - setenv("__AFL_TARGET_PID3", pid_buf, 1); - - } else if (fsrv->cmplog_binary) { - + if (fsrv->cmplog_binary) setenv("__AFL_TARGET_PID2", pid_buf, 1); - - } else { - + else setenv("__AFL_TARGET_PID1", pid_buf, 1); - } - /* Close the unneeded endpoints. */ close(ctl_pipe[0]); @@ -947,7 +937,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } else { - s32 fd; + s32 fd = fsrv->out_fd; if (fsrv->out_file) { @@ -966,7 +956,6 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } else { - fd = fsrv->out_fd; lseek(fd, 0, SEEK_SET); } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index db57061d..1b9df624 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -177,40 +177,6 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { } -u32 count_bits_len(afl_state_t *afl, u8 *mem, u32 len) { - - u32 *ptr = (u32 *)mem; - u32 i = (len >> 2); - u32 ret = 0; - - (void)(afl); - - if (len % 4) i++; - - while (i--) { - - u32 v = *(ptr++); - - /* This gets called on the inverse, virgin bitmap; optimize for sparse - data. */ - - if (v == 0xffffffff) { - - ret += 32; - continue; - - } - - v -= ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; - - } - - return ret; - -} - /* Count the number of bytes set in the bitmap. Called fairly sporadically, mostly to update the status screen or calibrate and examine confirmed new paths. */ @@ -237,32 +203,6 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) { } -u32 count_bytes_len(afl_state_t *afl, u8 *mem, u32 len) { - - u32 *ptr = (u32 *)mem; - u32 i = (len >> 2); - u32 ret = 0; - - (void)(afl); - - if (len % 4) i++; - - while (i--) { - - u32 v = *(ptr++); - - if (!v) { continue; } - if (v & 0x000000ff) { ++ret; } - if (v & 0x0000ff00) { ++ret; } - if (v & 0x00ff0000) { ++ret; } - if (v & 0xff000000) { ++ret; } - - } - - return ret; - -} - /* Count the number of non-255 bytes set in the bitmap. Used strictly for the status screen, several calls per second or so. */ @@ -655,7 +595,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #endif /* ^!SIMPLE_FILES */ - add_to_queue(afl, queue_fn, mem, len, afl->queue_top, 0); + add_to_queue(afl, queue_fn, len, 0); if (hnb == 2) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 359eef85..350a8599 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -712,7 +712,7 @@ void read_testcases(afl_state_t *afl) { if (!access(dfn, F_OK)) { passed_det = 1; } - add_to_queue(afl, fn2, NULL, st.st_size, NULL, passed_det); + add_to_queue(afl, fn2, st.st_size, passed_det); } @@ -771,13 +771,9 @@ void perform_dry_run(afl_state_t *afl) { close(fd); res = calibrate_case(afl, q, use_mem, 0, 1); + ck_free(use_mem); - if (afl->stop_soon) { - - ck_free(use_mem); - return; - - } + if (afl->stop_soon) { return; } if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { @@ -964,10 +960,6 @@ void perform_dry_run(afl_state_t *afl) { } - /* perform taint gathering on the input seed */ - if (afl->taint_mode) perform_taint_run(afl, q, q->fname, use_mem, q->len); - ck_free(use_mem); - q = q->next; } @@ -1446,10 +1438,6 @@ static void handle_existing_out_dir(afl_state_t *afl) { u8 *orig_q = alloc_printf("%s/queue", afl->out_dir); - u8 *fnt = alloc_printf("%s/taint", afl->out_dir); - mkdir(fnt, 0755); // ignore errors - ck_free(fnt); - afl->in_dir = alloc_printf("%s/_resume", afl->out_dir); rename(orig_q, afl->in_dir); /* Ignore errors */ @@ -1506,20 +1494,6 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); - if (afl->taint_mode) { - - fn = alloc_printf("%s/taint", afl->out_dir); - mkdir(fn, 0755); // ignore errors - - u8 *fn2 = alloc_printf("%s/taint/.input", afl->out_dir); - unlink(fn2); // ignore errors - ck_free(fn2); - - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } - ck_free(fn); - - } - /* All right, let's do out_dir>/crashes/id:* and * out_dir>/hangs/id:*. */ @@ -1747,16 +1721,6 @@ void setup_dirs_fds(afl_state_t *afl) { if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); - /* Taint directory if taint_mode. */ - - if (afl->taint_mode) { - - tmp = alloc_printf("%s/taint", afl->out_dir); - if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } - ck_free(tmp); - - } - /* Top-level directory for queue metadata used for session resume and related tasks. */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 6d52b2b4..57b53c9f 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -458,171 +458,28 @@ u8 fuzz_one_original(afl_state_t *afl) { } - u32 tmp_val = 0; - - if (unlikely(afl->taint_mode)) { - - tmp_val = afl->queue_cycle % 2; // starts with 1 - ret_val = 0; - - if (unlikely(afl->queue_cur->cal_failed && !tmp_val)) goto abandon_entry; - if (unlikely(!afl->skip_deterministic && !afl->queue_cur->passed_det && - !tmp_val)) - goto abandon_entry; - if ((!afl->queue_cur->taint_bytes_new || - afl->queue_cur->taint_bytes_new == afl->queue_cur->len) && - !tmp_val) - goto abandon_entry; - - ret_val = 1; - - s32 dst = 0, i; - temp_len = len = afl->queue_cur->len; - s32 j = 0; // tmp - - fd = open(afl->queue_cur->fname, O_RDONLY); - afl->taint_src = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (fd < 0 || (ssize_t)afl->taint_src == -1) - FATAL("unable to open '%s'", afl->queue_cur->fname); - close(fd); - afl->taint_needs_splode = 1; - - switch (tmp_val) { - - case 1: // fuzz only tainted bytes - - // special case: all or nothing tainted. in this case we act like - // nothing is special. this is not the taint you are looking for ... - if (!afl->queue_cur->taint_bytes_all || - afl->queue_cur->taint_bytes_all == (u32)len) { - - orig_in = in_buf = afl->taint_src; - afl->taint_needs_splode = 0; - break; - - } - - fd = open(afl->taint_input_file, O_RDONLY); - temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_all; - orig_in = in_buf = - mmap(0, len >= MAX_FILE - 65536 ? MAX_FILE : len + 65536, - PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (fd < 0 || (ssize_t)in_buf == -1) - FATAL("unable to open '%s'", afl->taint_input_file); - close(fd); - - fd = open(afl->queue_cur->fname_taint, O_RDONLY); - afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0); - if (fd < 0 || (ssize_t)in_buf == -1) - FATAL("unable to open '%s'", afl->queue_cur->fname_taint); - close(fd); - - for (i = 0; i < (s32)afl->queue_cur->len && dst < len; i++) - if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i]; - - // FIXME DEBUG TODO XXX - for (i = 0; i < (s32)afl->queue_cur->len; i++) { - - switch (afl->taint_map[i]) { - - case 0x0: - break; - case '!': - j++; - break; - default: - FATAL( - "invalid taint map entry byte 0x%02x at position %d " - "(passed_det:%d)\n", - afl->taint_map[i], i, afl->queue_cur->passed_det); - - } - - } - - if (j != len) - FATAL("different taint values in map vs in queue (%d != %d)", j, len); - - break; - - case 0: // fuzz only newly tainted bytes - - fd = open(afl->taint_input_file, O_RDONLY); - temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_new; - orig_in = in_buf = - mmap(0, len >= MAX_FILE - 65536 ? MAX_FILE : len + 65536, - PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (fd < 0 || (ssize_t)in_buf == -1) - FATAL("unable to open '%s'", afl->taint_input_file); - close(fd); - - u8 *fn = alloc_printf("%s.new", afl->queue_cur->fname_taint); - if (!fn) FATAL("OOM"); - fd = open(fn, O_RDWR); - afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0); - if (fd < 0 || (ssize_t)in_buf == -1) - FATAL("unable to open '%s' for %u bytes", fn, len); - close(fd); - ck_free(fn); - - for (i = 0; i < (s32)afl->queue_cur->len && dst < len; i++) - if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i]; - - // FIXME DEBUG TODO XXX - for (i = 0; i < (s32)afl->queue_cur->len; i++) { - - switch (afl->taint_map[i]) { - - case 0x0: - break; - case '!': - j++; - break; - default: - FATAL( - "invalid taint map entry byte 0x%02x at position %d " - "(passed_det:%d)\n", - afl->taint_map[i], i, afl->queue_cur->passed_det); - - } - - } - - if (j != len) - FATAL("different taint values in map vs in queue (%d != %d)", j, len); - - break; - - } - - } else { - - /* Map the test case into memory. */ - - fd = open(afl->queue_cur->fname, O_RDONLY); + /* Map the test case into memory. */ - if (unlikely(fd < 0)) { + fd = open(afl->queue_cur->fname, O_RDONLY); - PFATAL("Unable to open '%s'", afl->queue_cur->fname); + if (unlikely(fd < 0)) { - } + PFATAL("Unable to open '%s'", afl->queue_cur->fname); - len = afl->queue_cur->len; + } - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + len = afl->queue_cur->len; - if (unlikely(orig_in == MAP_FAILED)) { + orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); + if (unlikely(orig_in == MAP_FAILED)) { - } - - close(fd); + PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); } + close(fd); + /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every single byte anyway, so it wouldn't give us any performance or memory usage benefits. */ @@ -645,12 +502,8 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->queue_cur->exec_cksum = 0; - if (unlikely(afl->taint_needs_splode)) - res = calibrate_case(afl, afl->queue_cur, afl->taint_src, - afl->queue_cycle - 1, 0); - else - res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, - 0); + res = + calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -673,8 +526,8 @@ u8 fuzz_one_original(afl_state_t *afl) { * TRIMMING * ************/ - if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done && - !afl->disable_trim && !afl->taint_needs_splode)) { + if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && + !afl->disable_trim) { u8 res = trim_case(afl, afl->queue_cur, in_buf); @@ -711,26 +564,13 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) { - int res; - if (unlikely(afl->taint_needs_splode)) { - - len = afl->queue_cur->len; - memcpy(out_buf, afl->taint_src, len); - res = input_to_state_stage(afl, afl->taint_src, out_buf, len, - afl->queue_cur->exec_cksum); - // just abandon as success - ret_val = 0; - res = 1; - - } else { + if (input_to_state_stage(afl, in_buf, out_buf, len, + afl->queue_cur->exec_cksum)) { - res = input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum); + goto abandon_entry; } - if (unlikely(res)) { goto abandon_entry; } - } /* Skip right away if -d is given, if it has not been chosen sufficiently @@ -2293,18 +2133,8 @@ havoc_stage: if (actually_clone) { - if (unlikely(afl->taint_needs_splode)) { - - clone_len = choose_block_len(afl, afl->queue_cur->len); - clone_from = - rand_below(afl, afl->queue_cur->len - clone_len + 1); - - } else { - - clone_len = choose_block_len(afl, temp_len); - clone_from = rand_below(afl, temp_len - clone_len + 1); - - } + clone_len = choose_block_len(afl, temp_len); + clone_from = rand_below(afl, temp_len - clone_len + 1); } else { @@ -2326,11 +2156,7 @@ havoc_stage: if (actually_clone) { - if (unlikely(afl->taint_needs_splode)) - memcpy(new_buf + clone_to, afl->taint_src + clone_from, - clone_len); - else - memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); + memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); } else { @@ -2342,7 +2168,7 @@ havoc_stage: } /* Tail */ - memmove(new_buf + clone_to + clone_len, out_buf + clone_to, + memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); @@ -2363,49 +2189,16 @@ havoc_stage: if (temp_len < 2) { break; } - if (unlikely(afl->taint_needs_splode)) { - - copy_len = choose_block_len(afl, afl->queue_cur->len - 1); - copy_from = rand_below(afl, afl->queue_cur->len - copy_len + 1); - copy_to = rand_below(afl, temp_len + 1); - - } else { + copy_len = choose_block_len(afl, temp_len - 1); - copy_len = choose_block_len(afl, temp_len - 1); - copy_from = rand_below(afl, temp_len - copy_len + 1); - copy_to = rand_below(afl, temp_len - copy_len + 1); - - } + copy_from = rand_below(afl, temp_len - copy_len + 1); + copy_to = rand_below(afl, temp_len - copy_len + 1); if (rand_below(afl, 4)) { if (copy_from != copy_to) { - if (unlikely(afl->taint_needs_splode)) { - - if (temp_len >= (s32)(copy_to + copy_len)) { - - memcpy(out_buf + copy_to, afl->taint_src + copy_from, - copy_len); - - } else { - - u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), - copy_to + copy_len); - memcpy(new_buf, in_buf, copy_to); - memcpy(new_buf + copy_to, afl->taint_src + copy_from, - copy_len); - swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); - out_buf = new_buf; - temp_len = copy_to + copy_len; - - } - - } else { - - memmove(out_buf + copy_to, out_buf + copy_from, copy_len); - - } + memmove(out_buf + copy_to, out_buf + copy_from, copy_len); } @@ -2671,17 +2464,10 @@ havoc_stage: splices them together at some offset, then relies on the havoc code to mutate that blob. */ - u32 saved_len; - - if (unlikely(afl->taint_needs_splode)) - saved_len = afl->taint_len; - else - saved_len = afl->queue_cur->len; - retry_splicing: if (afl->use_splicing && splice_cycle++ < SPLICE_CYCLES && - afl->queued_paths > 1 && saved_len > 1) { + afl->queued_paths > 1 && afl->queue_cur->len > 1) { struct queue_entry *target; u32 tid, split_at; @@ -2694,7 +2480,7 @@ retry_splicing: if (in_buf != orig_in) { in_buf = orig_in; - len = saved_len; + len = afl->queue_cur->len; } @@ -2765,8 +2551,6 @@ retry_splicing: ret_val = 0; - goto abandon_entry; - /* we are through with this queue entry - for this iteration */ abandon_entry: @@ -2786,17 +2570,7 @@ abandon_entry: ++afl->queue_cur->fuzz_level; - if (unlikely(afl->taint_needs_splode)) { - - munmap(afl->taint_src, afl->queue_cur->len); - munmap(orig_in, afl->taint_len); - munmap(afl->taint_map, afl->queue_cur->len); - - } else { - - munmap(orig_in, afl->queue_cur->len); - - } + munmap(orig_in, afl->queue_cur->len); return ret_val; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 43794018..f35df914 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -103,169 +103,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } -void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname, - u8 *mem, u32 len) { - - u8 * ptr, *fn = fname; - u32 bytes = 0, plen = len; - struct queue_entry *prev = q->prev; - - if (plen % 4) plen = plen + 4 - (len % 4); - - if ((ptr = strrchr(fname, '/')) != NULL) fn = ptr + 1; - q->fname_taint = alloc_printf("%s/taint/%s", afl->out_dir, fn); - - if (q->fname_taint) { - - u8 *save = ck_maybe_grow(BUF_PARAMS(out_scratch), afl->fsrv.map_size); - memcpy(save, afl->taint_fsrv.trace_bits, afl->fsrv.map_size); - - afl->taint_fsrv.map_size = plen; // speed :) - write_to_testcase(afl, mem, len); - if (afl_fsrv_run_target(&afl->taint_fsrv, afl->fsrv.exec_tmout * 4, - &afl->stop_soon) == 0) { - - bytes = q->taint_bytes_all = - count_bytes_len(afl, afl->taint_fsrv.trace_bits, plen); - if (afl->debug) - fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, len); - - /* DEBUG FIXME TODO XXX */ - u32 i; - for (i = 0; i < len; i++) { - - if (afl->taint_fsrv.trace_bits[i] && - afl->taint_fsrv.trace_bits[i] != '!') - FATAL("invalid taint map value %02x at pos %d", - afl->taint_fsrv.trace_bits[i], i); - - } - - if (len < plen) - for (i = len; i < plen; i++) { - - if (afl->taint_fsrv.trace_bits[i]) - FATAL("invalid taint map value %02x in padding at pos %d", - afl->taint_fsrv.trace_bits[i], i); - - } - - } - - // if all is tainted we do not need to write taint data away - if (bytes && bytes < len) { - - // save the bytes away - int w = open(q->fname_taint, O_CREAT | O_WRONLY, 0644); - if (w >= 0) { - - ck_write(w, afl->taint_fsrv.trace_bits, len, q->fname_taint); - close(w); - - // find the highest tainted offset in the input (for trim opt) - s32 i = len; - while (i > 0 && !afl->taint_fsrv.trace_bits[i - 1]) - i--; - q->taint_bytes_highest = i; - - afl->taint_count++; - - } else { - - FATAL("could not create %s", q->fname_taint); - q->taint_bytes_all = bytes = 0; - - } - - // it is possible that there is no main taint file - if the whole file - // is tainted - but a .new taint file if it had new tainted bytes - - // check if there is a previous queue entry and if it had taint - if (bytes && prev && prev->taint_bytes_all && - prev->taint_bytes_all < prev->len) { - - // check if there are new bytes in the taint vs the previous - int r = open(prev->fname_taint, O_RDONLY); - - if (r >= 0) { - - u8 *bufr = mmap(0, prev->len, PROT_READ, MAP_PRIVATE, r, 0); - - if ((ssize_t)bufr != -1) { - - u32 i; - u8 *tmp = ck_maybe_grow(BUF_PARAMS(in_scratch), plen); - memset(tmp, 0, plen); - - for (i = 0; i < len; i++) - if (afl->taint_fsrv.trace_bits[i] && (i >= prev->len || !bufr[i])) - tmp[i] = '!'; - - q->taint_bytes_new = count_bytes_len(afl, tmp, plen); - - if (afl->debug) - fprintf(stderr, "Debug: %u new taint out of %u bytes\n", bytes, - len); - - if (q->taint_bytes_new) { - - u8 *fnw = alloc_printf("%s.new", q->fname_taint); - if (fnw) { - - int w = open(fnw, O_CREAT | O_WRONLY, 0644); - if (w >= 0) { - - ck_write(w, tmp, plen, fnw); - close(w); - - } else { - - FATAL("count not create '%s'", fnw); - q->taint_bytes_new = 0; - - } - - ck_free(fnw); - - } else { - - q->taint_bytes_new = 0; - - } - - } - - munmap(bufr, prev->len); - - } - - close(r); - - } - - } - - } - - memcpy(afl->taint_fsrv.trace_bits, save, afl->fsrv.map_size); - - } - - if (!bytes) { - - q->taint_bytes_highest = q->taint_bytes_all = q->taint_bytes_new = 0; - - if (q->fname_taint) { - - ck_free(q->fname_taint); - q->fname_taint = NULL; - - } - - } - -} - /* check if ascii or UTF-8 */ static u8 check_if_text(struct queue_entry *q) { @@ -375,12 +212,10 @@ static u8 check_if_text(struct queue_entry *q) { /* Append new test case to the queue. */ -void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len, - struct queue_entry *prev_q, u8 passed_det) { +void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { struct queue_entry *q = ck_alloc(sizeof(struct queue_entry)); - q->prev = prev_q; q->fname = fname; q->len = len; q->depth = afl->cur_depth + 1; @@ -419,13 +254,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len, afl->last_path_time = get_cur_time(); - /* trigger the tain gathering if this is not a dry run */ - if (afl->taint_mode && mem) { perform_taint_run(afl, q, fname, mem, len); } - - /* only redqueen currently uses is_ascii */ - if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q); - - /* run custom mutators afl_custom_queue_new_entry() */ if (afl->custom_mutators_count) { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { @@ -445,6 +273,9 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len, } + /* only redqueen currently uses is_ascii */ + if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q); + } /* Destroy the entire queue. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 5381723d..d3f823c9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -350,9 +350,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } - if (unlikely(afl->taint_mode)) - q->exec_cksum = 0; - else if (q->exec_cksum) { + if (q->exec_cksum) { memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); hnb = has_new_bits(afl, afl->virgin_bits); @@ -755,65 +753,56 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { while (remove_pos < q->len) { u32 trim_avail = MIN(remove_len, q->len - remove_pos); + u64 cksum; - if (likely((!q->taint_bytes_highest) || - (q->len - trim_avail > q->taint_bytes_highest))) { + write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); - u64 cksum; + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + ++afl->trim_execs; - write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); + if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } - fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); - ++afl->trim_execs; - - if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } - - /* Note that we don't keep track of crashes or hangs here; maybe TODO? - */ - - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - - /* If the deletion had no impact on the trace, make it permanent. This - isn't perfect for variable-path inputs, but we're just making a - best-effort pass, so it's not a big deal if we end up with false - negatives every now and then. */ - - if (cksum == q->exec_cksum) { + /* Note that we don't keep track of crashes or hangs here; maybe TODO? + */ - u32 move_tail = q->len - remove_pos - trim_avail; + cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - q->len -= trim_avail; - len_p2 = next_pow2(q->len); + /* If the deletion had no impact on the trace, make it permanent. This + isn't perfect for variable-path inputs, but we're just making a + best-effort pass, so it's not a big deal if we end up with false + negatives every now and then. */ - memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, - move_tail); + if (cksum == q->exec_cksum) { - /* Let's save a clean trace, which will be needed by - update_bitmap_score once we're done with the trimming stuff. */ + u32 move_tail = q->len - remove_pos - trim_avail; - if (!needs_write) { + q->len -= trim_avail; + len_p2 = next_pow2(q->len); - needs_write = 1; - memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); + memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, + move_tail); - } + /* Let's save a clean trace, which will be needed by + update_bitmap_score once we're done with the trimming stuff. */ - } else { + if (!needs_write) { - remove_pos += remove_len; + needs_write = 1; + memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); } - /* Since this can be slow, update the screen every now and then. */ - if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } - ++afl->stage_cur; - } else { remove_pos += remove_len; } + /* Since this can be slow, update the screen every now and then. */ + + if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } + ++afl->stage_cur; + } remove_len >>= 1; @@ -866,8 +855,6 @@ abort_trimming: } -#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size - /* Write a modified test case, run program, process results. Handle error conditions, returning 1 if it's time to bail out. This is a helper function for fuzz_one(). */ @@ -877,32 +864,6 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - if (unlikely(afl->taint_needs_splode)) { - - s32 new_len = afl->queue_cur->len + len - afl->taint_len; - if (new_len < 4) - new_len = 4; - else if (new_len > MAX_FILE) - new_len = MAX_FILE; - u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), new_len); - - u32 i, taint = 0; - for (i = 0; i < (u32)new_len; i++) { - - if (i >= afl->taint_len || i >= afl->queue_cur->len || afl->taint_map[i]) - new_buf[i] = out_buf[taint++]; - else - new_buf[i] = afl->taint_src[i]; - - } - - swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); - - out_buf = new_buf; - len = new_len; - - } - write_to_testcase(afl, out_buf, len); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); @@ -950,5 +911,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } -#undef BUF_PARAMS - diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index a8416eb1..d4de91a4 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -75,7 +75,7 @@ static list_t afl_states = {.element_prealloc_count = 0}; /* Initializes an afl_state_t. */ -void afl_state_init_1(afl_state_t *afl, uint32_t map_size) { +void afl_state_init(afl_state_t *afl, uint32_t map_size) { /* thanks to this memset, growing vars like out_buf and out_size are NULL/0 by default. */ @@ -100,6 +100,16 @@ void afl_state_init_1(afl_state_t *afl, uint32_t map_size) { afl->cpu_aff = -1; /* Selected CPU core */ #endif /* HAVE_AFFINITY */ + afl->virgin_bits = ck_alloc(map_size); + afl->virgin_tmout = ck_alloc(map_size); + afl->virgin_crash = ck_alloc(map_size); + afl->var_bytes = ck_alloc(map_size); + afl->top_rated = ck_alloc(map_size * sizeof(void *)); + afl->clean_trace = ck_alloc(map_size); + afl->clean_trace_custom = ck_alloc(map_size); + afl->first_trace = ck_alloc(map_size); + afl->map_tmp_buf = ck_alloc(map_size); + afl->fsrv.use_stdin = 1; afl->fsrv.map_size = map_size; // afl_state_t is not available in forkserver.c @@ -151,24 +161,6 @@ void afl_state_init_1(afl_state_t *afl, uint32_t map_size) { } -void afl_state_init_2(afl_state_t *afl, uint32_t map_size) { - - afl->shm.map_size = map_size ? map_size : MAP_SIZE; - - afl->virgin_bits = ck_alloc(map_size); - afl->virgin_tmout = ck_alloc(map_size); - afl->virgin_crash = ck_alloc(map_size); - afl->var_bytes = ck_alloc(map_size); - afl->top_rated = ck_alloc(map_size * sizeof(void *)); - afl->clean_trace = ck_alloc(map_size); - afl->clean_trace_custom = ck_alloc(map_size); - afl->first_trace = ck_alloc(map_size); - afl->map_tmp_buf = ck_alloc(map_size); - - afl->fsrv.map_size = map_size; - -} - /*This sets up the environment variables for afl-fuzz into the afl_state * struct*/ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 0cc06e12..aeb290bd 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -116,7 +116,6 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "edges_found : %u\n" "var_byte_count : %u\n" "havoc_expansion : %u\n" - "tainted_inputs : %u\n" "afl_banner : %s\n" "afl_version : " VERSION "\n" @@ -150,8 +149,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, #else -1, #endif - t_bytes, afl->var_byte_count, afl->expand_havoc, afl->taint_count, - afl->use_banner, afl->unicorn_mode ? "unicorn" : "", + t_bytes, afl->var_byte_count, afl->expand_havoc, afl->use_banner, + afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 106aa550..5dd092f2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -53,9 +53,6 @@ static void at_exit() { ptr = getenv("__AFL_TARGET_PID2"); if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL); - ptr = getenv("__AFL_TARGET_PID3"); - if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL); - i = 0; while (list[i] != NULL) { @@ -92,8 +89,6 @@ static void usage(u8 *argv0, int more_help) { " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" - " -A - use first level taint analysis (see " - "qemu_taint/README.md)\n" " -p schedule - power schedules compute a seed's performance score. " "debug = 1; } map_size = get_map_size(); - afl_state_init_1(afl, map_size); + afl_state_init(afl, map_size); afl->debug = debug; afl_fsrv_init(&afl->fsrv); @@ -283,15 +277,10 @@ int main(int argc, char **argv_orig, char **envp) { while ((opt = getopt( argc, argv, - "+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QANUWe:p:s:V:E:L:hRP:")) > 0) { + "+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) { switch (opt) { - case 'A': - afl->taint_mode = 1; - if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; } - break; - case 'I': afl->infoexec = optarg; break; @@ -499,7 +488,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!optarg) { FATAL("Wrong usage of -m"); } - if (!strcmp(optarg, "none") || !strcmp(optarg, "0")) { + if (!strcmp(optarg, "none")) { afl->fsrv.mem_limit = 0; break; @@ -829,15 +818,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->taint_mode && afl->fsrv.map_size < MAX_FILE) { - - real_map_size = map_size; - map_size = MAX_FILE; - - } - - afl_state_init_2(afl, map_size); - if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " @@ -845,7 +825,8 @@ int main(int argc, char **argv_orig, char **envp) { OKF("afl++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); OKF("Power schedules from github.com/mboehme/aflfast"); - OKF("Python Mutator from github.com/choller/afl"); + OKF("Python Mutator and llvm_mode instrument file list from " + "github.com/choller/afl"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->is_main_node && @@ -891,19 +872,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->crash_mode) { FATAL("-C 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"); } - if (afl->taint_mode) { FATAL("-A and -n are mutually exclusive"); } - - } - - if (afl->limit_time_sig != 0 && afl->taint_mode) { - - FATAL("-A and -L are mutually exclusive"); - - } - - if (afl->unicorn_mode != 0 && afl->taint_mode) { - - FATAL("-A and -U are mutually exclusive"); } @@ -1004,7 +972,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->afl_env.afl_preload) { - if (afl->fsrv.qemu_mode || afl->taint_mode) { + if (afl->fsrv.qemu_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -1100,13 +1068,6 @@ int main(int argc, char **argv_orig, char **envp) { afl->fsrv.trace_bits = afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); - if (real_map_size && map_size != real_map_size) { - - afl->fsrv.map_size = real_map_size; - if (afl->cmplog_binary) afl->cmplog_fsrv.map_size = real_map_size; - - } - if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); } memset(afl->virgin_tmout, 255, afl->fsrv.map_size); memset(afl->virgin_crash, 255, afl->fsrv.map_size); @@ -1262,6 +1223,7 @@ int main(int argc, char **argv_orig, char **envp) { ACTF("Spawning cmplog forkserver"); afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv); + // TODO: this is semi-nice afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; @@ -1272,70 +1234,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->taint_mode) { - - ACTF("Spawning qemu_taint forkserver"); - - u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); - setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); - - afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv); - afl->taint_fsrv.taint_mode = 1; - afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits; - - ck_free(afl->taint_fsrv.target_path); - afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind)); - afl->taint_fsrv.target_path = find_afl_binary("afl-qemu-taint", argv[0]); - afl->argv_taint[0] = find_afl_binary("afl-qemu-taint", argv[0]); - if (!afl->argv_taint[0]) - FATAL( - "Cannot find 'afl-qemu-taint', read qemu_taint/README.md on how to " - "build it."); - u32 idx = optind - 1, offset = 0; - do { - - idx++; - offset++; - afl->argv_taint[offset] = argv[idx]; - - } while (argv[idx] != NULL); - - if (afl->fsrv.use_stdin) - unsetenv("AFL_TAINT_INPUT"); - else - setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1); - afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon, - afl->afl_env.afl_debug_child_output); - - afl->taint_input_file = alloc_printf("%s/taint/.input", afl->out_dir); - int fd = open(afl->taint_input_file, O_CREAT | O_TRUNC | O_RDWR, 0644); - if (fd < 0) - FATAL("Cannot create taint inpu file '%s'", afl->taint_input_file); - lseek(fd, MAX_FILE, SEEK_SET); - ck_write(fd, "\0", 1, afl->taint_input_file); - - if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); - - OKF("Taint forkserver successfully started"); - - const rlim_t kStackSize = 128L * 1024L * 1024L; // min stack size = 128 Mb - struct rlimit rl; - rl.rlim_cur = kStackSize; - if (getrlimit(RLIMIT_STACK, &rl) != 0) - WARNF("Setting a higher stack size failed!"); - - #define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size - u8 *tmp1 = ck_maybe_grow(BUF_PARAMS(eff), MAX_FILE + 4096); - u8 *tmp2 = ck_maybe_grow(BUF_PARAMS(ex), MAX_FILE + 4096); - u8 *tmp3 = ck_maybe_grow(BUF_PARAMS(in_scratch), MAX_FILE + 4096); - u8 *tmp4 = ck_maybe_grow(BUF_PARAMS(out), MAX_FILE + 4096); - u8 *tmp5 = ck_maybe_grow(BUF_PARAMS(out_scratch), MAX_FILE + 4096); - #undef BUF_PARAMS - if (!tmp1 || !tmp2 || !tmp3 || !tmp4 || !tmp5) - FATAL("memory issues. me hungry, feed me!"); - - } - perform_dry_run(afl); cull_queue(afl); @@ -1410,7 +1308,7 @@ int main(int argc, char **argv_orig, char **envp) { break; case 1: if (afl->limit_time_sig == 0 && !afl->custom_only && - !afl->python_only && !afl->taint_mode) { + !afl->python_only) { afl->limit_time_sig = -1; afl->limit_time_puppet = 0; @@ -1598,11 +1496,8 @@ stop_fuzzing: } - if (afl->cmplog_binary) afl_fsrv_deinit(&afl->cmplog_fsrv); - if (afl->taint_mode) afl_fsrv_deinit(&afl->taint_fsrv); afl_fsrv_deinit(&afl->fsrv); if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } - if (afl->argv_taint) { ck_free(afl->argv_taint); } ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); ck_free(afl->sync_id); -- cgit 1.4.1 From 6c715f1a69f91d4336023a8ba10fb4a7e126f9c2 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 4 Sep 2020 17:04:42 +0200 Subject: more changes to fuzzer_setup --- docs/Changelog.md | 6 +++-- include/afl-fuzz.h | 2 +- include/common.h | 6 +++++ src/afl-common.c | 33 +++++++++++++++++++++++++ src/afl-fuzz-stats.c | 70 ++++++++++++++++++++++++++++------------------------ src/afl-fuzz.c | 3 ++- 6 files changed, 84 insertions(+), 36 deletions(-) (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index d1ee9656..0d93ee1f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,7 +15,7 @@ sending a mail to . https://github.com/AFLplusplus/Grammar-Mutator - a few QOL changes for Apple and its outdated gmake - afl-fuzz: - - Fix for auto dictionary entries found during fuzzing to not throw out + - fix for auto dictionary entries found during fuzzing to not throw out a -x dictionary - added total execs done to plot file - AFL_MAX_DET_EXTRAS env variable added to control the amount of @@ -25,11 +25,13 @@ sending a mail to . timeout. - bugfix for cmplog that results in a heap overflow based on target data (thanks to the magma team for reporting!) + - write fuzzing setup into out/fuzzer_setup (environment variables and + command line) - custom mutators: - added afl_custom_fuzz_count/fuzz_count function to allow specifying the number of fuzz attempts for custom_fuzz - llvm_mode: - - Ported SanCov to LTO, and made it the default for LTO. better + - ported SanCov to LTO, and made it the default for LTO. better instrumentation locations - Further llvm 12 support (fast moving target like afl++ :-) ) - deprecated LLVM SKIPSINGLEBLOCK env environment diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e3c3d5aa..358cb5dc 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -945,7 +945,7 @@ void destroy_extras(afl_state_t *); /* Stats */ -void write_fuzzer_config_file(afl_state_t *); +void write_setup_file(afl_state_t *, int, char **); void write_stats_file(afl_state_t *, double, double, double); void maybe_update_plot_file(afl_state_t *, double, double); void show_stats(afl_state_t *); diff --git a/include/common.h b/include/common.h index 87a7425b..c364ade0 100644 --- a/include/common.h +++ b/include/common.h @@ -110,5 +110,11 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); /* Reads the map size from ENV */ u32 get_map_size(void); +/* create a stream file */ +FILE *create_ffile(u8 *fn); + +/* create a file */ +s32 create_file(u8 *fn); + #endif diff --git a/src/afl-common.c b/src/afl-common.c index 367dec72..d66440aa 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -877,3 +877,36 @@ u32 get_map_size(void) { } +/* Create a stream file */ + +FILE *create_ffile(u8 *fn) { + + s32 fd; + FILE *f; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } + + f = fdopen(fd, "w"); + + if (!f) { PFATAL("fdopen() failed"); } + + return f; + +} + +/* Create a file */ + +s32 create_file(u8 *fn) { + + s32 fd; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } + + return fd; + +} + diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index b59a40e4..a84f1c7a 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -27,51 +27,57 @@ #include "envs.h" #include -/* Open file for writing */ - -inline FILE *open_file(const char *fn) { - - s32 fd; - FILE *f; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); +/* Write fuzzer setup file */ - if (fd < 0) { PFATAL("Unable to create '%s'", fn); } +void write_setup_file(afl_state_t *afl, int argc, char **argv) { - f = fdopen(fd, "w"); + char *val; + u8 fn[PATH_MAX]; + snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); + FILE *f = create_ffile(fn); - if (!f) { PFATAL("fdopen() failed"); } + fprintf(f, "# environment variables:\n"); + u32 s_afl_env = + sizeof(afl_environment_variables) / sizeof(afl_environment_variables[0]) - + 1; + for (u32 i = 0; i < s_afl_env; i++) { - return f; + if ((val = getenv(afl_environment_variables[i])) != NULL) { -} + fprintf(f, "%s=%s\n", afl_environment_variables[i], val); -/* Write fuzzer setup file */ + } -void write_fuzzer_config_file(afl_state_t *afl) { + } - u8 fn[PATH_MAX]; - FILE *f; + fprintf(f, "# command line:\n"); - snprintf(fn, PATH_MAX, "%s/fuzzer_config", afl->out_dir); - f = open_file(fn); + s32 i; + size_t j; + for (i = 0; i < argc; i++) { - char *val; + if (i) fprintf(f, " "); + if (index(argv[i], '\'')) { - uint32_t s_afl_env = - sizeof(afl_environment_variables) / sizeof(afl_environment_variables[0]) - - 1; - for (uint32_t i = 0; i < s_afl_env; i++) { + fprintf(f, "'"); + for (j = 0; j < strlen(argv[i]); j++) + if (argv[i][j] == '\'') + fprintf(f, "'\"'\"'"); + else + fprintf(f, "%c", argv[i][j]); + fprintf(f, "'"); - if ((val = getenv(afl_environment_variables[i])) != NULL) { + } else { - fprintf(f, "%s=%s\n", afl_environment_variables[i], val); + fprintf(f, "'%s'", argv[i]); } } + fprintf(f, "\n"); fclose(f); + (void)(afl_environment_deprecated); } @@ -84,13 +90,13 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, struct rusage rus; #endif - unsigned long long int cur_time = get_cur_time(); - u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits); - u8 fn[PATH_MAX]; - FILE * f; + u64 cur_time = get_cur_time(); + u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits); + u8 fn[PATH_MAX]; + FILE *f; snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); - f = open_file(fn); + f = create_ffile(fn); /* Keep last values in case we're called from another context where exec/sec stats and such are not readily available. */ @@ -209,7 +215,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, if (afl->debug) { - uint32_t i = 0; + u32 i = 0; fprintf(f, "virgin_bytes :"); for (i = 0; i < afl->fsrv.map_size; i++) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e9ea8b62..c12d5db5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1128,6 +1128,8 @@ int main(int argc, char **argv_orig, char **envp) { setup_custom_mutators(afl); + write_setup_file(afl, argc, argv); + setup_cmdline_file(afl, argv + optind); read_testcases(afl); @@ -1274,7 +1276,6 @@ int main(int argc, char **argv_orig, char **envp) { seek_to = find_start_position(afl); - write_fuzzer_config_file(afl); write_stats_file(afl, 0, 0, 0); maybe_update_plot_file(afl, 0, 0); save_auto(afl); -- cgit 1.4.1 From a9ba907676a63777f82c4029f732670c9389e15e Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Sun, 13 Sep 2020 21:25:02 +0900 Subject: Fix qemu argv construction (#555) --- src/afl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index d66440aa..30c67909 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -146,7 +146,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { u8 * tmp, *cp = NULL, *rsl, *own_copy; memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc - 1] = NULL; + new_argv[argc + 2] = NULL; new_argv[2] = *target_path_p; new_argv[1] = "--"; -- cgit 1.4.1 From 060dbe12391b1e4957c09ef8b135f99f2a3bb121 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 13 Sep 2020 14:26:24 +0200 Subject: wine argv fix --- src/afl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 30c67909..ddae2ac1 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -228,7 +228,7 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { u8 * tmp, *cp = NULL, *rsl, *own_copy; memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc - 1] = NULL; + new_argv[argc + 2] = NULL; new_argv[1] = *target_path_p; -- cgit 1.4.1 From 73c0e1357fa33276ca0a0ee63aacc933aa9ceac5 Mon Sep 17 00:00:00 2001 From: bigredb Date: Tue, 20 Oct 2020 05:16:34 -0700 Subject: qemu argv index was still wrong --- src/afl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index ddae2ac1..19c9419b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -146,7 +146,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { u8 * tmp, *cp = NULL, *rsl, *own_copy; memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc + 2] = NULL; + new_argv[argc + 3] = NULL; new_argv[2] = *target_path_p; new_argv[1] = "--"; -- cgit 1.4.1 From 54a312a5fe7d83fcee8b420868bc918622e9b3a6 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Fri, 13 Nov 2020 00:44:08 +0100 Subject: more small fixes --- qemu_mode/libcompcov/pmparser.h | 2 +- qemu_mode/qemuafl | 1 - src/afl-common.c | 2 +- src/afl-fuzz-python.c | 1 + .../samples/persistent/simple_target_noncrashing.c | 16 ++++++++++------ 5 files changed, 13 insertions(+), 9 deletions(-) delete mode 160000 qemu_mode/qemuafl (limited to 'src/afl-common.c') diff --git a/qemu_mode/libcompcov/pmparser.h b/qemu_mode/libcompcov/pmparser.h index 9421d47e..1a3d8834 100644 --- a/qemu_mode/libcompcov/pmparser.h +++ b/qemu_mode/libcompcov/pmparser.h @@ -108,7 +108,6 @@ void pmparser_print(procmaps_struct *map, int order); procmaps_iterator *pmparser_parse(int pid) { - procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator)); char maps_path[500]; if (pid >= 0) { @@ -129,6 +128,7 @@ procmaps_iterator *pmparser_parse(int pid) { } + procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator)); int ind = 0; char buf[PROCMAPS_LINE_MAX_LENGTH]; // int c; diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl deleted file mode 160000 index d66c9e26..00000000 --- a/qemu_mode/qemuafl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d66c9e2654efa8939f0fe6995d11a72b98a4da3e diff --git a/src/afl-common.c b/src/afl-common.c index 19c9419b..8cf1a444 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -342,7 +342,7 @@ u8 *find_binary(u8 *fname) { if (stat(target_path, &st) || !S_ISREG(st.st_mode) || !(st.st_mode & 0111) || st.st_size < 4) { - free(target_path); + ck_free(target_path); FATAL("Program '%s' not found or not executable", fname); } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index fe16bc46..596b733e 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -214,6 +214,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyErr_Print(); fprintf(stderr, "Failed to load \"%s\"\n", module_name); + free(py); return NULL; } diff --git a/unicorn_mode/samples/persistent/simple_target_noncrashing.c b/unicorn_mode/samples/persistent/simple_target_noncrashing.c index 00764473..9257643b 100644 --- a/unicorn_mode/samples/persistent/simple_target_noncrashing.c +++ b/unicorn_mode/samples/persistent/simple_target_noncrashing.c @@ -10,7 +10,7 @@ * Written by Nathan Voss * Adapted by Lukas Seidel */ - +#include int main(int argc, char** argv) { if(argc < 2){ @@ -19,15 +19,19 @@ int main(int argc, char** argv) { char *data_buf = argv[1]; - if len(data_buf < 20) { - if (data_buf[20] != 0) { + if (strlen(data_buf) >= 21 && data_buf[20] != 0) { printf("Not crashing"); - } else if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) { + } else if (strlen(data_buf) > 1 + && data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) { printf("Also not crashing with databuf[0] == %c", data_buf[0]) - } else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) { + } +#if 0 + // not possible with argv (zero terminated strings) (hexcoder-) + // do not try to access data_buf[10] and beyond + else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) { // Cause a crash if data[10] is not zero, but [9] and [11] are zero unsigned char invalid_read = *(unsigned char *) 0x00000000; } - +#endif return 0; } -- cgit 1.4.1 From a2e2fae840e9946c7994ac6807bed8496d71af56 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 3 Dec 2020 14:43:06 +0100 Subject: AFL_CRASH_EXITCODE env var added, u8->bool --- .gitignore | 1 + afl-cmin | 5 +++-- docs/Changelog.md | 4 +++- docs/env_variables.md | 7 +++++++ include/afl-fuzz.h | 7 ++++--- include/common.h | 2 +- include/envs.h | 1 + include/forkserver.h | 21 +++++++++++++-------- src/afl-analyze.c | 4 ++-- src/afl-common.c | 4 ++-- src/afl-forkserver.c | 22 +++++++++++++++------- src/afl-fuzz-init.c | 27 +++++++++++++++++++++++++-- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 26 ++++++++++++++++++++++++-- src/afl-showmap.c | 19 +++++++++++++++++++ src/afl-tmin.c | 32 +++++++++++++++++++++++++------- 16 files changed, 152 insertions(+), 37 deletions(-) (limited to 'src/afl-common.c') diff --git a/.gitignore b/.gitignore index 97f99bf6..82a81605 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.pyc *.dSYM as +a.out ld in out diff --git a/afl-cmin b/afl-cmin index 91ed8d6d..b3b1ead8 100755 --- a/afl-cmin +++ b/afl-cmin @@ -116,11 +116,12 @@ function usage() { "For additional tips, please consult README.md\n" \ "\n" \ "Environment variables used:\n" \ +"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \ +"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \ +"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \ "AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \ "AFL_PATH: path for the afl-showmap binary\n" \ "AFL_SKIP_BIN_CHECK: skip check for target binary\n" \ -"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" -"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" exit 1 } diff --git a/docs/Changelog.md b/docs/Changelog.md index fd30c7b0..02728f10 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -60,8 +60,10 @@ sending a mail to . - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/ - added INTROSPECTION support for custom modules - python fuzz function was not optional, fixed - - unicornafl synced with upstream (arm64 fix, better rust bindings) + - some python mutator speed improvements + - unicornafl synced with upstream version 1.02 (fixes, better rust bindings) - renamed AFL_DEBUG_CHILD_OUTPUT to AFL_DEBUG_CHILD + - added AFL_CRASH_EXITCODE env variable to treat a child exitcode as crash ### Version ++2.68c (release) diff --git a/docs/env_variables.md b/docs/env_variables.md index ada89257..e203055f 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -428,6 +428,13 @@ checks or alter some of the more exotic semantics of the tool: matches your StatsD server. Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`. + - Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash. + For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting + in an `-1` return code (i.e. `exit(-1)` got called), will be treated + as if a crash had ocurred. + This may be beneficial if you look for higher-level faulty conditions in which your + target still exits gracefully. + - Outdated environment variables that are not supported anymore: `AFL_DEFER_FORKSRV` `AFL_PERSISTENT` diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 933af65d..62d76323 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -144,8 +144,8 @@ struct queue_entry { u8 *fname; /* File name for the test case */ u32 len; /* Input length */ - u8 cal_failed, /* Calibration failed? */ - trim_done, /* Trimmed? */ + u8 cal_failed; /* Calibration failed? */ + bool trim_done, /* Trimmed? */ was_fuzzed, /* historical, but needed for MOpt */ passed_det, /* Deterministic stages passed? */ has_new_cov, /* Triggers new coverage? */ @@ -368,7 +368,8 @@ typedef struct afl_env_vars { u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, - *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries; + *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, + *afl_testcache_entries; } afl_env_vars_t; diff --git a/include/common.h b/include/common.h index c364ade0..6e5039d8 100644 --- a/include/common.h +++ b/include/common.h @@ -38,7 +38,7 @@ #define STRINGIFY_VAL_SIZE_MAX (16) -void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin); +void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); void check_environment_vars(char **env); char **argv_cpy_dup(int argc, char **argv); diff --git a/include/envs.h b/include/envs.h index 3aa05cb5..43c87148 100644 --- a/include/envs.h +++ b/include/envs.h @@ -32,6 +32,7 @@ static char *afl_environment_variables[] = { "AFL_CODE_START", "AFL_COMPCOV_BINNAME", "AFL_COMPCOV_LEVEL", + "AFL_CRASH_EXITCODE", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", diff --git a/include/forkserver.h b/include/forkserver.h index 300ecffc..5d5c728f 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -37,9 +37,7 @@ typedef struct afl_forkserver { /* a program that includes afl-forkserver needs to define these */ - u8 uses_asan; /* Target uses ASAN? */ u8 *trace_bits; /* SHM with instrumentation bitmap */ - u8 use_stdin; /* use stdin for sending data */ s32 fsrv_pid, /* PID of the fork server */ child_pid, /* PID of the fuzzed program */ @@ -53,8 +51,6 @@ typedef struct afl_forkserver { fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_st_fd; /* Fork server status pipe (read) */ - u8 no_unlink; /* do not unlink cur_input */ - u32 exec_tmout; /* Configurable exec timeout (ms) */ u32 init_tmout; /* Configurable init timeout (ms) */ u32 map_size; /* map size used by the target */ @@ -73,13 +69,22 @@ typedef struct afl_forkserver { u8 last_kill_signal; /* Signal that killed the child */ - u8 use_shmem_fuzz; /* use shared mem for test cases */ + bool use_shmem_fuzz; /* use shared mem for test cases */ + + bool support_shmem_fuzz; /* set by afl-fuzz */ + + bool use_fauxsrv; /* Fauxsrv for non-forking targets? */ + + bool qemu_mode; /* if running in qemu mode or not */ + + bool use_stdin; /* use stdin for sending data */ - u8 support_shmem_fuzz; /* set by afl-fuzz */ + bool no_unlink; /* do not unlink cur_input */ - u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ + bool uses_asan; /* Target uses ASAN? */ - u8 qemu_mode; /* if running in qemu mode or not */ + bool uses_crash_exitcode; /* Custom crash exitcode specified? */ + u8 crash_exitcode; /* The crash exitcode specified */ u32 *shmem_fuzz_len; /* length of the fuzzing test case */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index c8acebb3..2780deff 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ static s32 dev_null_fd = -1; /* FD to /dev/null */ -static u8 edges_only, /* Ignore hit counts? */ +static bool edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ - use_stdin = 1; /* Use stdin for program input? */ + use_stdin = true; /* Use stdin for program input? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_timed_out; /* Child timed out? */ diff --git a/src/afl-common.c b/src/afl-common.c index 8cf1a444..ed0b0e53 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -46,7 +46,7 @@ u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; -void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { +void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) { u32 i = 0; u8 cwd[PATH_MAX]; @@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); } - *use_stdin = 0; + *use_stdin = false; if (prog_in[0] != 0) { // not afl-showmap special case diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 01ef1d9e..20117c1d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -76,8 +76,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->dev_urandom_fd = -1; /* Settings */ - fsrv->use_stdin = 1; - fsrv->no_unlink = 0; + fsrv->use_stdin = true; + fsrv->no_unlink = false; fsrv->exec_tmout = EXEC_TIMEOUT; fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT; fsrv->mem_limit = MEM_LIMIT; @@ -86,8 +86,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { /* exec related stuff */ fsrv->child_pid = -1; fsrv->map_size = get_map_size(); - fsrv->use_fauxsrv = 0; - fsrv->last_run_timed_out = 0; + fsrv->use_fauxsrv = false; + fsrv->last_run_timed_out = false; + + fsrv->uses_crash_exitcode = false; + fsrv->uses_asan = false; fsrv->init_child_func = fsrv_exec_child; @@ -109,6 +112,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->dev_urandom_fd = from->dev_urandom_fd; fsrv_to->out_fd = from->out_fd; // not sure this is a good idea fsrv_to->no_unlink = from->no_unlink; + fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode; + fsrv_to->crash_exitcode = from->crash_exitcode; // These are forkserver specific. fsrv_to->out_dir_fd = -1; @@ -1136,10 +1141,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and - must use a special exit code. */ + /* MSAN in uses_asan mode uses a special exit code as it doesn't support + abort_on_error. + On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */ - if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) { + if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) || + (fsrv->uses_crash_exitcode && + WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) { fsrv->last_kill_signal = 0; return FSRV_RUN_CRASH; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 0360cdb0..6707340b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) { if (skip_crashes) { - WARNF("Test case results in a crash (skipping)"); + if (afl->fsrv.uses_crash_exitcode) { + + WARNF( + "Test case results in a crash or AFL_CRASH_EXITCODE %d " + "(skipping)", + (int)(s8)afl->fsrv.crash_exitcode); + + } else { + + WARNF("Test case results in a crash (skipping)"); + + } + q->cal_failed = CAL_CHANCES; ++cal_failures; break; @@ -954,7 +966,18 @@ void perform_dry_run(afl_state_t *afl) { #undef MSG_ULIMIT_USAGE #undef MSG_FORK_ON_APPLE - WARNF("Test case '%s' results in a crash, skipping", fn); + if (afl->fsrv.uses_crash_exitcode) { + + WARNF( + "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, " + "skipping", + fn, (int)(s8)afl->fsrv.crash_exitcode); + + } else { + + WARNF("Test case '%s' results in a crash, skipping", fn); + + } /* Remove from fuzzing queue but keep for splicing */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 489d4e53..73b94466 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -394,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_statsd_tags_flavor = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_CRASH_EXITCODE", + + afl_environment_variable_len)) { + + afl->afl_env.afl_crash_exitcode = + (u8 *)get_afl_env(afl_environment_variables[i]); + } } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b91d862d..eb5e9307 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -26,6 +26,7 @@ #include "afl-fuzz.h" #include "cmplog.h" #include +#include #ifndef USEMMAP #include #include @@ -165,6 +166,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n" "AFL_BENCH_JUST_ONE: run the target just once\n" "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n" "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n" "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n" @@ -702,7 +704,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'N': /* Unicorn mode */ if (afl->no_unlink) { FATAL("Multiple -N options not supported"); } - afl->fsrv.no_unlink = afl->no_unlink = 1; + afl->fsrv.no_unlink = (afl->no_unlink = true); break; @@ -1135,6 +1137,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->afl_env.afl_crash_exitcode) { + + long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + afl->afl_env.afl_crash_exitcode); + + } + + afl->fsrv.uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + afl->fsrv.crash_exitcode = (u8)exitcode; + + } + if (afl->non_instrumented_mode == 2 && afl->no_forkserver) { FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); @@ -1486,9 +1505,12 @@ int main(int argc, char **argv_orig, char **envp) { cull_queue(afl); - if (!afl->pending_not_fuzzed) + if (!afl->pending_not_fuzzed) { + FATAL("We need at least on valid input seed that does not crash!"); + } + show_init_stats(afl); if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index a8e7d3f9..e07e76c8 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -667,6 +667,8 @@ static void usage(u8 *argv0) { "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing " "inputs\n" "AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as " + "crash\n" "AFL_DEBUG: enable extra developer output\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the " "size\n" @@ -1090,6 +1092,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (getenv("AFL_CRASH_EXITCODE")) { + + long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + getenv("AFL_CRASH_EXITCODE")); + + } + + fsrv->uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + fsrv->crash_exitcode = (u8)exitcode; + + } + afl_fsrv_start(fsrv, use_argv, &stop_soon, (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e4fb068d..b9045551 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -841,17 +842,17 @@ static void usage(u8 *argv0) { "For additional tips, please consult %s/README.md.\n\n" "Environment variables used:\n" - "TMPDIR: directory to use for temporary input files\n" - "ASAN_OPTIONS: custom settings for ASAN\n" - " (must contain abort_on_error=1 and symbolize=0)\n" - "MSAN_OPTIONS: custom settings for MSAN\n" - " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" + "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" " the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n" - "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" - + "ASAN_OPTIONS: custom settings for ASAN\n" + " (must contain abort_on_error=1 and symbolize=0)\n" + "MSAN_OPTIONS: custom settings for MSAN\n" + " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" + "TMPDIR: directory to use for temporary input files\n" , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); exit(1); @@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (getenv("AFL_CRASH_EXITCODE")) { + + long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + getenv("AFL_CRASH_EXITCODE")); + + } + + fsrv->uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + fsrv->crash_exitcode = (u8)exitcode; + + } + shm_fuzz = ck_alloc(sizeof(sharedmem_t)); /* initialize cmplog_mode */ -- cgit 1.4.1 From 609f3d02651381215815eeadb7a10999c2041ffe Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 11 Dec 2020 13:29:45 +0100 Subject: fixed gcc analyzer warnings --- include/alloc-inl.h | 3 ++- src/afl-as.c | 5 +++++ src/afl-common.c | 24 ++++++++++++++++++++++-- src/afl-fuzz-init.c | 18 +++++++++++++----- src/afl-fuzz-run.c | 12 ++++++------ 5 files changed, 48 insertions(+), 14 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 68255fb6..3044b7a0 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -94,7 +94,8 @@ static inline void *DFL_ck_alloc_nozero(u32 size) { } -/* Allocate a buffer, returning zeroed memory. */ +/* Allocate a buffer, returning zeroed memory. + Returns null for 0 size */ static inline void *DFL_ck_alloc(u32 size) { diff --git a/src/afl-as.c b/src/afl-as.c index 3d6f7d5e..2171bb58 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -131,6 +131,11 @@ static void edit_params(int argc, char **argv) { if (!tmp_dir) { tmp_dir = "/tmp"; } as_params = ck_alloc((argc + 32) * sizeof(u8 *)); + if (unlikely((argc + 32) < argc || !as_params)) { + + FATAL("Too many parameters passed to as"); + + } as_params[0] = afl_as ? afl_as : (u8 *)"as"; diff --git a/src/afl-common.c b/src/afl-common.c index ed0b0e53..4df22394 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -108,6 +108,7 @@ char **argv_cpy_dup(int argc, char **argv) { int i = 0; char **ret = ck_alloc((argc + 1) * sizeof(char *)); + if (unlikely(!ret)) { FATAL("Amount of arguments specified is too high"); } for (i = 0; i < argc; i++) { @@ -130,6 +131,7 @@ void argv_cpy_free(char **argv) { while (argv[i]) { ck_free(argv[i]); + argv[i] = NULL; i++; } @@ -142,8 +144,12 @@ void argv_cpy_free(char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } + + u8 *tmp, *cp = NULL, *rsl, *own_copy; + char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); - u8 * tmp, *cp = NULL, *rsl, *own_copy; + if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); new_argv[argc + 3] = NULL; @@ -224,8 +230,12 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } + + u8 *tmp, *cp = NULL, *rsl, *own_copy; + char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); - u8 * tmp, *cp = NULL, *rsl, *own_copy; + if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); new_argv[argc + 2] = NULL; @@ -335,6 +345,8 @@ u8 *find_binary(u8 *fname) { struct stat st; + if (unlikely(!fname)) { FATAL("No binary supplied"); } + if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { target_path = ck_strdup(fname); @@ -356,6 +368,14 @@ u8 *find_binary(u8 *fname) { if (delim) { cur_elem = ck_alloc(delim - env_path + 1); + if (unlikely(!cur_elem)) { + + FATAL( + "Unexpected overflow when processing ENV. This should never " + "happend."); + + } + memcpy(cur_elem, env_path, delim - env_path); delim++; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 6707340b..0db3a111 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -772,10 +772,17 @@ void perform_dry_run(afl_state_t *afl) { while (q) { - u8 *use_mem; + u8 use_mem[MAX_FILE]; u8 res; s32 fd; + if (unlikely(!q->len)) { + + WARNF("Skipping 0-sized entry in queue (%s)", q->fname); + continue; + + } + u8 *fn = strrchr(q->fname, '/') + 1; ACTF("Attempting dry run with '%s'...", fn); @@ -783,9 +790,8 @@ void perform_dry_run(afl_state_t *afl) { fd = open(q->fname, O_RDONLY); if (fd < 0) { PFATAL("Unable to open '%s'", q->fname); } - use_mem = ck_alloc_nozero(q->len); - - if (read(fd, use_mem, q->len) != (ssize_t)q->len) { + u32 read_len = MIN(q->len, (u32)MAX_FILE); + if (read(fd, use_mem, read_len) != (ssize_t)read_len) { FATAL("Short read from '%s'", q->fname); @@ -794,7 +800,6 @@ void perform_dry_run(afl_state_t *afl) { close(fd); res = calibrate_case(afl, q, use_mem, 0, 1); - ck_free(use_mem); if (afl->stop_soon) { return; } @@ -2449,6 +2454,8 @@ void setup_testcase_shmem(afl_state_t *afl) { void check_binary(afl_state_t *afl, u8 *fname) { + if (unlikely(!fname)) { FATAL("BUG: Binary name is NULL"); } + u8 * env_path = 0; struct stat st; @@ -2477,6 +2484,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { if (delim) { cur_elem = ck_alloc(delim - env_path + 1); + if (unlikely(!cur_elem)) { FATAL("Unexpected large PATH"); } memcpy(cur_elem, env_path, delim - env_path); ++delim; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 5948d83a..b6603f1a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -94,9 +94,9 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { if (unlikely(afl->custom_mutators_count)) { - u8 * new_buf = NULL; ssize_t new_size = len; - void * new_mem = mem; + u8 * new_mem = mem; + u8 * new_buf = NULL; LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { @@ -152,13 +152,13 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, if (unlikely(!mem_trimmed)) { PFATAL("alloc"); } ssize_t new_size = len - skip_len; - void * new_mem = mem; - u8 * new_buf = NULL; + u8 * new_mem = mem; bool post_process_skipped = true; if (unlikely(afl->custom_mutators_count)) { + u8 *new_buf = NULL; new_mem = mem_trimmed; LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { @@ -207,7 +207,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, // If we did post_processing, copy directly from the new_buf bufer - memcpy(afl->fsrv.shmem_fuzz, new_buf, new_size); + memcpy(afl->fsrv.shmem_fuzz, new_mem, new_size); } @@ -265,7 +265,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, if (!post_process_skipped) { - ck_write(fd, new_buf, new_size, afl->fsrv.out_file); + ck_write(fd, new_mem, new_size, afl->fsrv.out_file); } else { -- cgit 1.4.1 From fd6bff727a860220bdd035952a7666c60f444b3f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 17 Dec 2020 22:57:28 +0100 Subject: fix crash for very fast targets --- docs/Changelog.md | 1 + src/afl-common.c | 5 +++++ src/afl-fuzz-stats.c | 2 ++ 3 files changed, 8 insertions(+) (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index c2ed0a12..ac75c68d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ sending a mail to . ### Version ++3.01a (release) + - fix crash for very, very fast targets+systems, thanks for reporting @mhlakhani - added dummy Makefile to instrumentation/ - allow instrumenting LLVMFuzzerTestOneInput diff --git a/src/afl-common.c b/src/afl-common.c index 4df22394..6dc8abe0 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "debug.h" #include "alloc-inl.h" @@ -786,6 +787,10 @@ u8 *u_stringify_float(u8 *buf, double val) { sprintf(buf, "%0.01f", val); + } else if (unlikely(isnan(val) || isfinite(val))) { + + strcpy(buf, "999.9"); + } else { return u_stringify_int(buf, (u64)val); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 321bbb35..50e2ef15 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -371,6 +371,8 @@ void show_stats(afl_state_t *afl) { if (!afl->stats_last_execs) { + if (unlikely(cur_ms == afl->start_time)) --afl->start_time; + afl->stats_avg_exec = ((double)afl->fsrv.total_execs) * 1000 / (cur_ms - afl->start_time); -- cgit 1.4.1 From 03849d147a69cf627746a8ad5f1b653367a56ff5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 23 Dec 2020 17:56:39 +0100 Subject: warn on _AFL and __AFL env vars --- include/alloc-inl.h | 3 ++- src/afl-analyze.c | 11 ++++++----- src/afl-common.c | 4 +++- src/afl-fuzz-bitmap.c | 17 ++++++++++------- src/afl-fuzz-run.c | 2 +- src/afl-showmap.c | 25 ++++++++++++++++--------- src/afl-tmin.c | 11 ++++++----- 7 files changed, 44 insertions(+), 29 deletions(-) (limited to 'src/afl-common.c') 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-common.c b/src/afl-common.c index 6dc8abe0..7914f83a 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; 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 #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-run.c b/src/afl-fuzz-run.c index 32cca579..d53ba546 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -29,7 +29,7 @@ #include #include #if !defined NAME_MAX -#define NAME_MAX _XOPEN_NAME_MAX + #define NAME_MAX _XOPEN_NAME_MAX #endif #include "cmplog.h" 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 -- cgit 1.4.1 From 0b9ca807f2a5e1ef6f43a8cb95356ed21ba3a3e5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 26 Dec 2020 13:15:05 +0100 Subject: fix exec/s display --- src/afl-common.c | 8 ++++++-- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 35 +++++++++++++++++++++-------------- 3 files changed, 28 insertions(+), 17 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 7914f83a..1928663d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -630,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); @@ -789,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-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..cb0d3dcd 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -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); + + } } -- cgit 1.4.1 From c6e038fe25789caa8da777f53154de1bd7b4e178 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Mon, 4 Jan 2021 20:40:53 +0100 Subject: code cleanups (shadowed vars, (un)signed type mismatches, format types, etc.) --- include/afl-fuzz.h | 4 +-- include/config.h | 46 +++++++++++++++--------------- src/afl-analyze.c | 4 +-- src/afl-cc.c | 74 ++++++++++++++++++++++++++++--------------------- src/afl-common.c | 20 ++++++------- src/afl-forkserver.c | 4 +-- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-extras.c | 6 ++-- src/afl-fuzz-mutators.c | 28 ++++++++++++------- src/afl-fuzz-one.c | 24 ++++++++-------- src/afl-fuzz-queue.c | 5 ++-- src/afl-fuzz-redqueen.c | 9 ++++-- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-stats.c | 8 +++--- src/afl-fuzz.c | 8 +++--- src/afl-ld-lto.c | 6 ++-- src/afl-showmap.c | 12 ++++---- src/afl-tmin.c | 4 +-- 18 files changed, 144 insertions(+), 122 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d6a322cc..ede54f0e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -573,7 +573,7 @@ typedef struct afl_state { u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */ - s32 stage_cur, stage_max; /* Stage progression */ + u32 stage_cur, stage_max; /* Stage progression */ s32 splicing_with; /* Splicing with which test case? */ u32 main_node_id, main_node_max; /* Main instance job splitting */ @@ -648,7 +648,7 @@ typedef struct afl_state { double last_avg_execs_saved; /* foreign sync */ -#define FOREIGN_SYNCS_MAX 32 +#define FOREIGN_SYNCS_MAX 32U u8 foreign_sync_cnt; struct foreign_sync foreign_syncs[FOREIGN_SYNCS_MAX]; diff --git a/include/config.h b/include/config.h index e8a49270..7c75e9c9 100644 --- a/include/config.h +++ b/include/config.h @@ -80,11 +80,11 @@ /* Default timeout for fuzzed code (milliseconds). This is the upper bound, also used for detecting hangs; the actual value is auto-scaled: */ -#define EXEC_TIMEOUT 1000 +#define EXEC_TIMEOUT 1000U /* Timeout rounding factor when auto-scaling (milliseconds): */ -#define EXEC_TM_ROUND 20 +#define EXEC_TM_ROUND 20U /* 64bit arch MACRO */ #if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) @@ -93,48 +93,48 @@ /* Default memory limit for child process (MB) 0 = disabled : */ -#define MEM_LIMIT 0 +#define MEM_LIMIT 0U /* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ -#define MEM_LIMIT_QEMU 0 +#define MEM_LIMIT_QEMU 0U /* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ -#define MEM_LIMIT_UNICORN 0 +#define MEM_LIMIT_UNICORN 0U /* Number of calibration cycles per every new test case (and for test cases that show variable behavior): */ -#define CAL_CYCLES 8 -#define CAL_CYCLES_LONG 40 +#define CAL_CYCLES 8U +#define CAL_CYCLES_LONG 40U /* Number of subsequent timeouts before abandoning an input file: */ -#define TMOUT_LIMIT 250 +#define TMOUT_LIMIT 250U /* Maximum number of unique hangs or crashes to record: */ -#define KEEP_UNIQUE_HANG 500 -#define KEEP_UNIQUE_CRASH 5000 +#define KEEP_UNIQUE_HANG 500U +#define KEEP_UNIQUE_CRASH 5000U /* Baseline number of random tweaks during a single 'havoc' stage: */ -#define HAVOC_CYCLES 256 -#define HAVOC_CYCLES_INIT 1024 +#define HAVOC_CYCLES 256U +#define HAVOC_CYCLES_INIT 1024U /* Maximum multiplier for the above (should be a power of two, beware of 32-bit int overflows): */ -#define HAVOC_MAX_MULT 64 -#define HAVOC_MAX_MULT_MOPT 64 +#define HAVOC_MAX_MULT 64U +#define HAVOC_MAX_MULT_MOPT 64U /* Absolute minimum number of havoc cycles (after all adjustments): */ -#define HAVOC_MIN 12 +#define HAVOC_MIN 12U /* Power Schedule Divisor */ -#define POWER_BETA 1 +#define POWER_BETA 1U #define MAX_FACTOR (POWER_BETA * 32) /* Maximum stacking for havoc-stage tweaks. The actual value is calculated @@ -146,19 +146,19 @@ In other words, the default (n = 4) produces 2, 4, 8, 16 stacked tweaks: */ -#define HAVOC_STACK_POW2 4 +#define HAVOC_STACK_POW2 4U /* Caps on block sizes for cloning and deletion operations. Each of these ranges has a 33% probability of getting picked, except for the first two cycles where smaller blocks are favored: */ -#define HAVOC_BLK_SMALL 32 -#define HAVOC_BLK_MEDIUM 128 -#define HAVOC_BLK_LARGE 1500 +#define HAVOC_BLK_SMALL 32U +#define HAVOC_BLK_MEDIUM 128U +#define HAVOC_BLK_LARGE 1500U /* Extra-large blocks, selected very rarely (<5% of the time): */ -#define HAVOC_BLK_XL 32768 +#define HAVOC_BLK_XL 32768U /* Probabilities of skipping non-favored entries in the queue, expressed as percentages: */ @@ -188,11 +188,11 @@ /* Maximum size of input file, in bytes (keep under 100MB): */ -#define MAX_FILE (1 * 1024 * 1024) +#define MAX_FILE (1 * 1024 * 1024U) /* The same, for the test case minimizer: */ -#define TMIN_MAX_FILE (10 * 1024 * 1024) +#define TMIN_MAX_FILE (10 * 1024 * 1024U) /* Block normalization steps for afl-tmin: */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 6dac415b..8fc4434a 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -903,8 +903,8 @@ static void usage(u8 *argv0) { "Execution control settings:\n" " -f file - input file read by the tested program (stdin)\n" - " -t msec - timeout for each run (%d ms)\n" - " -m megs - memory limit for child process (%d MB)\n" + " -t msec - timeout for each run (%u ms)\n" + " -m megs - memory limit for child process (%u MB)\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 " diff --git a/src/afl-cc.c b/src/afl-cc.c index e6a6718e..180ab3c4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -120,8 +120,10 @@ char compiler_mode_string[7][12] = { u8 *getthecwd() { - static u8 fail[] = ""; - if (getcwd(cwd, sizeof(cwd)) == NULL) return fail; + if (getcwd(cwd, sizeof(cwd)) == NULL) { + static u8 fail[] = ""; + return fail; + } return cwd; } @@ -654,9 +656,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - u32 idx; if (lto_mode && argc > 1) { + u32 idx; for (idx = 1; idx < argc; idx++) { if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; @@ -1208,12 +1210,12 @@ int main(int argc, char **argv, char **envp) { if (getenv("AFL_LLVM_INSTRUMENT")) { - u8 *ptr = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); + u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - while (ptr) { + while (ptr2) { - if (strncasecmp(ptr, "afl", strlen("afl")) == 0 || - strncasecmp(ptr, "classic", strlen("classic")) == 0) { + if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || + strncasecmp(ptr2, "classic", strlen("classic")) == 0) { if (instrument_mode == INSTRUMENT_LTO) { @@ -1229,8 +1231,8 @@ int main(int argc, char **argv, char **envp) { } - if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr, "pcguard", strlen("pcguard")) == 0) { + if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) instrument_mode = INSTRUMENT_PCGUARD; @@ -1241,8 +1243,8 @@ int main(int argc, char **argv, char **envp) { } // this is a hidden option - if (strncasecmp(ptr, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr, "llvm-native", strlen("llvm-native")) == 0) { + if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1252,8 +1254,8 @@ int main(int argc, char **argv, char **envp) { } - if (strncasecmp(ptr, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr, "instrim", strlen("instrim")) == 0) { + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { if (instrument_mode == INSTRUMENT_LTO) { @@ -1269,7 +1271,7 @@ int main(int argc, char **argv, char **envp) { } - if (strncasecmp(ptr, "lto", strlen("lto")) == 0) { + if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { lto_mode = 1; if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) @@ -1280,7 +1282,7 @@ int main(int argc, char **argv, char **envp) { } - if (strcasecmp(ptr, "gcc") == 0) { + if (strcasecmp(ptr2, "gcc") == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) instrument_mode = INSTRUMENT_GCC; @@ -1291,7 +1293,7 @@ int main(int argc, char **argv, char **envp) { } - if (strcasecmp(ptr, "clang") == 0) { + if (strcasecmp(ptr2, "clang") == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) instrument_mode = INSTRUMENT_CLANG; @@ -1302,29 +1304,29 @@ int main(int argc, char **argv, char **envp) { } - if (strncasecmp(ptr, "ctx", strlen("ctx")) == 0) { + if (strncasecmp(ptr2, "ctx", strlen("ctx")) == 0) { instrument_opt_mode |= INSTRUMENT_OPT_CTX; setenv("AFL_LLVM_CTX", "1", 1); } - if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) { + if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { - ptr += strlen("ngram"); - while (*ptr && (*ptr < '0' || *ptr > '9')) - ptr++; + ptr2 += strlen("ngram"); + while (*ptr2 && (*ptr2 < '0' || *ptr2 > '9')) + ptr2++; - if (!*ptr) { + if (!*ptr2) { - if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) + if ((ptr2 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) FATAL( "you must set the NGRAM size with (e.g. for value 2) " "AFL_LLVM_INSTRUMENT=ngram-2"); } - ngram_size = atoi(ptr); + ngram_size = atoi(ptr2); if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) FATAL( "NGRAM instrumentation option must be between 2 and " @@ -1332,12 +1334,12 @@ int main(int argc, char **argv, char **envp) { "(%u)", NGRAM_SIZE_MAX); instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); - ptr = alloc_printf("%u", ngram_size); - setenv("AFL_LLVM_NGRAM_SIZE", ptr, 1); + ptr2 = alloc_printf("%u", ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr2, 1); } - ptr = strtok(NULL, ":,;"); + ptr2 = strtok(NULL, ":,;"); } @@ -1448,20 +1450,28 @@ int main(int argc, char **argv, char **envp) { " The best is LTO but it often needs RANLIB and AR settings outside " "of afl-cc.\n\n"); +#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) +#define NATIVE_MSG \ + " NATIVE: use llvm's native PCGUARD instrumentation (less " \ + "performant)\n" +#else +#define NATIVE_MSG "" +#endif + SAYF( "Sub-Modes: (set via env AFL_LLVM_INSTRUMENT, afl-cc selects the best " "available)\n" " PCGUARD: Dominator tree instrumentation (best!) (README.llvm.md)\n" -#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - " NATIVE: use llvm's native PCGUARD instrumentation (less " - "performant)\n" -#endif + + NATIVE_MSG + " CLASSIC: decision target instrumentation (README.llvm.md)\n" " CTX: CLASSIC + 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"); +#undef NATIVE_MSG SAYF( "Features: (see documentation links)\n" @@ -1625,7 +1635,7 @@ int main(int argc, char **argv, char **envp) { if (!instrument_mode) { instrument_mode = INSTRUMENT_CFG; - ptr = instrument_mode_string[instrument_mode]; + //ptr = instrument_mode_string[instrument_mode]; } diff --git a/src/afl-common.c b/src/afl-common.c index 1928663d..21cb6ab4 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -696,16 +696,16 @@ u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - if (!event_ms) { snprintf(buf, len, "none seen yet"); } else { + u64 delta; + s32 t_d, t_h, t_m, t_s; + u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + delta = cur_ms - event_ms; t_d = delta / 1000 / 60 / 60 / 24; @@ -858,16 +858,16 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val) { u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - if (!event_ms) { sprintf(buf, "none seen yet"); } else { + u64 delta; + s32 t_d, t_h, t_m, t_s; + u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + delta = cur_ms - event_ms; t_d = delta / 1000 / 60 / 60 / 24; @@ -895,8 +895,8 @@ u32 get_map_size(void) { map_size = atoi(ptr); if (map_size < 8 || map_size > (1 << 29)) { - FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8, - 1 << 29); + FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8U, + 1U << 29); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 90fa55e9..d6195cb5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -213,7 +213,7 @@ restart_select: static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { unsigned char tmp[4] = {0, 0, 0, 0}; - pid_t child_pid = -1; + pid_t child_pid; if (!be_quiet) { ACTF("Using Fauxserver:"); } @@ -1104,7 +1104,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, "Unable to communicate with fork server. Some possible reasons:\n\n" " - You've run out of memory. Use -m to increase the the memory " "limit\n" - " to something higher than %lld.\n" + " to something higher than %llu.\n" " - The binary or one of the libraries it uses manages to " "create\n" " threads before the forkserver initializes.\n" diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 62a8211c..85a01f98 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -703,7 +703,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (!classified) { classify_counts(&afl->fsrv); - classified = 1; +// classified = 1; } diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 171cce96..04f0878c 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -266,7 +266,7 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len, if (afl->extras_cnt > afl->max_det_extras) { - WARNF("More than %d tokens - will use them probabilistically.", + WARNF("More than %u tokens - will use them probabilistically.", afl->max_det_extras); } @@ -431,7 +431,6 @@ void dedup_extras(afl_state_t *afl) { /* Adds a new extra / dict entry. */ void add_extra(afl_state_t *afl, u8 *mem, u32 len) { - u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX]; u32 i, found = 0; for (i = 0; i < afl->extras_cnt; i++) { @@ -451,6 +450,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) { if (len > MAX_DICT_FILE) { + u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX]; WARNF("Extra '%.*s' is too big (%s, limit is %s), skipping file!", (int)len, mem, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len), stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); @@ -481,7 +481,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) { if (afl->extras_cnt == afl->max_det_extras + 1) { - WARNF("More than %d tokens - will use them probabilistically.", + WARNF("More than %u tokens - will use them probabilistically.", afl->max_det_extras); } diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 0c85458e..5da692d3 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -316,16 +316,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, /* Initialize trimming in the custom mutator */ afl->stage_cur = 0; - afl->stage_max = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len); - if (unlikely(afl->stage_max) < 0) { + s32 retval = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len); + if (unlikely(retval) < 0) { - FATAL("custom_init_trim error ret: %d", afl->stage_max); + FATAL("custom_init_trim error ret: %d", retval); + } else { + + afl->stage_max = retval; + } if (afl->not_on_tty && afl->debug) { - SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, + SAYF("[Custom Trimming] START: Max %u iterations, %u bytes", afl->stage_max, q->len); } @@ -343,7 +347,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (unlikely(!retbuf)) { - FATAL("custom_trim failed (ret %zd)", retlen); + FATAL("custom_trim failed (ret %zu)", retlen); } else if (unlikely(retlen > orig_len)) { @@ -409,7 +413,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (afl->not_on_tty && afl->debug) { - SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", + SAYF("[Custom Trimming] SUCCESS: %u/%u iterations (now at %u bytes)", afl->stage_cur, afl->stage_max, q->len); } @@ -417,16 +421,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, } else { /* Tell the custom mutator that the trimming was unsuccessful */ - afl->stage_cur = mutator->afl_custom_post_trim(mutator->data, 0); - if (unlikely(afl->stage_cur < 0)) { + s32 retval2 = mutator->afl_custom_post_trim(mutator->data, 0); + if (unlikely(retval2 < 0)) { + + FATAL("Error ret in custom_post_trim: %d", retval2); + + } else { - FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); + afl->stage_cur = retval2; } if (afl->not_on_tty && afl->debug) { - SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, + SAYF("[Custom Trimming] FAILURE: %u/%u iterations", afl->stage_cur, afl->stage_max); } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e6fa6064..f9509e86 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -368,7 +368,7 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { u8 fuzz_one_original(afl_state_t *afl) { - s32 len, temp_len; + u32 len, temp_len; u32 j; u32 i; u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; @@ -545,7 +545,7 @@ u8 fuzz_one_original(afl_state_t *afl) { else orig_perf = perf_score = calculate_score(afl, afl->queue_cur); - if (unlikely(perf_score <= 0)) { goto abandon_entry; } + if (unlikely(perf_score == 0)) { goto abandon_entry; } if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) { @@ -902,7 +902,7 @@ u8 fuzz_one_original(afl_state_t *afl) { orig_hit_cnt = new_hit_cnt; - for (i = 0; (s32)i < len - 1; ++i) { + for (i = 0; i < len - 1; ++i) { /* Let's consult the effector map... */ @@ -945,7 +945,7 @@ u8 fuzz_one_original(afl_state_t *afl) { orig_hit_cnt = new_hit_cnt; - for (i = 0; (s32)i < len - 3; ++i) { + for (i = 0; i < len - 3; ++i) { /* Let's consult the effector map... */ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && @@ -1405,7 +1405,7 @@ skip_arith: orig_hit_cnt = new_hit_cnt; - for (i = 0; (s32)i < len - 1; ++i) { + for (i = 0; i < len - 1; ++i) { u16 orig = *(u16 *)(out_buf + i); @@ -1493,7 +1493,7 @@ skip_arith: orig_hit_cnt = new_hit_cnt; - for (i = 0; (s32)i < len - 3; i++) { + for (i = 0; i < len - 3; i++) { u32 orig = *(u32 *)(out_buf + i); @@ -1850,7 +1850,7 @@ custom_mutator_stage: if (unlikely(!mutated_buf)) { - FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size); + FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size); } @@ -2026,7 +2026,7 @@ havoc_stage: el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE); if (unlikely(!custom_havoc_buf)) { - FATAL("Error in custom_havoc (return %zd)", new_len); + FATAL("Error in custom_havoc (return %zu)", new_len); } @@ -2458,7 +2458,7 @@ havoc_stage: u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 extra_len = afl->a_extras[use_extra].len; - if ((s32)extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION @@ -2476,7 +2476,7 @@ havoc_stage: u32 use_extra = rand_below(afl, afl->extras_cnt); u32 extra_len = afl->extras[use_extra].len; - if ((s32)extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION @@ -2577,7 +2577,7 @@ havoc_stage: u32 copy_from, copy_to, copy_len; copy_len = choose_block_len(afl, new_len - 1); - if ((s32)copy_len > temp_len) copy_len = temp_len; + 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); @@ -2952,7 +2952,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { else orig_perf = perf_score = calculate_score(afl, afl->queue_cur); - if (unlikely(perf_score <= 0)) { goto abandon_entry; } + if (unlikely(perf_score == 0)) { goto abandon_entry; } if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 9a0d199e..cd41bafc 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -489,11 +489,12 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { void destroy_queue(afl_state_t *afl) { - struct queue_entry *q; u32 i; for (i = 0; i < afl->queued_paths; i++) { + struct queue_entry *q; + q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); @@ -996,7 +997,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, if (unlikely(!q->testcase_buf)) { - PFATAL("Unable to malloc '%s' with len %d", q->fname, len); + PFATAL("Unable to malloc '%s' with len %u", q->fname, len); } diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index c5db8fa1..7dba1caa 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -445,6 +445,9 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { u32 k; u8 cons_ff = 0, cons_0 = 0; + + if (shape > sizeof(v)) FATAL("shape is greater than %zu, please report!", sizeof(v)); + for (k = 0; k < shape; ++k) { if (b[k] == 0) { @@ -453,7 +456,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { } else if (b[k] == 0xff) { - ++cons_0; + ++cons_ff; } else { @@ -667,12 +670,12 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { u8 status = 0; // opt not in the paper - u32 fails = 0; +// u32 fails = 0; u8 found_one = 0; for (i = 0; i < loggeds; ++i) { - fails = 0; + u32 fails = 0; struct cmpfn_operands *o = &((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i]; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 339fb9c3..11d8204b 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -682,7 +682,7 @@ void sync_fuzzers(afl_state_t *afl) { // same time. If so, the first temporary main node running again will demote // themselves so this is not an issue - u8 path[PATH_MAX]; +// u8 path2[PATH_MAX]; afl->is_main_node = 1; sprintf(path, "%s/is_main_node", afl->out_dir); int fd = open(path, O_CREAT | O_RDWR, 0644); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 1c211da6..c8366174 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -31,7 +31,6 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { - char *val; u8 fn[PATH_MAX]; snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); FILE *f = create_ffile(fn); @@ -44,6 +43,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { for (i = 0; i < s_afl_env; ++i) { + char *val; if ((val = getenv(afl_environment_variables[i])) != NULL) { fprintf(f, "%s=%s\n", afl_environment_variables[i], val); @@ -228,7 +228,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, if (afl->virgin_bits[i] != 0xff) { - fprintf(f, " %d[%02x]", i, afl->virgin_bits[i]); + fprintf(f, " %u[%02x]", i, afl->virgin_bits[i]); } @@ -238,7 +238,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, fprintf(f, "var_bytes :"); for (i = 0; i < afl->fsrv.map_size; i++) { - if (afl->var_bytes[i]) { fprintf(f, " %d", i); } + if (afl->var_bytes[i]) { fprintf(f, " %u", i); } } @@ -1163,7 +1163,7 @@ void show_init_stats(afl_state_t *afl) { } else { - ACTF("-t option specified. We'll use an exec timeout of %d ms.", + ACTF("-t option specified. We'll use an exec timeout of %u ms.", afl->fsrv.exec_tmout); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 897c2f1e..e239b47f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -99,8 +99,8 @@ static void usage(u8 *argv0, int more_help) { " lin, quad> -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-%d ms)\n" - " -m megs - memory limit for child process (%d MB, 0 = no limit)\n" + " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" + " -m megs - memory limit for child process (%u MB, 0 = no limit)\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 " @@ -299,7 +299,7 @@ int main(int argc, char **argv_orig, char **envp) { s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/; u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = MAP_SIZE; + u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = get_map_size(); u8 *extras_dir[4]; u8 mem_limit_given = 0, exit_1 = 0, debug = 0, extras_dir_cnt = 0 /*, have_p = 0*/; @@ -326,7 +326,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; } - map_size = get_map_size(); +// map_size = get_map_size(); afl_state_init(afl, map_size); afl->debug = debug; afl_fsrv_init(&afl->fsrv); diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index fccdb1a5..1d54fda0 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -187,7 +187,7 @@ static void edit_params(int argc, char **argv) { if (debug) DEBUGF( - "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s " + "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s " "inst_present=%s rt_present=%s rt_lto_present=%s\n", passthrough ? "true" : "false", instrim, gold_pos, gold_present ? "true" : "false", inst_present ? "true" : "false", @@ -253,10 +253,10 @@ static void edit_params(int argc, char **argv) { int main(int argc, char **argv) { s32 pid, i, status; - u8 * ptr; +// u8 * ptr; char thecwd[PATH_MAX]; - if ((ptr = getenv("AFL_LD_CALLER")) != NULL) { + if (getenv("AFL_LD_CALLER") != NULL) { FATAL("ld loop detected! Set AFL_REAL_LD!\n"); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 355b2dc3..c0223a07 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -662,7 +662,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 (%d MB)\n" + " -m megs - memory limit for child process (%u MB)\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" @@ -1014,7 +1014,7 @@ int main(int argc, char **argv_orig, char **envp) { DIR * dir_in, *dir_out = NULL; struct dirent *dir_ent; - int done = 0; +// int done = 0; u8 infile[PATH_MAX], outfile[PATH_MAX]; u8 wait_for_gdb = 0; #if !defined(DT_REG) @@ -1090,11 +1090,11 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_DEBUG")) { - int i = optind; + int j = optind; DEBUGF("%s:", fsrv->target_path); - while (argv[i] != NULL) { + while (argv[j] != NULL) { - SAYF(" \"%s\"", argv[i++]); + SAYF(" \"%s\"", argv[j++]); } @@ -1143,7 +1143,7 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - while (done == 0 && (dir_ent = readdir(dir_in))) { + while ((dir_ent = readdir(dir_in))) { if (dir_ent->d_name[0] == '.') { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index ed928c7c..09d97f58 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -835,8 +835,8 @@ static void usage(u8 *argv0) { "Execution control settings:\n" " -f file - input file read by the tested program (stdin)\n" - " -t msec - timeout for each run (%d ms)\n" - " -m megs - memory limit for child process (%d MB)\n" + " -t msec - timeout for each run (%u ms)\n" + " -m megs - memory limit for child process (%u MB)\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 " -- cgit 1.4.1 From 34732e3c5ede9020ff1802f0f0827e3731217dce Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 8 Jan 2021 11:36:40 +0100 Subject: refactored kill signal env parsing --- include/common.h | 5 +++++ src/afl-common.c | 34 ++++++++++++++++++++++++++++++++++ src/afl-fuzz.c | 32 ++++---------------------------- src/afl-showmap.c | 29 ++--------------------------- src/afl-tmin.c | 29 ++--------------------------- 5 files changed, 47 insertions(+), 82 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index 125c3abf..9490ec5f 100644 --- a/include/common.h +++ b/include/common.h @@ -56,6 +56,11 @@ extern u8 *doc_path; /* path to documentation dir */ u8 *find_binary(u8 *fname); +/* Parses the kill signal environment variable, FATALs on error. + If the env is not set, sets the env to default_signal for the signal handlers + and returns the default_signal. */ +int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal); + /* Read a bitmap from file fname to memory This is for the -B option again. */ diff --git a/src/afl-common.c b/src/afl-common.c index 21cb6ab4..3a7d0ce5 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -424,6 +424,40 @@ u8 *find_binary(u8 *fname) { } +/* Parses the kill signal environment variable, FATALs on error. + If the env is not set, sets the env to default_signal for the signal handlers + and returns the default_signal. */ +int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) { + + if (afl_kill_signal_env && afl_kill_signal_env[0]) { + + char *endptr; + u8 signal_code; + signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10); + /* Did we manage to parse the full string? */ + if (*endptr != '\0' || endptr == (char *)afl_kill_signal_env) { + + FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)", + afl_kill_signal_env); + + } + + return signal_code; + + } else { + + char *sigstr = alloc_printf("%d", default_signal); + if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); } + + /* Set the env for signal handler */ + setenv("AFL_KILL_SIGNAL", sigstr, 1); + free(sigstr); + return default_signal; + + } + +} + void check_environment_vars(char **envp) { if (be_quiet) { return; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5c363c63..37f8db8a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -76,9 +76,9 @@ static void at_exit() { } - u8 kill_signal = SIGKILL; + int kill_signal = SIGKILL; - /* AFL_KILL_SIGNAL should already be initialized by afl_fsrv_init() */ + /* AFL_KILL_SIGNAL should already be a valid int at this point */ if (getenv("AFL_KILL_SIGNAL")) { kill_signal = atoi(getenv("AFL_KILL_SIGNAL")); @@ -987,32 +987,8 @@ int main(int argc, char **argv_orig, char **envp) { #endif - afl->fsrv.kill_signal = SIGKILL; - if (afl->afl_env.afl_kill_signal) { - - char *endptr; - u8 signal_code; - signal_code = (u8)strtoul(afl->afl_env.afl_kill_signal, &endptr, 10); - /* Did we manage to parse the full string? */ - if (*endptr != '\0' || endptr == (char *)afl->afl_env.afl_kill_signal) { - - FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)", - afl->afl_env.afl_kill_signal); - - } - - afl->fsrv.kill_signal = signal_code; - - } else { - - char *sigstr = alloc_printf("%d", (int)SIGKILL); - if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); } - - /* Set the env for signal handler */ - setenv("AFL_KILL_SIGNAL", sigstr, 1); - free(sigstr); - - } + afl->fsrv.kill_signal = + parse_afl_kill_signal_env(afl->afl_env.afl_kill_signal, SIGKILL); setup_signal_handlers(); check_asan_opts(afl); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 2c9c38ed..5c9d38e0 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1116,33 +1116,8 @@ int main(int argc, char **argv_orig, char **envp) { } - fsrv->kill_signal = SIGKILL; - char *afl_kill_signal_env = getenv("AFL_KILL_SIGNAL"); - if (afl_kill_signal_env && afl_kill_signal_env[0]) { - - char *endptr; - u8 signal_code; - signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10); - /* Did we manage to parse the full string? */ - if (*endptr != '\0' || endptr == afl_kill_signal_env) { - - FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)", - afl_kill_signal_env); - - } - - fsrv->kill_signal = signal_code; - - } else { - - char *sigstr = alloc_printf("%d", (int)SIGKILL); - if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); } - - /* Set the env for signal handler */ - setenv("AFL_KILL_SIGNAL", sigstr, 1); - free(sigstr); - - } + fsrv->kill_signal = + parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); if (getenv("AFL_CRASH_EXITCODE")) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 342de9c8..6e2d7708 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1135,33 +1135,8 @@ int main(int argc, char **argv_orig, char **envp) { } - fsrv->kill_signal = SIGKILL; - char *afl_kill_signal_env = getenv("AFL_KILL_SIGNAL"); - if (afl_kill_signal_env && afl_kill_signal_env[0]) { - - char *endptr; - u8 signal_code; - signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10); - /* Did we manage to parse the full string? */ - if (*endptr != '\0' || endptr == afl_kill_signal_env) { - - FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)", - afl_kill_signal_env); - - } - - fsrv->kill_signal = signal_code; - - } else { - - char *sigstr = alloc_printf("%d", (int)SIGKILL); - if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); } - - /* Set the env for signal handler */ - setenv("AFL_KILL_SIGNAL", sigstr, 1); - free(sigstr); - - } + fsrv->kill_signal = + parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); if (getenv("AFL_CRASH_EXITCODE")) { -- cgit 1.4.1 From 0ddbffd80e6378bdaf8565caeca3990630574d3f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 12 Jan 2021 17:36:10 +0100 Subject: fix --- src/afl-common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 3a7d0ce5..cf996548 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -927,14 +927,14 @@ u32 get_map_size(void) { if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { map_size = atoi(ptr); - if (map_size < 8 || map_size > (1 << 29)) { + if (!map_size || map_size > (1 << 29)) { - FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8U, + FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 32U, 1U << 29); } - if (map_size % 8) { map_size = (((map_size >> 3) + 1) << 3); } + if (map_size % 32) { map_size = (((map_size >> 5) + 1) << 5); } } -- cgit 1.4.1 From 6f5746d42878207b5d17af71317220932a42ebd7 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 29 Jan 2021 15:38:49 +0100 Subject: AFL_USE_QASAN --- include/common.h | 1 + src/afl-analyze.c | 25 ++++++++++++++++++++ src/afl-common.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-forkserver.c | 4 ++++ src/afl-fuzz.c | 30 +++++++++++++++++++++--- src/afl-showmap.c | 25 ++++++++++++++++++++ src/afl-tmin.c | 25 ++++++++++++++++++++ 7 files changed, 171 insertions(+), 3 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index 9490ec5f..bdaa1735 100644 --- a/include/common.h +++ b/include/common.h @@ -47,6 +47,7 @@ void argv_cpy_free(char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); +u8 *get_libqasan_path(u8 *own_loc); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 0af489fe..28598ba0 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -1078,6 +1078,31 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file) { usage(argv[0]); } + if (qemu_mode && getenv("AFL_USE_QASAN")) { + + u8* preload = getenv("AFL_PRELOAD"); + u8* libqasan = get_libqasan_path(argv_orig[0]); + + if (!preload) { + + setenv("AFL_PRELOAD", libqasan, 0); + + } else { + + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); + strcpy(result, libqasan); + strcat(result, " "); + strcat(result, preload); + + setenv("AFL_PRELOAD", result, 1); + ck_free(result); + + } + + ck_free(libqasan); + + } + map_size = get_map_size(); use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); diff --git a/src/afl-common.c b/src/afl-common.c index cf996548..a69f2e97 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -334,6 +334,70 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } +/* Get libqasan path. */ + +u8 *get_libqasan_path(u8 *own_loc) { + + if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } + + u8 *tmp, *cp = NULL, *rsl, *own_copy; + + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/libqasan.so", tmp); + + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } + + return cp; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/libqasan.so", own_copy); + ck_free(own_copy); + + if (!access(cp, X_OK)) { + + return cp; + + } + + } else { + + ck_free(own_copy); + + } + + if (!access(BIN_PATH "/libqasan.so", X_OK)) { + + if (cp) { ck_free(cp); } + + return ck_strdup(BIN_PATH "/libqasan.so"); + + } + + SAYF("\n" cLRD "[-] " cRST + "Oops, unable to find the 'libqasan.so' binary. The binary must be " + "built\n" + " separately by following the instructions in " + "qemu_mode/libqasan/README.md. " + "If you\n" + " already have the binary installed, you may need to specify " + "AFL_PATH in the\n" + " environment.\n"); + + FATAL("Failed to locate 'libqasan.so'."); + +} + /* Find binary, used by analyze, showmap, tmin @returns the path, allocating the string */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1f5685b0..e59f0d11 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -515,6 +515,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_sigill=0", 0); + /* Envs for QASan */ + setenv("QASAN_MAX_CALL_STACK", "0", 0); + setenv("QASAN_SYMBOLIZE", "0", 0); + /* MSAN is tricky, because it doesn't support abort_on_error=1 at this point. So, we do this in a very hacky way. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e856730e..54850173 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -326,8 +326,32 @@ int main(int argc, char **argv_orig, char **envp) { "compile time)"); } - #endif + + if (getenv("AFL_USE_QASAN")) { + + u8* preload = getenv("AFL_PRELOAD"); + u8* libqasan = get_libqasan_path(argv_orig[0]); + + if (!preload) { + + setenv("AFL_PRELOAD", libqasan, 0); + + } else { + + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); + strcpy(result, libqasan); + strcat(result, " "); + strcat(result, preload); + + setenv("AFL_PRELOAD", result, 1); + ck_free(result); + + } + + ck_free(libqasan); + + } char **argv = argv_cpy_dup(argc, argv_orig); @@ -1245,7 +1269,7 @@ int main(int argc, char **argv_orig, char **envp) { "instead of using AFL_PRELOAD?"); } - + if (afl->afl_env.afl_preload) { if (afl->fsrv.qemu_mode) { @@ -1297,7 +1321,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); } - + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 5a0b6ecf..f3cd5a90 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -942,6 +942,31 @@ int main(int argc, char **argv_orig, char **envp) { } if (optind == argc || !out_file) { usage(argv[0]); } + + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { + + u8* preload = getenv("AFL_PRELOAD"); + u8* libqasan = get_libqasan_path(argv_orig[0]); + + if (!preload) { + + setenv("AFL_PRELOAD", libqasan, 0); + + } else { + + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); + strcpy(result, libqasan); + strcat(result, " "); + strcat(result, preload); + + setenv("AFL_PRELOAD", result, 1); + ck_free(result); + + } + + ck_free(libqasan); + + } if (in_dir) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 5fd60cd2..9e9e2d63 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1074,6 +1074,31 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); + + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { + + u8* preload = getenv("AFL_PRELOAD"); + u8* libqasan = get_libqasan_path(argv_orig[0]); + + if (!preload) { + + setenv("AFL_PRELOAD", libqasan, 0); + + } else { + + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); + strcpy(result, libqasan); + strcat(result, " "); + strcat(result, preload); + + setenv("AFL_PRELOAD", result, 1); + ck_free(result); + + } + + ck_free(libqasan); + + } /* initialize cmplog_mode */ shm.cmplog_mode = 0; -- cgit 1.4.1 From 9d08f0d098c91e69b5fe41674e4c5d05363af604 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 30 Jan 2021 15:39:47 +0100 Subject: added AFL_CMPLOG_ONLY_NEW feature --- docs/Changelog.md | 2 + docs/env_variables.md | 5 ++ include/afl-fuzz.h | 2 +- include/common.h | 2 +- include/envs.h | 1 + src/afl-analyze.c | 22 ++++---- src/afl-common.c | 6 +-- src/afl-fuzz-init.c | 3 ++ src/afl-fuzz-one.c | 5 +- src/afl-fuzz-redqueen.c | 135 +++++++++++++++++++++++++----------------------- src/afl-fuzz-state.c | 7 +++ src/afl-fuzz.c | 35 +++++++------ src/afl-showmap.c | 24 ++++----- src/afl-tmin.c | 24 ++++----- 14 files changed, 147 insertions(+), 126 deletions(-) (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 329b7520..6e59961b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,8 @@ sending a mail to . transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). this is costly hence new command line option -l that sets the intensity (values 1 to 3). recommended is 1 or 2. + - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from + `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - if determinstic mode is active (-D, or -M without -d) then we sync diff --git a/docs/env_variables.md b/docs/env_variables.md index 66d85749..4c3b1cfb 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -287,6 +287,11 @@ checks or alter some of the more exotic semantics of the tool: the target. This must be equal or larger than the size the target was compiled with. + - `AFL_CMPLOG_ONLY_NEW` will only perform the expensive cmplog feature for + newly found testcases and not for testcases that are loaded on startup + (`-i in`). This is an important feature to set when resuming a fuzzing + session. + - `AFL_TESTCACHE_SIZE` allows you to override the size of `#define TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if your fuzzing finds a huge amount of paths for large inputs. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 12db9e4d..e8a21cb5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -384,7 +384,7 @@ typedef struct afl_env_vars { afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, - afl_cycle_schedules, afl_expand_havoc, afl_statsd; + afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, diff --git a/include/common.h b/include/common.h index bdaa1735..bb8831f2 100644 --- a/include/common.h +++ b/include/common.h @@ -47,7 +47,7 @@ void argv_cpy_free(char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); -u8 *get_libqasan_path(u8 *own_loc); +u8 * get_libqasan_path(u8 *own_loc); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/include/envs.h b/include/envs.h index 926c9e27..210b34a6 100644 --- a/include/envs.h +++ b/include/envs.h @@ -28,6 +28,7 @@ static char *afl_environment_variables[] = { "AFL_CC", "AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", + "AFL_CMPLOG_ONLY_NEW", "AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME", diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 28598ba0..20aef2da 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -1079,28 +1079,28 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file) { usage(argv[0]); } if (qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } map_size = get_map_size(); diff --git a/src/afl-common.c b/src/afl-common.c index a69f2e97..235c4c05 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -364,11 +364,7 @@ u8 *get_libqasan_path(u8 *own_loc) { cp = alloc_printf("%s/libqasan.so", own_copy); ck_free(own_copy); - if (!access(cp, X_OK)) { - - return cp; - - } + if (!access(cp, X_OK)) { return cp; } } else { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1808f0a1..2a7864f9 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -25,6 +25,7 @@ #include "afl-fuzz.h" #include +#include "cmplog.h" #ifdef HAVE_AFFINITY @@ -833,6 +834,8 @@ void perform_dry_run(afl_state_t *afl) { } + if (afl->afl_env.afl_cmplog_only_new) { q->colorized = CMPLOG_LVL_MAX; } + u8 *fn = strrchr(q->fname, '/') + 1; ACTF("Attempting dry run with '%s'...", fn); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ff766158..0cf889a8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -26,6 +26,7 @@ #include "afl-fuzz.h" #include #include +#include "cmplog.h" /* MOpt */ @@ -553,7 +554,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(len < 4)) { - afl->queue_cur->colorized = 0xff; + afl->queue_cur->colorized = CMPLOG_LVL_MAX; } else { @@ -2981,7 +2982,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (unlikely(len < 4)) { - afl->queue_cur->colorized = 0xff; + afl->queue_cur->colorized = CMPLOG_LVL_MAX; } else { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index fc620781..d7657c1d 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1118,7 +1118,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, #ifdef ARITHMETIC_LESSER_GREATER if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; } - if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { return 0; } + if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { + + return 0; + + } // transform >= to < and <= to > if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) { @@ -1138,110 +1142,110 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // lesser/greater FP comparison if (attr >= IS_FP && attr < IS_FP_MOD) { - u64 repl_new; - - if (attr & IS_GREATER) { + u64 repl_new; - if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { + if (attr & IS_GREATER) { - float *f = (float *)&repl; - float g = *f; - g += 1.0; - u32 *r = (u32 *)&g; - repl_new = (u32)*r; + if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { - } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) { + float *f = (float *)&repl; + float g = *f; + g += 1.0; + u32 *r = (u32 *)&g; + repl_new = (u32)*r; - double *f = (double *)&repl; - double g = *f; - g += 1.0; + } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) { - u64 *r = (u64 *)&g; - repl_new = *r; + double *f = (double *)&repl; + double g = *f; + g += 1.0; - } else { + u64 *r = (u64 *)&g; + repl_new = *r; - return 0; + } else { - } + return 0; - changed_val = repl_new; + } - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + changed_val = repl_new; - return 1; + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { - } + return 1; - } else { + } - if (SHAPE_BYTES(h->shape) == 4) { + } else { - float *f = (float *)&repl; - float g = *f; - g -= 1.0; - u32 *r = (u32 *)&g; - repl_new = (u32)*r; + if (SHAPE_BYTES(h->shape) == 4) { - } else if (SHAPE_BYTES(h->shape) == 8) { + float *f = (float *)&repl; + float g = *f; + g -= 1.0; + u32 *r = (u32 *)&g; + repl_new = (u32)*r; - double *f = (double *)&repl; - double g = *f; - g -= 1.0; - u64 *r = (u64 *)&g; - repl_new = *r; + } else if (SHAPE_BYTES(h->shape) == 8) { - } else { + double *f = (double *)&repl; + double g = *f; + g -= 1.0; + u64 *r = (u64 *)&g; + repl_new = *r; - return 0; + } else { - } + return 0; - changed_val = repl_new; + } - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + changed_val = repl_new; - return 1; + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { - } + return 1; } - // transform double to float, llvm likes to do that internally ... - if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) { + } - double *f = (double *)&repl; - float g = (float)*f; - repl_new = 0; + // transform double to float, llvm likes to do that internally ... + if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) { + + double *f = (double *)&repl; + float g = (float)*f; + repl_new = 0; #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - memcpy((char *)&repl_new, (char *)&g, 4); + memcpy((char *)&repl_new, (char *)&g, 4); #else - memcpy(((char *)&repl_new) + 4, (char *)&g, 4); + memcpy(((char *)&repl_new) + 4, (char *)&g, 4); #endif - changed_val = repl_new; - h->shape = 3; // modify shape - - // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new); + changed_val = repl_new; + h->shape = 3; // modify shape - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new); - h->shape = 7; // recover shape - return 1; - - } + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { h->shape = 7; // recover shape + return 1; } + h->shape = 7; // recover shape + } + } + else if (attr < IS_FP) { // lesser/greater integer comparison @@ -1707,6 +1711,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape)); } else + #endif { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 8423a3d1..5040e3ef 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -236,6 +236,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_custom_mutator_only = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW", + + afl_environment_variable_len)) { + + afl->afl_env.afl_cmplog_only_new = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_UI", afl_environment_variable_len)) { afl->afl_env.afl_no_ui = diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 312d9424..9d9b0434 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -181,6 +181,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n" "AFL_BENCH_JUST_ONE: run the target just once\n" "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n" + "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n" "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n" "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n" @@ -326,8 +327,9 @@ int main(int argc, char **argv_orig, char **envp) { "compile time)"); } + #endif - + char **argv = argv_cpy_dup(argc, argv_orig); afl_state_t *afl = calloc(1, sizeof(afl_state_t)); @@ -356,8 +358,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:nNo:p:RQs:S:t:T:UV:Wx:Z")) > 0) { switch (opt) { @@ -984,31 +985,31 @@ int main(int argc, char **argv_orig, char **envp) { usage(argv[0], show_help); } - + if (afl->fsrv.qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + afl->afl_env.afl_preload = (u8 *)getenv("AFL_PRELOAD"); ck_free(libqasan); - + } if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; @@ -1270,7 +1271,7 @@ int main(int argc, char **argv_orig, char **envp) { "instead of using AFL_PRELOAD?"); } - + if (afl->afl_env.afl_preload) { if (afl->fsrv.qemu_mode) { @@ -1322,7 +1323,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); } - + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index f3cd5a90..62bf1021 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -942,30 +942,30 @@ int main(int argc, char **argv_orig, char **envp) { } if (optind == argc || !out_file) { usage(argv[0]); } - + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } if (in_dir) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 9e9e2d63..09b5211d 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1074,30 +1074,30 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); - + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } /* initialize cmplog_mode */ -- cgit 1.4.1 From 32110a04c0101a77a43088b85f1465ba321b2bc4 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 1 Feb 2021 15:51:04 +0100 Subject: fixes --- src/afl-common.c | 2 +- src/afl-fuzz.c | 38 ++++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 235c4c05..1cc7f462 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -981,7 +981,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { /* Reads the map size from ENV */ u32 get_map_size(void) { - uint32_t map_size = MAP_SIZE; + uint32_t map_size = (MAP_SIZE << 2); // needed for target ctors :( char * ptr; if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d8ebe097..008ba7d1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1540,6 +1540,7 @@ int main(int argc, char **argv_orig, char **envp) { !afl->unicorn_mode) { afl->fsrv.map_size = 4194304; // dummy temporary value + setenv("AFL_MAP_SIZE", "4194304", 1); u32 new_map_size = afl_fsrv_get_mapsize( &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); @@ -1552,15 +1553,15 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Re-initializing maps to %u bytes", new_map_size); - afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); - afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); - afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); - afl->var_bytes = ck_realloc(afl->var_bytes, map_size); - afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *)); - afl->clean_trace = ck_realloc(afl->clean_trace, map_size); - afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size); - afl->first_trace = ck_realloc(afl->first_trace, map_size); - afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size); + afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); + afl->top_rated = ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); + afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, new_map_size); + afl->first_trace = ck_realloc(afl->first_trace, new_map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); afl_fsrv_kill(&afl->fsrv); afl_shm_deinit(&afl->shm); @@ -1596,6 +1597,7 @@ int main(int argc, char **argv_orig, char **envp) { u32 new_map_size = afl_fsrv_get_mapsize(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); +printf("NEW MAP SIZE2 %u (is %u)\n", new_map_size, map_size); if (new_map_size && new_map_size != 4194304) { @@ -1604,15 +1606,15 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Re-initializing maps to %u bytes due cmplog", new_map_size); - afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); - afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); - afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); - afl->var_bytes = ck_realloc(afl->var_bytes, map_size); - afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *)); - afl->clean_trace = ck_realloc(afl->clean_trace, map_size); - afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size); - afl->first_trace = ck_realloc(afl->first_trace, map_size); - afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size); + afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); + afl->top_rated = ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); + afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, new_map_size); + afl->first_trace = ck_realloc(afl->first_trace, new_map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); afl_fsrv_kill(&afl->fsrv); afl_fsrv_kill(&afl->cmplog_fsrv); -- cgit 1.4.1 From 9bd1e19d7f004b4da6a610b07e59f99d66bb7ec2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 22:43:56 +0100 Subject: added AFL_IGNORE_UNKNOWN_ENVS --- docs/Changelog.md | 3 ++- docs/env_variables.md | 5 ++++- include/envs.h | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- src/afl-cc.c | 1 + src/afl-common.c | 4 ++-- src/afl-fuzz.c | 1 + src/afl-showmap.c | 5 +++-- 8 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 895ab845..71ef4c2c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -61,7 +61,8 @@ sending a mail to . - Added a new example harness to compare python, c, and rust bindings - afl-cmin and afl-showmap now support the -f option - changed default: no memory limit for afl-cmin and afl-cmin.bash - - warn on any _AFL and __AFL env vars + - warn on any _AFL and __AFL env vars. + - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) diff --git a/docs/env_variables.md b/docs/env_variables.md index 886669ad..f7745247 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -5,6 +5,10 @@ users or for some types of custom fuzzing setups. See [README.md](README.md) for the general instruction manual. + Note that most tools will warn on any unknown AFL environment variables. + This is for warning on typos that can happen. If you want to disable this + check then set the `AFL_IGNORE_UNKNOWN_ENVS` environment variable. + ## 1) Settings for all compilers Starting with afl++ 3.0 there is only one compiler: afl-cc @@ -18,7 +22,6 @@ To select the different instrumentation modes this can be done by `MODE` can be one of `LTO` (afl-clang-lto*), `LLVM` (afl-clang-fast*), `GCC_PLUGIN` (afl-g*-fast) or `GCC` (afl-gcc/afl-g++). - Because (with the exception of the --afl-MODE command line option) the compile-time tools do not accept afl specific command-line options, they make fairly broad use of environmental variables instead: diff --git a/include/envs.h b/include/envs.h index 210b34a6..4313e053 100644 --- a/include/envs.h +++ b/include/envs.h @@ -61,6 +61,7 @@ static char *afl_environment_variables[] = { "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", + "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 80c8f917..9b1351b0 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1138,7 +1138,7 @@ void ModuleSanitizerCoverage::InjectTraceForGep( IRBuilder<> IRB(GEP); for (Use &Idx : GEP->indices()) if (!isa(Idx) && Idx->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, + IRB.CreateCall(SanCovTraceGepFunction, {IRB.CreateIntCast(Idx, IntptrTy, true)}); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 9d88f262..d41f79a2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1587,6 +1587,7 @@ int main(int argc, char **argv, char **envp) { "libtokencap.so)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" + " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" " AFL_INST_RATIO: percentage of branches to instrument\n" " AFL_QUIET: suppress verbose output\n" " AFL_HARDEN: adds code hardening to catch memory bugs\n" diff --git a/src/afl-common.c b/src/afl-common.c index 1cc7f462..589aac71 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -523,7 +523,7 @@ void check_environment_vars(char **envp) { if (be_quiet) { return; } int index = 0, issue_detected = 0; - char *env, *val; + char *env, *val, *ignore = getenv("AFL_IGNORE_UNKNOWN_ENVS"); while ((env = envp[index++]) != NULL) { if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 || @@ -582,7 +582,7 @@ void check_environment_vars(char **envp) { } - if (match == 0) { + if (match == 0 && !ignore) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e4139857..e0ac8840 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -198,6 +198,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n" "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n" + "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0d2c5ceb..b40527d3 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1168,8 +1168,9 @@ int main(int argc, char **argv_orig, char **envp) { } - stdin_file = at_file ? strdup(at_file) : (char *) - alloc_printf("%s/.afl-showmap-temp-%u", use_dir, (u32)getpid()); + 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; -- cgit 1.4.1 From 89cf94f0e6afd4d360f7f139f16a6730a07b478d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 20:33:12 +0100 Subject: suggested env vars for lazy ppl --- include/common.h | 1 + qemu_mode/libqasan/dlmalloc.c | 5 ++ src/afl-common.c | 116 ++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 2 + 4 files changed, 124 insertions(+) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index bb8831f2..cd728536 100644 --- a/include/common.h +++ b/include/common.h @@ -39,6 +39,7 @@ #define STRINGIFY_VAL_SIZE_MAX (16) void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); +void print_suggested_envs(char *mispelled_env); void check_environment_vars(char **env); char **argv_cpy_dup(int argc, char **argv); diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index bace0ff6..aff58ad5 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3917,6 +3917,7 @@ static void internal_malloc_stats(mstate m) { \ } else if (RTCHECK(B == smallbin_at(M, I) || \ \ + \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4128,6 +4129,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4144,6 +4146,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4156,12 +4159,14 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-common.c b/src/afl-common.c index 589aac71..0b38b222 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -518,6 +518,120 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) { } +#define HELPER_MIN3(a, b, c) \ + ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) + +// from +// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C +static int string_distance_levenshtein(char *s1, char *s2) { + + unsigned int s1len, s2len, x, y, lastdiag, olddiag; + s1len = strlen(s1); + s2len = strlen(s2); + unsigned int column[s1len + 1]; + for (y = 1; y <= s1len; y++) + column[y] = y; + for (x = 1; x <= s2len; x++) { + + column[0] = x; + for (y = 1, lastdiag = x - 1; y <= s1len; y++) { + + olddiag = column[y]; + column[y] = HELPER_MIN3(column[y] + 1, column[y - 1] + 1, + lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1)); + lastdiag = olddiag; + + } + + } + + return column[s1len]; + +} + +#undef HELPER_MIN3 + +void print_suggested_envs(char *mispelled_env) { + + size_t env_name_len = + strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix + char *env_name = ck_alloc(env_name_len + 1); + memcpy(env_name, mispelled_env + 4, env_name_len); + + char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); + + int j; + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + + char *afl_env = afl_environment_variables[j] + 4; + + int distance = string_distance_levenshtein(afl_env, env_name); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + size_t afl_env_len = strlen(afl_env); + char * reduced = ck_alloc(afl_env_len + 1); + + size_t start = 0; + while (start < afl_env_len) { + + size_t end = start + strcspn(afl_env + start, "_") + 1; + memcpy(reduced, afl_env, start); + if (end < afl_env_len) + memcpy(reduced + start, afl_env + end, afl_env_len - end); + reduced[afl_env_len - end + start] = 0; + + int distance = string_distance_levenshtein(reduced, env_name); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + start = end; + + }; + + } + + char * reduced = ck_alloc(env_name_len + 1); + size_t start = 0; + while (start < env_name_len) { + + size_t end = start + strcspn(env_name + start, "_") + 1; + memcpy(reduced, env_name, start); + if (end < env_name_len) + memcpy(reduced + start, env_name + end, env_name_len - end); + reduced[env_name_len - end + start] = 0; + + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + + int distance = string_distance_levenshtein( + afl_environment_variables[j] + 4, reduced); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + } + + start = end; + + }; + + ck_free(env_name); + ck_free(reduced); + ck_free(seen); + +} + void check_environment_vars(char **envp) { if (be_quiet) { return; } @@ -587,6 +701,8 @@ void check_environment_vars(char **envp) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; + print_suggested_envs(env); + } } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 5040e3ef..3d36e712 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -486,6 +486,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; + print_suggested_envs(env); + } } -- cgit 1.4.1 From 62767a42dc2101a67eeb723ca94f5bf853525d60 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 20:40:38 +0100 Subject: improved env suggestions --- src/afl-common.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 0b38b222..531753c2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -551,6 +551,8 @@ static int string_distance_levenshtein(char *s1, char *s2) { #undef HELPER_MIN3 +#define ENV_SIMILARITY_TRESHOLD 3 + void print_suggested_envs(char *mispelled_env) { size_t env_name_len = @@ -559,20 +561,28 @@ void print_suggested_envs(char *mispelled_env) { memcpy(env_name, mispelled_env + 4, env_name_len); char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); + int found = 0; int j; for (j = 0; afl_environment_variables[j] != NULL; ++j) { char *afl_env = afl_environment_variables[j] + 4; - int distance = string_distance_levenshtein(afl_env, env_name); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; + found = 1; } + + } + + if (found) goto cleanup; + + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + char *afl_env = afl_environment_variables[j] + 4; size_t afl_env_len = strlen(afl_env); char * reduced = ck_alloc(afl_env_len + 1); @@ -586,10 +596,11 @@ void print_suggested_envs(char *mispelled_env) { reduced[afl_env_len - end + start] = 0; int distance = string_distance_levenshtein(reduced, env_name); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; + found = 1; } @@ -599,6 +610,8 @@ void print_suggested_envs(char *mispelled_env) { } + if (found) goto cleanup; + char * reduced = ck_alloc(env_name_len + 1); size_t start = 0; while (start < env_name_len) { @@ -613,7 +626,7 @@ void print_suggested_envs(char *mispelled_env) { int distance = string_distance_levenshtein( afl_environment_variables[j] + 4, reduced); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; @@ -626,8 +639,10 @@ void print_suggested_envs(char *mispelled_env) { }; - ck_free(env_name); ck_free(reduced); + +cleanup: + ck_free(env_name); ck_free(seen); } -- cgit 1.4.1 From 974aab6cf6aa4ae34ee73bdceed1bd44a212fc5e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 17:53:09 +0100 Subject: cmplog config.h -> -l option --- include/afl-fuzz.h | 1 + include/config.h | 9 ++---- src/afl-common.c | 8 ++--- src/afl-fuzz-redqueen.c | 83 +++++++++++++++++++++++++------------------------ src/afl-fuzz.c | 46 ++++++++++++++++++++------- 5 files changed, 85 insertions(+), 62 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1d5ec1f0..10d94fed 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -649,6 +649,7 @@ typedef struct afl_state { u32 cmplog_max_filesize; u32 cmplog_lvl; u32 colorize_success; + u8 cmplog_enable_arith, cmplog_enable_transform; struct afl_pass_stat *pass_stats; struct cmp_map * orig_cmp_map; diff --git a/include/config.h b/include/config.h index 9f7db04d..535ce0d3 100644 --- a/include/config.h +++ b/include/config.h @@ -42,13 +42,8 @@ * */ -/* Enable arithmetic compare solving for both branches */ -#define CMPLOG_SOLVE_ARITHMETIC - -/* Enable transform following (XOR/ADD/SUB manipulations, hex en/decoding) */ -#define CMPLOG_SOLVE_TRANSFORM - -/* if TRANSFORM is enabled, this additionally enables base64 en/decoding */ +/* if TRANSFORM is enabled with '-l T', this additionally enables base64 + encoding/decoding */ // #define CMPLOG_SOLVE_TRANSFORM_BASE64 /* If a redqueen pass finds more than one solution, try to combine them? */ diff --git a/src/afl-common.c b/src/afl-common.c index 531753c2..ce63c262 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -561,13 +561,13 @@ void print_suggested_envs(char *mispelled_env) { memcpy(env_name, mispelled_env + 4, env_name_len); char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); - int found = 0; + int found = 0; int j; for (j = 0; afl_environment_variables[j] != NULL; ++j) { char *afl_env = afl_environment_variables[j] + 4; - int distance = string_distance_levenshtein(afl_env, env_name); + int distance = string_distance_levenshtein(afl_env, env_name); if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); @@ -575,14 +575,14 @@ void print_suggested_envs(char *mispelled_env) { found = 1; } - + } if (found) goto cleanup; for (j = 0; afl_environment_variables[j] != NULL; ++j) { - char *afl_env = afl_environment_variables[j] + 4; + char * afl_env = afl_environment_variables[j] + 4; size_t afl_env_len = strlen(afl_env); char * reduced = ck_alloc(afl_env_len + 1); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index d77baf25..1ab5f996 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -30,7 +30,6 @@ //#define _DEBUG //#define CMPLOG_INTROSPECTION -#define CMPLOG_COMBINE // CMP attribute enum enum { @@ -523,7 +522,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -#ifdef CMPLOG_SOLVE_TRANSFORM +//#ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -608,7 +607,7 @@ static int is_hex(const char *str) { } - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // tests 4 bytes at location static int is_base64(const char *str) { @@ -721,10 +720,10 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } - #endif - #endif +//#endif + static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -748,9 +747,9 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // o_pattern, pattern, repl, changed_val, idx, taint_len, // h->shape + 1, attr); -#ifdef CMPLOG_SOLVE_TRANSFORM + //#ifdef CMPLOG_SOLVE_TRANSFORM // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 - if (lvl & LVL3) { + if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 * endptr; u8 use_num = 0, use_unum = 0; @@ -771,11 +770,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - #ifdef _DEBUG +#ifdef _DEBUG if (idx == 0) fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n", afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern); - #endif +#endif // num is likely not pattern as atoi("AAA") will be zero... if (use_num && ((u64)num == pattern || !num)) { @@ -1060,7 +1059,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } -#endif + //#endif // we only allow this for ascii2integer (above) so leave if this is the case if (unlikely(pattern == o_pattern)) { return 0; } @@ -1215,8 +1214,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) -#ifdef CMPLOG_SOLVE_ARITHMETIC - if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; } + //#ifdef CMPLOG_SOLVE_ARITHMETIC + if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { + + return 0; + + } if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { @@ -1321,11 +1324,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, double *f = (double *)&repl; float g = (float)*f; repl_new = 0; - #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) memcpy((char *)&repl_new, (char *)&g, 4); - #else +#else memcpy(((char *)&repl_new) + 4, (char *)&g, 4); - #endif +#endif changed_val = repl_new; h->shape = 3; // modify shape @@ -1380,7 +1383,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } -#endif /* CMPLOG_SOLVE_ARITHMETIC */ + //#endif /* CMPLOG_SOLVE_ARITHMETIC return 0; @@ -1539,7 +1542,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { for (k = 0; k < size; ++k) { #else - u32 off = 16 - size; + u32 off = 16 - size; for (k = 16 - size; k < 16; ++k) { #endif @@ -1857,9 +1860,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, #ifndef CMPLOG_COMBINE (void)(cbuf); #endif -#ifndef CMPLOG_SOLVE_TRANSFORM - (void)(changed_val); -#endif + //#ifndef CMPLOG_SOLVE_TRANSFORM + // (void)(changed_val); + //#endif u8 save[40]; u32 saved_idx = idx, pre, from = 0, to = 0, i, j; @@ -1939,16 +1942,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } -#ifdef CMPLOG_SOLVE_TRANSFORM + //#ifdef CMPLOG_SOLVE_TRANSFORM if (*status == 1) return 0; - if (lvl & LVL3) { + if (afl->cmplog_enable_transform && (lvl & LVL3)) { u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0; - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 u32 tob64 = 0, fromb64 = 0; - #endif +#endif u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0; u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0; u8 xor_val[32], arith_val[32], tmp[48]; @@ -2044,7 +2047,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 if (i % 3 == 2 && i < 24) { if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; @@ -2057,7 +2060,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #endif +#endif if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) { @@ -2085,20 +2088,20 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef _DEBUG +#ifdef _DEBUG fprintf(stderr, "RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " "from_0=%u from_slash=%u from_x=%u\n", idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0, to_slash, to_x, from_0, from_slash, from_x); - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 + #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64, fromb64); - #endif #endif +#endif - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // input is base64 and converted to binary? convert repl to base64! if ((i % 4) == 3 && i < 24 && fromb64 > i) { @@ -2121,7 +2124,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #endif +#endif // input is converted to hex? convert repl to binary! if (i < 16 && tohex > i) { @@ -2250,16 +2253,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef CMPLOG_COMBINE +#ifdef CMPLOG_COMBINE if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); } - #endif +#endif if ((i >= 7 && (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i > (fromhex + from_0 + from_x + from_slash + 1) - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 && i > tob64 + 3 && i > fromb64 + 4 - #endif +#endif )) || repl[i] != changed_val[i] || *status == 1) { @@ -2273,7 +2276,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } -#endif + //#endif return 0; @@ -2606,9 +2609,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } else if ((lvl & LVL1) -#ifdef CMPLOG_SOLVE_TRANSFORM - || (lvl & LVL3) -#endif + //#ifdef CMPLOG_SOLVE_TRANSFORM + || ((lvl & LVL3) && afl->cmplog_enable_transform) + //#endif ) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { @@ -2689,7 +2692,7 @@ exit_its: #else u32 *v = (u32 *)afl->virgin_bits; u32 *s = (u32 *)virgin_save; - u32 i; + u32 i; for (i = 0; i < (afl->shm.map_size >> 2); i++) { v[i] &= s[i]; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e3e9007d..e2db029d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -103,7 +103,8 @@ static void usage(u8 *argv0, int more_help) { " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-... ms, default %u ms)\n" + " -t msec - timeout for each run (auto-scaled, 50-... ms, default " + "%u ms)\n" " add a '+' to skip over seeds running longer.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" @@ -123,10 +124,10 @@ static void usage(u8 *argv0, int more_help) { " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" " if using QEMU, just use -c 0.\n" - " -l cmplog_level - set the complexity/intensivity of CmpLog.\n" - " Values: 1 (basic), 2 (larger files) and 3 " - "(transform)\n\n" - + " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" + " 1=small files (default), 2=larger files, 3=all " + "files,\n" + " A=arithmetic solving, T=tranformational solving.\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " "random\n" @@ -813,13 +814,36 @@ int main(int argc, char **argv_orig, char **envp) { case 'l': { - if (optarg) { afl->cmplog_lvl = atoi(optarg); } - if (afl->cmplog_lvl < 1 || afl->cmplog_lvl > CMPLOG_LVL_MAX) { + if (!optarg) { FATAL("missing parameter for 'l'"); } + char *c = optarg; + while (*c) { - FATAL( - "Bad complog level value, accepted values are 1 (default), 2 and " - "%u.", - CMPLOG_LVL_MAX); + switch (*c) { + + case '0': + case '1': + afl->cmplog_lvl = 1; + break; + case '2': + afl->cmplog_lvl = 2; + break; + case '3': + afl->cmplog_lvl = 3; + break; + case 'a': + case 'A': + afl->cmplog_enable_arith = 1; + break; + case 't': + case 'T': + afl->cmplog_enable_transform = 1; + break; + default: + FATAL("Unknown option value '%c' in -l %s", *c, optarg); + + } + + ++c; } -- cgit 1.4.1 From cc7c651dc97f5567af33164d396b390d36b46049 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 24 Feb 2021 18:07:08 +0100 Subject: tidied up env suggestions --- docs/Changelog.md | 3 ++- src/afl-common.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index d8587334..1260531e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -36,6 +36,7 @@ sending a mail to . - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - added minimum SYNC_TIME to include/config.h (30 minutes default) + - printing suggestions for mistyped `AFL_` env variables - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a @@ -68,7 +69,7 @@ sending a mail to . - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) + - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b) - @Edznux added a nice documentation on how to use rpc.statsd with afl++ in docs/rpc_statsd.md, thanks! diff --git a/src/afl-common.c b/src/afl-common.c index ce63c262..1628e517 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -529,6 +529,8 @@ static int string_distance_levenshtein(char *s1, char *s2) { s1len = strlen(s1); s2len = strlen(s2); unsigned int column[s1len + 1]; + column[s1len] = 1; + for (y = 1; y <= s1len; y++) column[y] = y; for (x = 1; x <= s2len; x++) { @@ -608,6 +610,8 @@ void print_suggested_envs(char *mispelled_env) { }; + ck_free(reduced); + } if (found) goto cleanup; -- cgit 1.4.1 From 2f7e57f6aa4f09d0b6f55b6592fbd70d2c2c1064 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 25 Feb 2021 10:04:41 +0100 Subject: helper_min3 func --- src/afl-common.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 1628e517..078ffb9d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -518,8 +518,12 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) { } -#define HELPER_MIN3(a, b, c) \ - ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) +static inline unsigned int helper_min3(unsigned int a, unsigned int b, + unsigned int c) { + + return a < b ? (a < c ? a : c) : (b < c ? b : c); + +} // from // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C @@ -539,7 +543,7 @@ static int string_distance_levenshtein(char *s1, char *s2) { for (y = 1, lastdiag = x - 1; y <= s1len; y++) { olddiag = column[y]; - column[y] = HELPER_MIN3(column[y] + 1, column[y - 1] + 1, + column[y] = helper_min3(column[y] + 1, column[y - 1] + 1, lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1)); lastdiag = olddiag; @@ -551,8 +555,6 @@ static int string_distance_levenshtein(char *s1, char *s2) { } -#undef HELPER_MIN3 - #define ENV_SIMILARITY_TRESHOLD 3 void print_suggested_envs(char *mispelled_env) { -- cgit 1.4.1 From 79f1a44a01775ab28ad39f21f09e084fcd773c98 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 27 Feb 2021 18:14:50 +0100 Subject: fix qasan search path --- qemu_mode/qemuafl | 2 +- src/afl-common.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/afl-common.c') diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 213f3b27..e36a30eb 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 213f3b27dd099ef352181c48cd75c0f20a73e3f0 +Subproject commit e36a30ebca57ca433a5d6e20b1a32975aabb761b diff --git a/src/afl-common.c b/src/afl-common.c index 078ffb9d..c341bb97 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -372,11 +372,11 @@ u8 *get_libqasan_path(u8 *own_loc) { } - if (!access(BIN_PATH "/libqasan.so", X_OK)) { + if (!access(AFL_PATH "/libqasan.so", X_OK)) { if (cp) { ck_free(cp); } - return ck_strdup(BIN_PATH "/libqasan.so"); + return ck_strdup(AFL_PATH "/libqasan.so"); } -- cgit 1.4.1 From f81ef4abf41184a24d24828841c82b98b9216ddc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 28 Feb 2021 00:12:21 +0100 Subject: fix afl-common compile --- src/afl-common.c | 4 ++++ utils/afl_network_proxy/GNUmakefile | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index c341bb97..fa4aec7f 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -47,6 +47,10 @@ u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; +#ifndef AFL_PATH + #define AFL_PATH "/usr/local/lib/afl/" +#endif + void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) { u32 i = 0; diff --git a/utils/afl_network_proxy/GNUmakefile b/utils/afl_network_proxy/GNUmakefile index 25a3df82..0b55dc2c 100644 --- a/utils/afl_network_proxy/GNUmakefile +++ b/utils/afl_network_proxy/GNUmakefile @@ -1,5 +1,6 @@ PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin +HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH = $(PREFIX)/share/doc/afl PROGRAMS = afl-network-client afl-network-server @@ -31,7 +32,7 @@ afl-network-client: afl-network-client.c $(CC) $(CFLAGS) -I../../include -o afl-network-client afl-network-client.c $(LDFLAGS) afl-network-server: afl-network-server.c - $(CC) $(CFLAGS) -I../../include -o afl-network-server afl-network-server.c ../../src/afl-forkserver.c ../../src/afl-sharedmem.c ../../src/afl-common.c -DBIN_PATH=\"$(BIN_PATH)\" $(LDFLAGS) + $(CC) $(CFLAGS) -I../../include -o afl-network-server afl-network-server.c ../../src/afl-forkserver.c ../../src/afl-sharedmem.c ../../src/afl-common.c -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" $(LDFLAGS) clean: rm -f $(PROGRAMS) *~ core -- cgit 1.4.1 From 4619a1395b9a414e5e11148d79fde3a7fa348e87 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 09:57:57 +0100 Subject: ensure proper aligning for skim patch --- instrumentation/afl-compiler-rt.o.c | 8 ++++++-- instrumentation/afl-llvm-lto-instrumentation.so.cc | 4 +--- src/afl-common.c | 2 +- src/afl-forkserver.c | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/afl-common.c') diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index e4aeadfa..ecb94cab 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -244,8 +244,12 @@ static void __afl_map_shm(void) { if (__afl_final_loc) { - if (__afl_final_loc % 32) - __afl_final_loc = (((__afl_final_loc + 31) >> 5) << 5); + if (__afl_final_loc % 64) { + + __afl_final_loc = (((__afl_final_loc + 63) >> 6) << 6); + + } + __afl_map_size = __afl_final_loc; if (__afl_final_loc > MAP_SIZE) { diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index f5c24e41..137bae2c 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -924,9 +924,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) { - uint32_t write_loc = afl_global_id; - - if (afl_global_id % 32) write_loc = (((afl_global_id + 32) >> 4) << 4); + uint32_t write_loc = (((afl_global_id + 63) >> 6) << 6); GlobalVariable *AFLFinalLoc = new GlobalVariable( M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc"); diff --git a/src/afl-common.c b/src/afl-common.c index fa4aec7f..a306fe5e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1135,7 +1135,7 @@ u32 get_map_size(void) { } - if (map_size % 32) { map_size = (((map_size >> 5) + 1) << 5); } + if (map_size % 64) { map_size = (((map_size >> 6) + 1) << 6); } } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9ee59822..fd5edc98 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -656,11 +656,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } - if (unlikely(tmp_map_size % 32)) { + if (unlikely(tmp_map_size % 64)) { // should not happen WARNF("Target reported non-aligned map size of %u", tmp_map_size); - tmp_map_size = (((tmp_map_size + 31) >> 5) << 5); + tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); } -- cgit 1.4.1 From 47f2650a32470172a32c4ebd446003cb8a4b80e8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Mar 2021 16:53:56 +0100 Subject: add AFL_NOOPT --- README.md | 17 +++++++++++++---- docs/env_variables.md | 11 +++++++++++ include/envs.h | 4 +++- src/afl-cc.c | 21 +++++++++++++++++++-- src/afl-common.c | 1 + 5 files changed, 47 insertions(+), 7 deletions(-) (limited to 'src/afl-common.c') diff --git a/README.md b/README.md index 6b11fee4..d4e39566 100644 --- a/README.md +++ b/README.md @@ -399,10 +399,19 @@ How to do this is described below. Then build the target. (Usually with `make`) -**NOTE**: sometimes configure and build systems are fickle and do not like -stderr output (and think this means a test failure) - which is something -afl++ like to do to show statistics. It is recommended to disable them via -`export AFL_QUIET=1`. +**NOTES** + +1. sometimes configure and build systems are fickle and do not like + stderr output (and think this means a test failure) - which is something + afl++ like to do to show statistics. It is recommended to disable them via + `export AFL_QUIET=1`. + +2. sometimes configure and build systems error on warnings - these should be + disabled (e.g. `--disable-werror` for some configure scripts` + +3. in case the configure/build system complains about afl++'s compiler and + aborts then set `export AFL_NOOPT=1` which will then just behave like the + real compiler. This option has to be unset again before building the target! ##### configure diff --git a/docs/env_variables.md b/docs/env_variables.md index f6ed12d0..a20f1e42 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -26,6 +26,17 @@ Because (with the exception of the --afl-MODE command line option) the compile-time tools do not accept afl specific command-line options, they make fairly broad use of environmental variables instead: + - Some build/configure scripts break with afl++ compilers. To be able to + pass them, do: +``` + export CC=afl-cc + export CXX=afl-c++ + export AFL_NOOPT=1 + ./configure --disable-shared --disabler-werror + unset AFL_NOOPT + make +``` + - Most afl tools do not print any output if stdout/stderr are redirected. If you want to get the output into a file then set the `AFL_DEBUG` environment variable. diff --git a/include/envs.h b/include/envs.h index e8595ef7..37748a56 100644 --- a/include/envs.h +++ b/include/envs.h @@ -119,10 +119,12 @@ static char *afl_environment_variables[] = { "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", - "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_MAX_DET_EXTRAS", + "AFL_NO_X86", // not really an env but we dont want to warn on it + "AFL_NOOPT", + "AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", diff --git a/src/afl-cc.c b/src/afl-cc.c index bb136fb9..8f9bb397 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1025,7 +1025,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { int main(int argc, char **argv, char **envp) { - int i; + int i, passthrough = 0; char *callname = argv[0], *ptr = NULL; if (getenv("AFL_DEBUG")) { @@ -1045,6 +1045,13 @@ int main(int argc, char **argv, char **envp) { } + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + + passthrough = 1; + if (!debug) { be_quiet = 1; } + + } + if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; argvnull = (u8 *)argv[0]; check_environment_vars(envp); @@ -1665,6 +1672,7 @@ int main(int argc, char **argv, char **envp) { " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" " AFL_NO_BUILTIN: no builtins for string compare functions (for " "libtokencap.so)\n" + " AFL_NOOP: behave lik a normal compiler (to pass configure tests)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" @@ -1977,7 +1985,16 @@ int main(int argc, char **argv, char **envp) { } - execvp(cc_params[0], (char **)cc_params); + if (passthrough) { + + argv[0] = cc_params[0]; + execvp(cc_params[0], (char **)argv); + + } else { + + execvp(cc_params[0], (char **)cc_params); + + } FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); diff --git a/src/afl-common.c b/src/afl-common.c index a306fe5e..68f82a5e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -682,6 +682,7 @@ void check_environment_vars(char **envp) { env[strlen(afl_environment_variables[i])] == '=') { match = 1; + if ((val = getenv(afl_environment_variables[i])) && !*val) { WARNF( -- cgit 1.4.1 From a10a627622fe9785301fcb033cd1eee69d3f3056 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 10 Mar 2021 19:22:57 +0100 Subject: fix auto map discovery --- src/afl-common.c | 4 +- src/afl-fuzz.c | 181 ++++++++++++++++++++++++++----------------------------- 2 files changed, 86 insertions(+), 99 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 68f82a5e..9f6eb564 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1123,7 +1123,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { /* Reads the map size from ENV */ u32 get_map_size(void) { - uint32_t map_size = (MAP_SIZE << 2); // needed for target ctors :( + uint32_t map_size = 8000000; // a very large default map char * ptr; if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { @@ -1131,7 +1131,7 @@ u32 get_map_size(void) { map_size = atoi(ptr); if (!map_size || map_size > (1 << 29)) { - FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 32U, + FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 64U, 1U << 29); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8364c1c2..cd049fd5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -351,7 +351,7 @@ int main(int argc, char **argv_orig, char **envp) { exit_1 = !!afl->afl_env.afl_bench_just_one; SAYF(cCYA "afl-fuzz" VERSION cRST - " based on afl by Michal Zalewski and a big online community\n"); + " based on afl by Michal Zalewski and a large online community\n"); doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; @@ -1562,62 +1562,63 @@ int main(int argc, char **argv_orig, char **envp) { } - afl->argv = use_argv; - afl->fsrv.trace_bits = - afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); - - if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->unicorn_mode) { - - u32 set_env = 0; - if (!getenv("AFL_MAP_SIZE")) { - - afl->fsrv.map_size = 8000000; // dummy temporary value - setenv("AFL_MAP_SIZE", "8000000", 1); - set_env = 1; - - } - - u32 prev_map_size = afl->fsrv.map_size; + if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->unicorn_mode) { - u32 new_map_size = afl_fsrv_get_mapsize( - &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); + map_size = afl->fsrv.map_size = MAP_SIZE; + afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, map_size); + afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, map_size); + afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size); + afl->first_trace = ck_realloc(afl->first_trace, map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size); - if (new_map_size && new_map_size != prev_map_size) { - - // only reinitialize when it makes sense - if (map_size < new_map_size || - (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) { + } - OKF("Re-initializing maps to %u bytes", new_map_size); + afl->argv = use_argv; + afl->fsrv.trace_bits = + afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); - afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); - afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); - afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); - afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); - afl->top_rated = - ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); - afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); - afl->clean_trace_custom = - ck_realloc(afl->clean_trace_custom, new_map_size); - afl->first_trace = ck_realloc(afl->first_trace, new_map_size); - afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); + if (afl->fsrv.map_size <= 8000000) { - afl_fsrv_kill(&afl->fsrv); - afl_shm_deinit(&afl->shm); - afl->fsrv.map_size = new_map_size; - afl->fsrv.trace_bits = - afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); - setenv("AFL_NO_AUTODICT", "1", 1); // loaded already - afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, - afl->afl_env.afl_debug_child); + afl->fsrv.map_size = 8000000; // dummy temporary value + setenv("AFL_MAP_SIZE", "8000000", 1); - } + } - map_size = new_map_size; - if (set_env) { unsetenv("AFL_MAP_SIZE"); } + u32 new_map_size = afl_fsrv_get_mapsize( + &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); + + // only reinitialize when it makes sense + if (map_size < new_map_size || + (new_map_size > map_size && new_map_size - map_size > MAP_SIZE && + (!afl->cmplog_binary || new_map_size == MAP_SIZE))) { + + OKF("Re-initializing maps to %u bytes", new_map_size); + + afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); + afl->top_rated = ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); + afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, new_map_size); + afl->first_trace = ck_realloc(afl->first_trace, new_map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); + + afl_fsrv_kill(&afl->fsrv); + afl_shm_deinit(&afl->shm); + afl->fsrv.map_size = new_map_size; + afl->fsrv.trace_bits = + afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); + setenv("AFL_NO_AUTODICT", "1", 1); // loaded already + afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, + afl->afl_env.afl_debug_child); + map_size = new_map_size; - } + } else { afl->fsrv.map_size = map_size; @@ -1633,64 +1634,50 @@ int main(int argc, char **argv_orig, char **envp) { afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.init_child_func = cmplog_exec_child; - u32 set_env = 0; - if (!getenv("AFL_MAP_SIZE")) { - - afl->fsrv.map_size = 8000000; // dummy temporary value - setenv("AFL_MAP_SIZE", "8000000", 1); - set_env = 1; - - } - - u32 prev_map_size = afl->fsrv.map_size; - u32 new_map_size = afl_fsrv_get_mapsize(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); - if (new_map_size && new_map_size != prev_map_size) { - - // only reinitialize when it needs to be larger - if (map_size < new_map_size) { - - OKF("Re-initializing maps to %u bytes due cmplog", new_map_size); + // only reinitialize when necessary + if (map_size < new_map_size || + (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) { + + OKF("Re-initializing maps to %u bytes due cmplog", new_map_size); + + afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); + afl->top_rated = + ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); + afl->clean_trace_custom = + ck_realloc(afl->clean_trace_custom, new_map_size); + afl->first_trace = ck_realloc(afl->first_trace, new_map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); + + afl_fsrv_kill(&afl->fsrv); + afl_fsrv_kill(&afl->cmplog_fsrv); + afl_shm_deinit(&afl->shm); + afl->cmplog_fsrv.map_size = new_map_size; // non-cmplog stays the same + + afl->fsrv.trace_bits = + afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); + setenv("AFL_NO_AUTODICT", "1", 1); // loaded already + afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, + afl->afl_env.afl_debug_child); + + afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, + afl->afl_env.afl_debug_child); - afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); - afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); - afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); - afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size); - afl->top_rated = - ck_realloc(afl->top_rated, new_map_size * sizeof(void *)); - afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size); - afl->clean_trace_custom = - ck_realloc(afl->clean_trace_custom, new_map_size); - afl->first_trace = ck_realloc(afl->first_trace, new_map_size); - afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); - - afl_fsrv_kill(&afl->fsrv); - afl_fsrv_kill(&afl->cmplog_fsrv); - afl_shm_deinit(&afl->shm); - afl->cmplog_fsrv.map_size = new_map_size; // non-cmplog stays the same - - afl->fsrv.trace_bits = - afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); - setenv("AFL_NO_AUTODICT", "1", 1); // loaded already - afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, - afl->afl_env.afl_debug_child); - - afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, - afl->afl_env.afl_debug_child); - - map_size = new_map_size; + map_size = new_map_size; - } + } else { - if (set_env) { unsetenv("AFL_MAP_SIZE"); } + afl->cmplog_fsrv.map_size = map_size; } - afl->cmplog_fsrv.map_size = map_size; - OKF("Cmplog forkserver successfully started"); } -- cgit 1.4.1 From d4fb7f8b4015297e1c74b28d671eba058cfb6366 Mon Sep 17 00:00:00 2001 From: realmadsci <71108352+realmadsci@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:53:42 -0500 Subject: Add AFL_QEMU_CUSTOM_BIN environment flag In QEMU mode (-Q), setting AFL_QEMU_CUSTOM_BIN cause afl-fuzz to skip prepending afl-qemu-trace to your command line. Use this if you wish to use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments. --- docs/env_variables.md | 4 ++++ include/envs.h | 1 + src/afl-common.c | 7 +++++++ src/afl-fuzz-init.c | 1 + 4 files changed, 13 insertions(+) (limited to 'src/afl-common.c') diff --git a/docs/env_variables.md b/docs/env_variables.md index a20f1e42..c6ad0aa4 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -393,6 +393,10 @@ checks or alter some of the more exotic semantics of the tool: - In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace. + - In QEMU mode (-Q), setting `AFL_QEMU_CUSTOM_BIN` cause afl-fuzz to skip + prepending `afl-qemu-trace` to your command line. Use this if you wish to use a + custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments. + - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule everytime a cycle is finished. diff --git a/include/envs.h b/include/envs.h index 4d4d6b0e..e92bee2a 100644 --- a/include/envs.h +++ b/include/envs.h @@ -130,6 +130,7 @@ static char *afl_environment_variables[] = { "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", "AFL_PYTHON_MODULE", + "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", diff --git a/src/afl-common.c b/src/afl-common.c index 9f6eb564..58fbf765 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -149,6 +149,13 @@ void argv_cpy_free(char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) { + WARNF( + "AFL_QEMU_CUSTOM_BIN is enabled. " + "You must run your target under afl-qemu-trace on your own!"); + return argv; + } + if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } u8 *tmp, *cp = NULL, *rsl, *own_copy; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ca2f75f1..82c1799e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2592,6 +2592,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode || + (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) || afl->non_instrumented_mode) { return; -- cgit 1.4.1 From 01ad7610beaf772063c9011daae5fa3a3232494c Mon Sep 17 00:00:00 2001 From: realmadsci <71108352+realmadsci@users.noreply.github.com> Date: Mon, 15 Mar 2021 11:45:58 -0400 Subject: Remove AFL_PRELOAD and AFL_USE_QASAN handlers These are now processed in afl-qemu-trace so that the "copy+paste" code that is in all of the other AFL tools can be removed. This also allows the AFL_USE_QASAN flag to work the same when used with tools like afl-fuzz as it does with afl-qemu-trace. This is important in situations where loading the QASAN library changes the address of your desired entrypoint, or for crash validation using the same environment that afl-fuzz was using. With this change, the same set of environment variables can be used in exactly the same way between afl-fuzz, afl-showmap, and afl-qemu-trace, and you will get exactly the same guest environment. --- include/common.h | 1 - src/afl-analyze.c | 58 +-------------------------- src/afl-common.c | 60 ---------------------------- src/afl-fuzz.c | 59 +-------------------------- src/afl-showmap.c | 58 +-------------------------- src/afl-tmin.c | 58 +-------------------------- utils/afl_network_proxy/afl-network-server.c | 33 +-------------- 7 files changed, 5 insertions(+), 322 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index cd728536..b7adbaec 100644 --- a/include/common.h +++ b/include/common.h @@ -48,7 +48,6 @@ void argv_cpy_free(char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); -u8 * get_libqasan_path(u8 *own_loc); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index d46ecb8d..86b0f7e9 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -822,38 +822,7 @@ static void set_up_environment(void) { if (qemu_mode) { - u8 *qemu_preload = getenv("QEMU_SET_ENV"); - u8 *afl_preload = getenv("AFL_PRELOAD"); - u8 *buf; - - s32 i, afl_preload_size = strlen(afl_preload); - for (i = 0; i < afl_preload_size; ++i) { - - if (afl_preload[i] == ',') { - - PFATAL( - "Comma (',') is not allowed in AFL_PRELOAD when -Q is " - "specified!"); - - } - - } - - if (qemu_preload) { - - buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - qemu_preload, afl_preload, afl_preload); - - } else { - - buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - afl_preload, afl_preload); - - } - - setenv("QEMU_SET_ENV", buf, 1); - - ck_free(buf); + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ } else { @@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file) { usage(argv[0]); } - if (qemu_mode && getenv("AFL_USE_QASAN")) { - - u8 *preload = getenv("AFL_PRELOAD"); - u8 *libqasan = get_libqasan_path(argv_orig[0]); - - if (!preload) { - - setenv("AFL_PRELOAD", libqasan, 0); - - } else { - - u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); - strcpy(result, libqasan); - strcat(result, " "); - strcat(result, preload); - - setenv("AFL_PRELOAD", result, 1); - ck_free(result); - - } - - ck_free(libqasan); - - } - map_size = get_map_size(); use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); diff --git a/src/afl-common.c b/src/afl-common.c index 9f6eb564..5ac50595 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -338,66 +338,6 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } -/* Get libqasan path. */ - -u8 *get_libqasan_path(u8 *own_loc) { - - if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } - - u8 *tmp, *cp = NULL, *rsl, *own_copy; - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/libqasan.so", tmp); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - return cp; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/libqasan.so", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { return cp; } - - } else { - - ck_free(own_copy); - - } - - if (!access(AFL_PATH "/libqasan.so", X_OK)) { - - if (cp) { ck_free(cp); } - - return ck_strdup(AFL_PATH "/libqasan.so"); - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the 'libqasan.so' binary. The binary must be " - "built\n" - " separately by following the instructions in " - "qemu_mode/libqasan/README.md. " - "If you\n" - " already have the binary installed, you may need to specify " - "AFL_PATH in the\n" - " environment.\n"); - - FATAL("Failed to locate 'libqasan.so'."); - -} - /* Find binary, used by analyze, showmap, tmin @returns the path, allocating the string */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ff27048a..3ca377f6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1022,32 +1022,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->fsrv.qemu_mode && getenv("AFL_USE_QASAN")) { - - u8 *preload = getenv("AFL_PRELOAD"); - u8 *libqasan = get_libqasan_path(argv_orig[0]); - - if (!preload) { - - setenv("AFL_PRELOAD", libqasan, 0); - - } else { - - u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); - strcpy(result, libqasan); - strcat(result, " "); - strcat(result, preload); - - setenv("AFL_PRELOAD", result, 1); - ck_free(result); - - } - - afl->afl_env.afl_preload = (u8 *)getenv("AFL_PRELOAD"); - ck_free(libqasan); - - } - 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\" " @@ -1312,38 +1286,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.qemu_mode) { - u8 *qemu_preload = getenv("QEMU_SET_ENV"); - u8 *afl_preload = getenv("AFL_PRELOAD"); - u8 *buf; - - s32 j, afl_preload_size = strlen(afl_preload); - for (j = 0; j < afl_preload_size; ++j) { - - if (afl_preload[j] == ',') { - - PFATAL( - "Comma (',') is not allowed in AFL_PRELOAD when -Q is " - "specified!"); - - } - - } - - if (qemu_preload) { - - buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - qemu_preload, afl_preload, afl_preload); - - } else { - - buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - afl_preload, afl_preload); - - } - - setenv("QEMU_SET_ENV", buf, 1); - - ck_free(buf); + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ } else { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0fc76193..7bf5a9c7 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -599,38 +599,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (fsrv->qemu_mode) { - u8 *qemu_preload = getenv("QEMU_SET_ENV"); - u8 *afl_preload = getenv("AFL_PRELOAD"); - u8 *buf; - - s32 i, afl_preload_size = strlen(afl_preload); - for (i = 0; i < afl_preload_size; ++i) { - - if (afl_preload[i] == ',') { - - PFATAL( - "Comma (',') is not allowed in AFL_PRELOAD when -Q is " - "specified!"); - - } - - } - - if (qemu_preload) { - - buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - qemu_preload, afl_preload, afl_preload); - - } else { - - buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - afl_preload, afl_preload); - - } - - setenv("QEMU_SET_ENV", buf, 1); - - ck_free(buf); + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ } else { @@ -946,31 +915,6 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !out_file) { usage(argv[0]); } - if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8 *preload = getenv("AFL_PRELOAD"); - u8 *libqasan = get_libqasan_path(argv_orig[0]); - - if (!preload) { - - setenv("AFL_PRELOAD", libqasan, 0); - - } else { - - u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); - strcpy(result, libqasan); - strcat(result, " "); - strcat(result, preload); - - setenv("AFL_PRELOAD", result, 1); - ck_free(result); - - } - - ck_free(libqasan); - - } - if (in_dir) { if (!out_file && !collect_coverage) diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 6d04c652..7ef8b9bf 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -753,38 +753,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (fsrv->qemu_mode) { - u8 *qemu_preload = getenv("QEMU_SET_ENV"); - u8 *afl_preload = getenv("AFL_PRELOAD"); - u8 *buf; - - s32 i, afl_preload_size = strlen(afl_preload); - for (i = 0; i < afl_preload_size; ++i) { - - if (afl_preload[i] == ',') { - - PFATAL( - "Comma (',') is not allowed in AFL_PRELOAD when -Q is " - "specified!"); - - } - - } - - if (qemu_preload) { - - buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - qemu_preload, afl_preload, afl_preload); - - } else { - - buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - afl_preload, afl_preload); - - } - - setenv("QEMU_SET_ENV", buf, 1); - - ck_free(buf); + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ } else { @@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) { check_environment_vars(envp); setenv("AFL_NO_AUTODICT", "1", 1); - if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8 *preload = getenv("AFL_PRELOAD"); - u8 *libqasan = get_libqasan_path(argv_orig[0]); - - if (!preload) { - - setenv("AFL_PRELOAD", libqasan, 0); - - } else { - - u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); - strcpy(result, libqasan); - strcat(result, " "); - strcat(result, preload); - - setenv("AFL_PRELOAD", result, 1); - ck_free(result); - - } - - ck_free(libqasan); - - } - /* initialize cmplog_mode */ shm.cmplog_mode = 0; diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index fe225416..0dfae658 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -237,38 +237,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (fsrv->qemu_mode) { - u8 *qemu_preload = getenv("QEMU_SET_ENV"); - u8 *afl_preload = getenv("AFL_PRELOAD"); - u8 *buf; - - s32 i, afl_preload_size = strlen(afl_preload); - for (i = 0; i < afl_preload_size; ++i) { - - if (afl_preload[i] == ',') { - - PFATAL( - "Comma (',') is not allowed in AFL_PRELOAD when -Q is " - "specified!"); - - } - - } - - if (qemu_preload) { - - buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - qemu_preload, afl_preload, afl_preload); - - } else { - - buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", - afl_preload, afl_preload); - - } - - setenv("QEMU_SET_ENV", buf, 1); - - afl_free(buf); + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ } else { -- cgit 1.4.1 From 862cb3217f5983e5cfff6568f6b31fcf1e960802 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 16 Mar 2021 14:38:13 +0100 Subject: fix cmplog rtn --- include/envs.h | 1 + instrumentation/afl-compiler-rt.o.c | 10 +++++----- src/afl-common.c | 6 ++++-- utils/aflpp_driver/aflpp_driver.c | 10 ++++++++++ 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/envs.h b/include/envs.h index e92bee2a..cfd73b68 100644 --- a/include/envs.h +++ b/include/envs.h @@ -50,6 +50,7 @@ static char *afl_environment_variables[] = { "AFL_FAST_CAL", "AFL_FORCE_UI", "AFL_FUZZER_ARGS", // oss-fuzz + "AFL_GDB", "AFL_GCC_ALLOWLIST", "AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index cca38cd0..32dbc53d 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1730,18 +1730,18 @@ __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size) { // to avoid to call it on .text addresses static int area_is_valid(void *ptr, size_t len) { - if (unlikely(__asan_region_is_poisoned(ptr, len))) { return 0; } + if (unlikely(!ptr || __asan_region_is_poisoned(ptr, len))) { return 0; } - long r = syscall(__afl_dummy_fd[1], SYS_write, ptr, len); + long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len); if (unlikely(r <= 0 || r > len)) { // fail - maybe hitting asan boundary? char *p = (char *)ptr; long page_size = sysconf(_SC_PAGE_SIZE); char *page = (char *)((uintptr_t)p & ~(page_size - 1)) + page_size; - if (page < p + len) { return 0; } // no isnt, return fail - len -= (p + len - page); - r = syscall(__afl_dummy_fd[1], SYS_write, p, len); + if (page >= p + len) { return 0; } // no isnt, return fail + len = page - p - len; + r = syscall(SYS_write, __afl_dummy_fd[1], p, len); } diff --git a/src/afl-common.c b/src/afl-common.c index bfb05a67..27b63434 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -150,10 +150,12 @@ void argv_cpy_free(char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) { + WARNF( - "AFL_QEMU_CUSTOM_BIN is enabled. " - "You must run your target under afl-qemu-trace on your own!"); + "AFL_QEMU_CUSTOM_BIN is enabled. " + "You must run your target under afl-qemu-trace on your own!"); return argv; + } if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 9c97607c..f0f3a47d 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -208,6 +208,16 @@ int main(int argc, char **argv) { "======================================================\n", argv[0], argv[0]); + if (getenv("AFL_GDB")) { + + char cmd[64]; + snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid()); + system(cmd); + fprintf(stderr, "DEBUG: aflpp_driver pid is %d\n", getpid()); + sleep(1); + + } + output_file = stderr; maybe_duplicate_stderr(); maybe_close_fd_mask(); -- cgit 1.4.1 From 5e2a5f1110e29c36f1c41fb4677ab698c5d571c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 17 Mar 2021 10:26:02 +0100 Subject: shmem map size in config.h --- include/config.h | 9 ++++++ instrumentation/afl-compiler-rt.o.c | 6 ++-- src/afl-cc.c | 62 ++++++++++++++++++------------------- src/afl-common.c | 2 +- src/afl-fuzz.c | 24 +++++++++----- 5 files changed, 60 insertions(+), 43 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/config.h b/include/config.h index b049fee0..29225f6b 100644 --- a/include/config.h +++ b/include/config.h @@ -34,6 +34,15 @@ * * ******************************************************/ +/* Default shared memory map size. Most targets just need a coverage map + between 20-250kb. Plus there is an auto-detection feature in afl-fuzz. + However if a target has problematic constructors and init arrays then + this can fail. Hence afl-fuzz deploys a larger default map. The largest + map seen so far is the xlsx fuzzer for libreoffice which is 5MB. + At runtime this value can be overriden via AFL_MAP_SIZE. + Default: 8MB (defined in bytes) */ +#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024) + /* CMPLOG/REDQUEEN TUNING * * Here you can modify tuning and solving options for CMPLOG. diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 70148b78..c635ae63 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1774,14 +1774,14 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { */ if (unlikely(!__afl_cmp_map)) return; - //fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2); + // fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2); int l1, l2; if ((l1 = area_is_valid(ptr1, 32)) <= 0 || (l2 = area_is_valid(ptr2, 32)) <= 0) return; int len = MIN(l1, l2); - //fprintf(stderr, "RTN2 %u\n", len); + // fprintf(stderr, "RTN2 %u\n", len); uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); k &= CMP_MAP_W - 1; @@ -1812,7 +1812,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { ptr1, len); __builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2, len); - //fprintf(stderr, "RTN3\n"); + // fprintf(stderr, "RTN3\n"); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 206066fd..ebbd390c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -959,63 +959,63 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (compiler_mode != GCC && compiler_mode != CLANG) { - switch (bit_mode) { + switch (bit_mode) { - case 0: - if (!shared_linking) + case 0: + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + if (lto_mode) + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); + break; - case 32: - if (!shared_linking) + case 32: + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-32.o", obj_path); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m32 is not supported by your compiler"); + if (lto_mode) { + + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m32 is not supported by your compiler"); - if (lto_mode) { - - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); - } + } - break; + break; - case 64: - if (!shared_linking) + case 64: + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-64.o", obj_path); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m64 is not supported by your compiler"); + if (lto_mode) { + + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m64 is not supported by your compiler"); - if (lto_mode) { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); - - } + } - break; + break; - } + } #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking) + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif - } + } #if defined(USEMMAP) && !defined(__HAIKU__) - cc_params[cc_par_cnt++] = "-lrt"; + cc_params[cc_par_cnt++] = "-lrt"; #endif #endif diff --git a/src/afl-common.c b/src/afl-common.c index 27b63434..7e56ce3f 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1072,7 +1072,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { /* Reads the map size from ENV */ u32 get_map_size(void) { - uint32_t map_size = 8000000; // a very large default map + uint32_t map_size = DEFAULT_SHMEM_SIZE; char * ptr; if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2fde561c..8318a92e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1527,11 +1527,13 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !afl->unicorn_mode) { - if (map_size <= 8000000 && !afl->non_instrumented_mode && + if (map_size <= DEFAULT_SHMEM_SIZE && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !afl->unicorn_mode) { - afl->fsrv.map_size = 8000000; // dummy temporary value - setenv("AFL_MAP_SIZE", "8000000", 1); + afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value + char vbuf[16]; + snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE); + setenv("AFL_MAP_SIZE", vbuf, 1); } @@ -1582,11 +1584,13 @@ int main(int argc, char **argv_orig, char **envp) { afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.init_child_func = cmplog_exec_child; - if (map_size <= 8000000 && !afl->non_instrumented_mode && + if (map_size <= DEFAULT_SHMEM_SIZE && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !afl->unicorn_mode) { - afl->cmplog_fsrv.map_size = 8000000; // dummy temporary value - setenv("AFL_MAP_SIZE", "8000000", 1); + afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value + char vbuf[16]; + snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE); + setenv("AFL_MAP_SIZE", vbuf, 1); } @@ -1634,8 +1638,12 @@ int main(int argc, char **argv_orig, char **envp) { } if (afl->debug) { - printf("NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, afl->cmplog_fsrv.map_size); - fprintf(stderr, "NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, afl->cmplog_fsrv.map_size); + + printf("NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, + afl->cmplog_fsrv.map_size); + fprintf(stderr, "NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, + afl->cmplog_fsrv.map_size); + } load_auto(afl); -- cgit 1.4.1