diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-common.c | 155 | ||||
-rw-r--r-- | src/afl-forkserver.c | 17 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 62 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 42 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 284 | ||||
-rw-r--r-- | src/afl-fuzz-queue.c | 177 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 99 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 30 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 5 | ||||
-rw-r--r-- | src/afl-fuzz.c | 127 |
10 files changed, 806 insertions, 192 deletions
diff --git a/src/afl-common.c b/src/afl-common.c index 367dec72..cefed8dc 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -138,62 +138,73 @@ 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) { +u8 *find_afl_binary(u8 *fname, u8 *own_loc) { - 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; } - 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/afl-qemu-trace", own_copy); - ck_free(own_copy); + *rsl = 0; - if (!access(cp, X_OK)) { + cp = alloc_printf("%s/%s", own_copy, fname); + ck_free(own_copy); - *target_path_p = new_argv[0] = cp; - return new_argv; + if (!access(cp, X_OK)) { return cp; } - } + } else { - } else { + ck_free(own_copy); - ck_free(own_copy); + } } - 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_afl_binary("afl-qemu-trace", own_loc); + + if (cp) { + + *target_path_p = new_argv[0] = cp; return new_argv; } @@ -225,7 +236,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; @@ -234,66 +245,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 = alloc_printf("%s/afl-qemu-trace", tmp); + cp = find_afl_binary("afl-qemu-trace", own_loc); - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } + if (cp) { ck_free(cp); + cp = find_afl_binary("afl-wine-trace", own_loc); - cp = alloc_printf("%s/afl-wine-trace", tmp); - - 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)) { + if (cp) { - *target_path_p = new_argv[0] = ck_strdup(ncp); + *target_path_p = new_argv[0] = cp; return new_argv; } @@ -301,25 +262,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 25983f26..173cc70f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -498,11 +498,21 @@ 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->taint_mode) { + + 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. */ close(ctl_pipe[0]); @@ -937,7 +947,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) { @@ -956,6 +966,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 1b9df624..db57061d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -177,6 +177,40 @@ 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. */ @@ -203,6 +237,32 @@ 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. */ @@ -595,7 +655,7 @@ 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..359eef85 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); } @@ -771,9 +771,13 @@ 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; } + if (afl->stop_soon) { + + ck_free(use_mem); + return; + + } if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { @@ -960,6 +964,10 @@ 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; } @@ -1438,6 +1446,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 +1506,20 @@ 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 <afl->out_dir>/crashes/id:* and * <afl->out_dir>/hangs/id:*. */ @@ -1721,6 +1747,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->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 57b53c9f..6d52b2b4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -458,27 +458,170 @@ u8 fuzz_one_original(afl_state_t *afl) { } - /* Map the test case into memory. */ + u32 tmp_val = 0; - fd = open(afl->queue_cur->fname, O_RDONLY); + if (unlikely(afl->taint_mode)) { - if (unlikely(fd < 0)) { + tmp_val = afl->queue_cycle % 2; // starts with 1 + ret_val = 0; - PFATAL("Unable to open '%s'", afl->queue_cur->fname); + 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; - len = afl->queue_cur->len; + s32 dst = 0, i; + temp_len = len = afl->queue_cur->len; + s32 j = 0; // tmp - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + 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; - if (unlikely(orig_in == MAP_FAILED)) { + switch (tmp_val) { - PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); + 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) { - close(fd); + 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); + + 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); + + if (unlikely(orig_in == MAP_FAILED)) { + + 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 @@ -502,8 +645,12 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->queue_cur->exec_cksum = 0; - res = - calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 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); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -526,8 +673,8 @@ u8 fuzz_one_original(afl_state_t *afl) { * TRIMMING * ************/ - if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && - !afl->disable_trim) { + if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done && + !afl->disable_trim && !afl->taint_needs_splode)) { u8 res = trim_case(afl, afl->queue_cur, in_buf); @@ -564,13 +711,26 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) { - if (input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum)) { + int res; + if (unlikely(afl->taint_needs_splode)) { - goto abandon_entry; + 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 { + + res = input_to_state_stage(afl, in_buf, out_buf, len, + afl->queue_cur->exec_cksum); } + if (unlikely(res)) { goto abandon_entry; } + } /* Skip right away if -d is given, if it has not been chosen sufficiently @@ -2133,8 +2293,18 @@ havoc_stage: if (actually_clone) { - clone_len = choose_block_len(afl, temp_len); - clone_from = rand_below(afl, temp_len - clone_len + 1); + 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); + + } } else { @@ -2156,7 +2326,11 @@ havoc_stage: if (actually_clone) { - memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); + 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); } else { @@ -2168,7 +2342,7 @@ havoc_stage: } /* Tail */ - memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, + memmove(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); @@ -2189,16 +2363,49 @@ havoc_stage: if (temp_len < 2) { break; } - copy_len = choose_block_len(afl, temp_len - 1); + 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_from = rand_below(afl, temp_len - copy_len + 1); - copy_to = rand_below(afl, temp_len - copy_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); + + } if (rand_below(afl, 4)) { if (copy_from != copy_to) { - memmove(out_buf + copy_to, out_buf + copy_from, copy_len); + 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); + + } } @@ -2464,10 +2671,17 @@ 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 && afl->queue_cur->len > 1) { + afl->queued_paths > 1 && saved_len > 1) { struct queue_entry *target; u32 tid, split_at; @@ -2480,7 +2694,7 @@ retry_splicing: if (in_buf != orig_in) { in_buf = orig_in; - len = afl->queue_cur->len; + len = saved_len; } @@ -2551,6 +2765,8 @@ retry_splicing: ret_val = 0; + goto abandon_entry; + /* we are through with this queue entry - for this iteration */ abandon_entry: @@ -2570,7 +2786,17 @@ abandon_entry: ++afl->queue_cur->fuzz_level; - munmap(orig_in, afl->queue_cur->len); + 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); + + } return ret_val; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f35df914..43794018 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -103,6 +103,169 @@ 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) { @@ -212,10 +375,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 +419,13 @@ 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->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 +445,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 d3f823c9..5381723d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -350,7 +350,9 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } - if (q->exec_cksum) { + if (unlikely(afl->taint_mode)) + q->exec_cksum = 0; + else if (q->exec_cksum) { memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); hnb = has_new_bits(afl, afl->virgin_bits); @@ -753,56 +755,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; + + 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) { - 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) { + } else { - needs_write = 1; - memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); + 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; @@ -855,6 +866,8 @@ 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(). */ @@ -864,6 +877,32 @@ 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); @@ -911,3 +950,5 @@ 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 d4de91a4..a8416eb1 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(afl_state_t *afl, uint32_t map_size) { +void afl_state_init_1(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,16 +100,6 @@ void afl_state_init(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 @@ -161,6 +151,24 @@ void afl_state_init(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 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 " : "", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5dd092f2..106aa550 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,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" " -p schedule - power schedules compute a seed's performance score. " "<explore\n" " (default), fast, coe, lin, quad, exploit, mmopt, " @@ -239,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; @@ -257,7 +263,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(); - afl_state_init(afl, map_size); + afl_state_init_1(afl, map_size); afl->debug = debug; afl_fsrv_init(&afl->fsrv); @@ -277,10 +283,15 @@ 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:QNUWe:p:s:V:E:L:hRP:")) > 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->taint_mode = 1; + if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; } + break; + case 'I': afl->infoexec = optarg; break; @@ -488,7 +499,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; @@ -818,6 +829,15 @@ 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\" " @@ -825,8 +845,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 && @@ -872,6 +891,19 @@ 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"); } @@ -972,7 +1004,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->taint_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -1068,6 +1100,13 @@ 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); @@ -1223,7 +1262,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; @@ -1234,6 +1272,70 @@ 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); @@ -1308,7 +1410,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->python_only && !afl->taint_mode) { afl->limit_time_sig = -1; afl->limit_time_puppet = 0; @@ -1496,8 +1598,11 @@ 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); |