diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-fuzz-init.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-queue.c | 7 | ||||
-rw-r--r-- | src/afl-fuzz.c | 224 |
3 files changed, 184 insertions, 49 deletions
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7310e49f..98de26dd 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) { } - if (!q->was_fuzzed) { + if (unlikely(!q->was_fuzzed)) { q->was_fuzzed = 1; afl->reinit_table = 1; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f4cb930d..a28172f9 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -401,7 +401,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } else { - if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); } + if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ } } @@ -699,12 +699,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { void destroy_queue(afl_state_t *afl) { - u32 i; + u32 i; + struct queue_entry *q; for (i = 0; i < afl->queued_items; i++) { - struct queue_entry *q; - q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bb05c9c6..d8be5721 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -181,7 +181,7 @@ static void usage(u8 *argv0, int more_help) { "it.\n" " if using QEMU/FRIDA or the fuzzing target is " "compiled\n" - " for CmpLog then use '-c 0'. To disable Cmplog use '-c " + " for CmpLog then use '-c 0'. To disable CMPLOG use '-c " "-'.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n" " 1=small files, 2=larger files (default), 3=all " @@ -2116,7 +2116,7 @@ int main(int argc, char **argv_orig, char **envp) { if (read(fr_fd, buf, 32) >= 16) { - sscanf(buf, "%p", (void**)&prev_target_hash); + sscanf(buf, "%p", (void **)&prev_target_hash); } @@ -2126,7 +2126,6 @@ int main(int argc, char **argv_orig, char **envp) { } - write_setup_file(afl, argc, argv); if (afl->in_place_resume) { @@ -2143,8 +2142,23 @@ int main(int argc, char **argv_orig, char **envp) { snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); if ((fr_fd = open(fn, O_RDONLY)) >= 0) { - OKF("Performing FAST RESUME"); - // fast_resume = 1; + u8 ver_string[8]; + u64 *ver = (u64 *)ver_string; + u64 expect_ver = + afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + if (read(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string)) + WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME"); + else if (expect_ver != *ver) + WARNF( + "Different AFL++ version or feature usage, cannot perform FAST " + "RESUME"); + else { + + OKF("Will perform FAST RESUME"); + fast_resume = 1; + + } } else { @@ -2156,42 +2170,34 @@ int main(int argc, char **argv_orig, char **envp) { } - if (fast_resume) { + read_testcases(afl, NULL); - // XXX + pivot_inputs(afl); - } else { - - read_testcases(afl, NULL); - - pivot_inputs(afl); + if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! - if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! + if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { - if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { + char tmpfile[PATH_MAX]; - char tmpfile[PATH_MAX]; + if (afl->file_extension) { - if (afl->file_extension) { + snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, + afl->file_extension); - snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, - afl->file_extension); - - } else { - - snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); + } else { - } + snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); - /* there is still a race condition here, but well ... */ - if (access(tmpfile, F_OK) != -1) { + } - FATAL( - "AFL_TMPDIR already has an existing temporary input file: %s - if " - "this is not from another instance, then just remove the file.", - tmpfile); + /* there is still a race condition here, but well ... */ + if (access(tmpfile, F_OK) != -1) { - } + FATAL( + "AFL_TMPDIR already has an existing temporary input file: %s - if " + "this is not from another instance, then just remove the file.", + tmpfile); } @@ -2474,7 +2480,7 @@ int main(int argc, char **argv_orig, char **envp) { } - OKF("Cmplog forkserver successfully started"); + OKF("CMPLOG forkserver successfully started"); } @@ -2512,29 +2518,102 @@ int main(int argc, char **argv_orig, char **envp) { dedup_extras(afl); if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); } - // after we have the correct bitmap size we can read the bitmap -B option - // and set the virgin maps - if (afl->in_bitmap) { + if (unlikely(fast_resume)) { - read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + u64 resume_start = get_cur_time_us(); + // if we get here then we should abort on errors + ck_read(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ck_read(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ck_read(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ck_read(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); - } else { + u8 res[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 r = 8 + afl->fsrv.map_size * 4; + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; - memset(afl->virgin_bits, 255, map_size); + for (u32 i = 0; i < afl->queued_items; i++) { - } + q = afl->queue_buf[i]; + ck_read(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ck_read(fr_fd, res, 1, "check map"); + if (res[0]) { - memset(afl->virgin_tmout, 255, map_size); - memset(afl->virgin_crash, 255, map_size); + q->trace_mini = ck_alloc(m_len); + ck_read(fr_fd, q->trace_mini, m_len, "trace_mini"); + r += q_len + m_len + 1; - if (likely(!afl->afl_env.afl_no_startup_calibration)) { + } else { + + r += q_len + 1; + + } + + afl->total_bitmap_size += q->bitmap_size; + ++afl->total_bitmap_entries; + update_bitmap_score(afl, q); + + if (q->was_fuzzed) { --afl->pending_not_fuzzed; } + + if (q->disabled) { + + if (!q->was_fuzzed) { --afl->pending_not_fuzzed; } + --afl->active_items; + + } - perform_dry_run(afl); + if (q->var_behavior) { ++afl->queued_variable; } + if (q->favored) { + + ++afl->queued_favored; + if (!q->was_fuzzed) { ++afl->pending_favored; } + + } + + } + + u8 buf[4]; + if (read(fr_fd, buf, 3) > 0) { + + FATAL("invalid trailing data in fastresume.bin"); + + } + + OKF("Successfully loaded fastresume.bin (%u bytes)!", r); + close(fr_fd); + afl->reinit_table = 1; + update_calibration_time(afl, &resume_start); } else { - ACTF("skipping initial seed calibration due option override!"); - usleep(1000); + // after we have the correct bitmap size we can read the bitmap -B option + // and set the virgin maps + if (afl->in_bitmap) { + + read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + + } else { + + memset(afl->virgin_bits, 255, map_size); + + } + + memset(afl->virgin_tmout, 255, map_size); + memset(afl->virgin_crash, 255, map_size); + + if (likely(!afl->afl_env.afl_no_startup_calibration)) { + + perform_dry_run(afl); + + } else { + + ACTF("Skipping initial seed calibration due option override!"); + usleep(1000); + + } } @@ -3125,6 +3204,63 @@ stop_fuzzing: fclose(afl->fsrv.det_plot_file); #endif + /* create fastresume.bin */ + u8 fr[PATH_MAX]; + snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= + 0) { + + u8 ver_string[8]; + u32 w = 0; + u64 *ver = (u64 *)ver_string; + *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + w += write(fr_fd, ver_string, sizeof(ver_string)); + + w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size); + w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size); + + u8 on[1] = {1}, off[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; + + afl->pending_not_fuzzed = afl->queued_items; + afl->active_items = afl->queued_items; + + for (u32 i = 0; i < afl->queued_items; i++) { + + q = afl->queue_buf[i]; + ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + if (!q->trace_mini) { + + ck_write(fr_fd, off, 1, "no_mini"); + w += q_len + 1; + + } else { + + ck_write(fr_fd, on, 1, "yes_mini"); + ck_write(fr_fd, q->trace_mini, m_len, "trace_mini"); + w += q_len + m_len + 1; + + } + + } + + close(fr_fd); + afl->var_byte_count = count_bytes(afl, afl->var_bytes); + OKF("Written fastresume.bin with %u bytes!", w); + + } else { + + WARNF("Could not create fastresume.bin"); + + } + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); |