diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-common.c | 5 | ||||
-rw-r--r-- | src/afl-forkserver.c | 42 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 12 | ||||
-rw-r--r-- | src/afl-fuzz-extras.c | 4 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 19 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-queue.c | 151 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 60 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 14 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 90 | ||||
-rw-r--r-- | src/afl-fuzz.c | 406 | ||||
-rw-r--r-- | src/afl-performance.c | 2 | ||||
-rw-r--r-- | src/hashmap.c | 2 |
13 files changed, 668 insertions, 141 deletions
diff --git a/src/afl-common.c b/src/afl-common.c index efdb5d60..892745a7 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -108,7 +108,8 @@ void set_sanitizer_defaults() { if (!have_san_options) { strcpy(buf, default_options); } if (have_asan_options) { - if (NULL != strstr(have_asan_options, "detect_leaks=0")) { + if (NULL != strstr(have_asan_options, "detect_leaks=0") || + NULL != strstr(have_asan_options, "detect_leaks=false")) { strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); @@ -979,6 +980,7 @@ inline u64 get_cur_time(void) { struct timeval tv; struct timezone tz; + // TO NOT REPLACE WITH clock_gettime!!! gettimeofday(&tv, &tz); return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); @@ -992,6 +994,7 @@ inline u64 get_cur_time_us(void) { struct timeval tv; struct timezone tz; + // TO NOT REPLACE WITH clock_gettime!!! gettimeofday(&tv, &tz); return (tv.tv_sec * 1000000ULL) + tv.tv_usec; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 71d8570d..c7c493cf 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -241,6 +241,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->mem_limit = MEM_LIMIT; fsrv->out_file = NULL; fsrv->child_kill_signal = SIGKILL; + fsrv->max_length = MAX_FILE; /* exec related stuff */ fsrv->child_pid = -1; @@ -252,6 +253,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->uses_crash_exitcode = false; fsrv->uses_asan = false; +#ifdef __AFL_CODE_COVERAGE + fsrv->persistent_trace_bits = NULL; +#endif + fsrv->init_child_func = fsrv_exec_child; list_append(&fsrv_list, fsrv); @@ -278,12 +283,19 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal; fsrv_to->debug = from->debug; +#ifdef __AFL_CODE_COVERAGE + fsrv_to->persistent_trace_bits = from->persistent_trace_bits; +#endif + // These are forkserver specific. fsrv_to->out_dir_fd = -1; fsrv_to->child_pid = -1; fsrv_to->use_fauxsrv = 0; fsrv_to->last_run_timed_out = 0; + fsrv_to->late_send = from->late_send; + fsrv_to->custom_data_ptr = from->custom_data_ptr; + fsrv_to->init_child_func = from->init_child_func; // Note: do not copy ->add_extra_func or ->persistent_record* @@ -295,8 +307,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -static u32 __attribute__((hot)) -read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, volatile u8 *stop_soon_p) { +static u32 __attribute__((hot)) read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, + volatile u8 *stop_soon_p) { fd_set readfds; FD_ZERO(&readfds); @@ -1326,6 +1338,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->map_size = tmp_map_size; + } else { + + fsrv->real_map_size = fsrv->map_size = MAP_SIZE; + } if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { @@ -1432,6 +1448,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + } else { + + // The binary is most likely instrumented using AFL's tool, and we will + // set map_size to MAP_SIZE. + fsrv->real_map_size = fsrv->map_size = MAP_SIZE; + } } @@ -1683,8 +1705,8 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, /* Delete the current testcase and write the buf to the testcase file */ -void __attribute__((hot)) -afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { +void __attribute__((hot)) afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, + u8 *buf, size_t len) { #ifdef __linux__ if (unlikely(fsrv->nyx_mode)) { @@ -1802,9 +1824,8 @@ afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t __attribute__((hot)) -afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, - volatile u8 *stop_soon_p) { +fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target( + afl_forkserver_t *fsrv, u32 timeout, volatile u8 *stop_soon_p) { s32 res; u32 exec_ms; @@ -1944,6 +1965,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } + if (unlikely(fsrv->late_send)) { + + fsrv->late_send(fsrv->custom_data_ptr, fsrv->custom_input, + fsrv->custom_input_len); + + } + exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout, stop_soon_p); diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 03bc5d6c..fd75a822 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -75,9 +75,13 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { } +#if __has_builtin(__builtin_popcount) + ret += __builtin_popcount(v); +#else v -= ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; +#endif } @@ -452,14 +456,14 @@ void write_crash_readme(afl_state_t *afl) { save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ -u8 __attribute__((hot)) -save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { +u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, + u32 len, u8 fault) { if (unlikely(len == 0)) { return 0; } if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -485,7 +489,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Generating a hash on every input is super expensive. Bad idea and should only be used for special schedules */ - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); classified = 1; diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 55b6be04..da996602 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -455,13 +455,13 @@ void deunicode_extras(afl_state_t *afl) { case 2: if (!afl->extras[i].data[j]) { ++z3; } - // fall through + __attribute__((fallthrough)); case 0: if (!afl->extras[i].data[j]) { ++z1; } break; case 3: if (!afl->extras[i].data[j]) { ++z4; } - // fall through + __attribute__((fallthrough)); case 1: if (!afl->extras[i].data[j]) { ++z2; } break; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7310e49f..10951300 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; @@ -2443,20 +2443,19 @@ void check_crash_handling(void) { SAYF( "\n" cLRD "[-] " cRST - "Hmm, your system is configured to send core dump notifications to an\n" + "Your system is configured to send core dump notifications to an\n" " external utility. This will cause issues: there will be an " "extended delay\n" " between stumbling upon a crash and having this information " "relayed to the\n" " fuzzer via the standard waitpid() API.\n" - " If you're just testing, set " + " If you're just experimenting, set " "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n" - " To avoid having crashes misinterpreted as timeouts, please log in " - "as root\n" - " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" + " To avoid having crashes misinterpreted as timeouts, please \n" + " temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" - " echo core >/proc/sys/kernel/core_pattern\n"); + " echo core | sudo tee /proc/sys/kernel/core_pattern\n"); if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) { @@ -2717,7 +2716,11 @@ void fix_up_sync(afl_state_t *afl) { } - if (strlen(afl->sync_id) > 32) { FATAL("Fuzzer ID too long"); } + if (strlen(afl->sync_id) > 50) { + + FATAL("sync_id max length is 50 characters"); + + } x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 74bb8cbc..fd5ed87c 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3914,7 +3914,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { #define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2) #define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1)) #define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l)) -#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1) +#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l) - 1) - EFF_APOS(_p) + 1) /* Initialize effector map for the next step (see comments below). Always flag first and last byte as doing something. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 313e8ae5..8db89775 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -123,7 +123,7 @@ void create_alias_table(afl_state_t *afl) { double weight = 1.0; { // inline does result in a compile error with LTO, weird - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { u32 hits = afl->n_fuzz[q->n_fuzz_entry]; if (likely(hits)) { weight /= (log10(hits) + 1); } @@ -133,39 +133,127 @@ void create_alias_table(afl_state_t *afl) { if (likely(afl->schedule < RARE)) { double t = q->exec_us / avg_exec_us; + if (likely(t < 0.1)) { // nothing - } else if (likely(t <= 0.25)) + } else if (likely(t <= 0.25)) { + + weight *= 0.95; - weight *= 0.9; - else if (likely(t <= 0.5)) { + } else if (likely(t <= 0.5)) { // nothing - } else if (likely(t < 1.0)) + } else if (likely(t <= 0.75)) { + + weight *= 1.05; + + } else if (likely(t <= 1.0)) { + + weight *= 1.1; + + } else if (likely(t < 1.25)) { + + weight *= 0.2; // WTF ??? makes no sense + + } else if (likely(t <= 1.5)) { + + // nothing + + } else if (likely(t <= 2.0)) { + + weight *= 1.1; + + } else if (likely(t <= 2.5)) { + + } else if (likely(t <= 5.0)) { weight *= 1.15; - else if (unlikely(t > 2.5 && t < 5.0)) + + } else if (likely(t <= 20.0)) { + weight *= 1.1; - // else nothing + // else nothing + + } } double l = q->len / avg_len; - if (likely(l < 0.1)) - weight *= 0.75; - else if (likely(l < 0.25)) - weight *= 1.1; - else if (unlikely(l >= 10)) - weight *= 1.1; + if (likely(l < 0.1)) { + + weight *= 0.5; + + } else if (likely(l <= 0.5)) { + + // nothing + + } else if (likely(l <= 1.25)) { + + weight *= 1.05; + + } else if (likely(l <= 1.75)) { + + // nothing + + } else if (likely(l <= 2.0)) { + + weight *= 0.95; + + } else if (likely(l <= 5.0)) { + + // nothing + + } else if (likely(l <= 10.0)) { + + weight *= 1.05; + + } else { + + weight *= 1.15; + + } double bms = q->bitmap_size / avg_bitmap_size; - if (likely(bms < 0.5)) - weight *= (1.0 + ((bms - 0.5) / 2)); - else if (unlikely(bms > 1.33)) - weight *= 1.1; + if (likely(bms < 0.1)) { + + weight *= 0.01; + + } else if (likely(bms <= 0.25)) { + + weight *= 0.55; + + } else if (likely(bms <= 0.5)) { + + // nothing + + } else if (likely(bms <= 0.75)) { + + weight *= 1.2; + + } else if (likely(bms <= 1.25)) { + + weight *= 1.3; + + } else if (likely(bms <= 1.75)) { + + weight *= 1.25; + + } else if (likely(bms <= 2.0)) { + + // nothing + + } else if (likely(bms <= 2.5)) { + + weight *= 1.3; + + } else { + + weight *= 0.75; + + } if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } if (unlikely(q->fs_redundant)) { weight *= 0.75; } @@ -387,6 +475,17 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { q->fs_redundant = state; + if (likely(q->fs_redundant)) { + + if (unlikely(q->trace_mini)) { + + ck_free(q->trace_mini); + q->trace_mini = NULL; + + } + + } + sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, strrchr((char *)q->fname, '/') + 1); @@ -400,7 +499,9 @@ 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);*/ + + } } @@ -698,12 +799,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); @@ -739,7 +839,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fav_factor; u64 fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { fuzz_p2 = 0; // Skip the fuzz_p2 comparison @@ -775,7 +875,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison @@ -811,7 +911,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!--afl->top_rated[i]->tc_ref) { ck_free(afl->top_rated[i]->trace_mini); - afl->top_rated[i]->trace_mini = 0; + afl->top_rated[i]->trace_mini = NULL; } @@ -872,7 +972,8 @@ void cull_queue(afl_state_t *afl) { for (i = 0; i < afl->fsrv.map_size; ++i) { - if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { + if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7))) && + afl->top_rated[i]->trace_mini) { u32 j = len; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 6a0da6ab..4ce17eb2 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -41,8 +41,9 @@ u64 time_spent_working = 0; /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t __attribute__((hot)) -fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { +fsrv_run_result_t __attribute__((hot)) fuzz_run_target(afl_state_t *afl, + afl_forkserver_t *fsrv, + u32 timeout) { #ifdef PROFILING static u64 time_spent_start = 0; @@ -60,6 +61,27 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); +#ifdef __AFL_CODE_COVERAGE + if (unlikely(!fsrv->persistent_trace_bits)) { + + // On the first run, we allocate the persistent map to collect coverage. + fsrv->persistent_trace_bits = (u8 *)malloc(fsrv->map_size); + memset(fsrv->persistent_trace_bits, 0, fsrv->map_size); + + } + + for (u32 i = 0; i < fsrv->map_size; ++i) { + + if (fsrv->persistent_trace_bits[i] != 255 && fsrv->trace_bits[i]) { + + fsrv->persistent_trace_bits[i]++; + + } + + } + +#endif + /* If post_run() function is defined in custom mutator, the function will be called each time after AFL++ executes the target program. */ @@ -90,8 +112,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -u32 __attribute__((hot)) -write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { +u32 __attribute__((hot)) write_to_testcase(afl_state_t *afl, void **mem, + u32 len, u32 fix) { u8 sent = 0; @@ -173,7 +195,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { if (el->afl_custom_fuzz_send) { - el->afl_custom_fuzz_send(el->data, *mem, new_size); + if (!afl->afl_env.afl_custom_mutator_late_send) { + + el->afl_custom_fuzz_send(el->data, *mem, new_size); + + } else { + + afl->fsrv.custom_input = *mem; + afl->fsrv.custom_input_len = new_size; + + } + sent = 1; } @@ -185,17 +217,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { /* everything as planned. use the potentially new data. */ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size); - if (likely(!afl->afl_env.afl_post_process_keep_original)) { + } - len = new_size; + if (likely(!afl->afl_env.afl_post_process_keep_original)) { - } else { + len = new_size; - /* restore the original memory which was saved in new_mem */ - *mem = new_mem; - afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + } else { - } + /* restore the original memory which was saved in new_mem */ + *mem = new_mem; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); } @@ -1142,8 +1174,8 @@ abort_trimming: error conditions, returning 1 if it's time to bail out. This is a helper function for fuzz_one(). */ -u8 __attribute__((hot)) -common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { +u8 __attribute__((hot)) common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, + u32 len) { u8 fault; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index fbe6d32a..eead3e50 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -286,6 +286,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_no_sync = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_FASTRESUME", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_fastresume = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { @@ -293,6 +300,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_CUSTOM_MUTATOR_LATE_SEND", + + afl_environment_variable_len)) { + + afl->afl_env.afl_custom_mutator_late_send = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 3a71e158..9f5f59c0 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -76,7 +76,13 @@ char *get_fuzzing_state(afl_state_t *afl) { void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX], fn2[PATH_MAX]; + + snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); + FILE *f2 = create_ffile(fn2); + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); + fclose(f2); + snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); FILE *f = create_ffile(fn); u32 i; @@ -957,9 +963,9 @@ void show_stats_normal(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->non_instrumented_mode) { @@ -1001,7 +1007,7 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); SAYF(bV bSTOP " run time : " cRST "%-33s " bSTG bV bSTOP - " cycles done : %s%-5s " bSTG bV "\n", + " cycles done : %s%-5s " bSTG bV "\n", time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); /* We want to warn people about not seeing new paths after a full cycle, @@ -1041,7 +1047,7 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); SAYF(bV bSTOP "last saved crash : " cRST "%-33s " bSTG bV bSTOP - "saved crashes : %s%-6s" bSTG bV "\n", + "saved crashes : %s%-6s" bSTG bV "\n", time_tmp, crash_color, tmp); sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs), @@ -1049,12 +1055,12 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); SAYF(bV bSTOP " last saved hang : " cRST "%-33s " bSTG bV bSTOP - " saved hangs : " cRST "%-6s" bSTG bV "\n", + " saved hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA - " map coverage" bSTG bHT bH20 bH2 bVL "\n"); + " map coverage" bSTG bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -1085,9 +1091,9 @@ void show_stats_normal(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_items); @@ -1095,7 +1101,7 @@ void show_stats_normal(afl_state_t *afl) { /* Yeah... it's still going on... halp? */ SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP - " favored items : " cRST "%-20s" bSTG bV "\n", + " favored items : " cRST "%-20s" bSTG bV "\n", afl->stage_name, tmp); if (!afl->stage_max) { @@ -1124,13 +1130,13 @@ void show_stats_normal(afl_state_t *afl) { if (afl->crash_mode) { SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP - " new crashes : %s%-20s" bSTG bV "\n", + " new crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } else { SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP - " total crashes : %s%-20s" bSTG bV "\n", + " total crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } @@ -1183,7 +1189,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " bit flips : " cRST "%-36s " bSTG bV bSTOP - " levels : " cRST "%-10s" bSTG bV "\n", + " levels : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->max_depth)); if (unlikely(!afl->skip_deterministic)) { @@ -1199,7 +1205,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP - " pending : " cRST "%-10s" bSTG bV "\n", + " pending : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); if (unlikely(!afl->skip_deterministic)) { @@ -1215,7 +1221,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP - " pend fav : " cRST "%-10s" bSTG bV "\n", + " pend fav : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_favored)); if (unlikely(!afl->skip_deterministic)) { @@ -1231,7 +1237,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP - " own finds : " cRST "%-10s" bSTG bV "\n", + " own finds : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->queued_discovered)); if (unlikely(!afl->skip_deterministic)) { @@ -1257,7 +1263,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP - " imported : " cRST "%-10s" bSTG bV "\n", + " imported : " cRST "%-10s" bSTG bV "\n", tmp, afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a"); @@ -1445,8 +1451,8 @@ void show_stats_normal(afl_state_t *afl) { /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN - " %s " bSTG bH10 cCYA bSTOP " state:" cPIN + SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN + " %s " bSTG bH10 cCYA bSTOP " state:" cPIN " %s " bSTG bH2 bRB bSTOP cRST RESET_G1, afl->fuzz_mode == 0 ? "explore" : "exploit", get_fuzzing_state(afl)); @@ -1815,8 +1821,8 @@ void show_stats_pizza(afl_state_t *afl) { } u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); - SAYF(bV bSTOP - " open time : " cRST "%-37s " bSTG bV bSTOP + SAYF(bV bSTOP + " open time : " cRST "%-37s " bSTG bV bSTOP " seasons done : %s%-5s " bSTG bV "\n", time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); @@ -1859,7 +1865,7 @@ void show_stats_pizza(afl_state_t *afl) { (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); - SAYF(bV bSTOP + SAYF(bV bSTOP " last ordered pizza : " cRST "%-33s " bSTG bV bSTOP " at table : %s%-6s " bSTG bV "\n", time_tmp, crash_color, tmp); @@ -1868,15 +1874,15 @@ void show_stats_pizza(afl_state_t *afl) { (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); - SAYF(bV bSTOP + SAYF(bV bSTOP " last conversation with customers : " cRST "%-33s " bSTG bV bSTOP " number of Peroni : " cRST "%-6s " bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " Baking progress " bSTG bH30 bH20 bH5 bH bX bH bSTOP cCYA - " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n"); + " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -1912,8 +1918,8 @@ void show_stats_pizza(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-19s " bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA - " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA + " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA " Types of pizzas cooking " bSTG bH10 bH5 bH2 bH10 bH2 bH bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), @@ -1922,7 +1928,7 @@ void show_stats_pizza(afl_state_t *afl) { /* Yeah... it's still going on... halp? */ SAYF(bV bSTOP " now preparing : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " favourite topping : " cRST "%-20s" bSTG bV "\n", afl->stage_name, tmp); @@ -1955,14 +1961,14 @@ void show_stats_pizza(afl_state_t *afl) { if (afl->crash_mode) { SAYF(bV bSTOP " total pizzas : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " pizzas with pineapple : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } else { SAYF(bV bSTOP " total pizzas : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " total pizzas with pineapple : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); @@ -1999,7 +2005,7 @@ void show_stats_pizza(afl_state_t *afl) { /* Aaaalmost there... hold on! */ SAYF(bVR bH cCYA bSTOP " Promotional campaign on TikTok yields " bSTG bH30 bH2 - bH bH2 bX bH bSTOP cCYA + bH bH2 bX bH bSTOP cCYA " Customer type " bSTG bH5 bH2 bH30 bH2 bH bVL "\n"); if (unlikely(afl->custom_only)) { @@ -2022,8 +2028,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP " levels : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->max_depth)); @@ -2040,8 +2046,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP " pizzas to make : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); @@ -2058,8 +2064,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizza bianca : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizza bianca : " cRST "%-36s " bSTG bV bSTOP " nice table : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_favored)); @@ -2076,8 +2082,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " recurring customers : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " recurring customers : " cRST "%-36s " bSTG bV bSTOP " new customers : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->queued_discovered)); @@ -2104,8 +2110,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " dictionary : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " dictionary : " cRST "%-36s " bSTG bV bSTOP " patrons from old resturant : " cRST "%-10s " bSTG bV "\n", tmp, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a7ddef6e..726a2260 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -36,6 +36,67 @@ #include <sys/ipc.h> #include <sys/shm.h> #endif +#ifdef HAVE_ZLIB + + #define ck_gzread(fd, buf, len, fn) \ + do { \ + \ + s32 _len = (s32)(len); \ + s32 _res = gzread(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ + \ + } while (0) + + #define ck_gzwrite(fd, buf, len, fn) \ + do { \ + \ + if (len <= 0) break; \ + s32 _written = 0, _off = 0, _len = (s32)(len); \ + \ + do { \ + \ + s32 _res = gzwrite(fd, (buf) + _off, _len); \ + if (_res != _len && (_res > 0 && _written + _res != _len)) { \ + \ + if (_res > 0) { \ + \ + _written += _res; \ + _len -= _res; \ + _off += _res; \ + \ + } else { \ + \ + RPFATAL(_res, "Short write to %s (%d of %d bytes)", fn, _res, \ + _len); \ + \ + } \ + \ + } else { \ + \ + break; \ + \ + } \ + \ + } while (1); \ + \ + \ + \ + } while (0) + + #include <zlib.h> + #define ZLIBOPEN gzopen + #define ZLIBREAD ck_gzread + #define NZLIBREAD gzread + #define ZLIBWRITE ck_gzwrite + #define ZLIBCLOSE gzclose + #define ZLIB_EXTRA "9" +#else + #define ZLIBOPEN open + #define NZLIBREAD read + #define ZLIBREAD ck_read + #define ZLIBWRITE ck_write + #define ZLIBCLOSE close +#endif #ifdef __APPLE__ #include <sys/qos.h> @@ -181,7 +242,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 " @@ -335,6 +396,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" " suported formats: dogstatsd, librato, signalfx, influxdb\n" + "AFL_NO_FASTRESUME: do not read or write a fast resume file\n" "AFL_NO_SYNC: disables all syncing\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n" @@ -960,7 +1022,11 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); } + if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 5) { + + FATAL("Dangerously low value of -m"); + + } if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) { @@ -1544,17 +1610,7 @@ int main(int argc, char **argv_orig, char **envp) { #endif - if (afl->sync_id) { - - if (strlen(afl->sync_id) > 50) { - - FATAL("sync_id max length is 50 characters"); - - } - - fix_up_sync(afl); - - } + if (afl->sync_id) { fix_up_sync(afl); } if (!strcmp(afl->in_dir, afl->out_dir)) { @@ -1868,6 +1924,15 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Using Frida Address Sanitizer Mode"); + if (afl->fsrv.mem_limit) { + + WARNF( + "in the Frida Address Sanitizer Mode we disable all memory " + "limits"); + afl->fsrv.mem_limit = 0; + + } + fasan_check_afl_preload(afl_preload); setenv("ASAN_OPTIONS", "detect_leaks=false", 1); @@ -2067,6 +2132,31 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->custom_mutators_count && afl->afl_env.afl_custom_mutator_late_send) { + + u32 count_send = 0; + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz_send) { + + if (count_send) { + + FATAL( + "You can only have one custom send() function if you are using " + "AFL_CUSTOM_MUTATOR_LATE_SEND!"); + + } + + afl->fsrv.late_send = el->afl_custom_fuzz_send; + afl->fsrv.custom_data_ptr = el->data; + count_send = 1; + + } + + }); + + } + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { if (afl->custom_only) { @@ -2101,13 +2191,92 @@ int main(int argc, char **argv_orig, char **envp) { } + setup_cmdline_file(afl, argv + optind); + check_binary(afl, argv[optind]); + + u64 prev_target_hash = 0; + s32 fast_resume = 0; + #ifdef HAVE_ZLIB + gzFile fr_fd = NULL; + #else + s32 fr_fd = -1; + #endif + + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { + + u8 fn[PATH_MAX], buf[32]; + snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir); + s32 fd = open(fn, O_RDONLY); + if (fd >= 0) { + + if (read(fd, buf, 32) >= 16) { + + sscanf(buf, "%p", (void **)&prev_target_hash); + + } + + close(fd); + + } + + } + write_setup_file(afl, argc, argv); - setup_cmdline_file(afl, argv + optind); + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { + + u64 target_hash = get_binary_hash(afl->fsrv.target_path); + + if (!target_hash || prev_target_hash != target_hash) { + + ACTF("Target binary is different, cannot perform FAST RESUME!"); + + } else { + + u8 fn[PATH_MAX]; + snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fn, "rb")) != NULL) { + + #else + if ((fr_fd = open(fn, O_RDONLY)) >= 0) { + + #endif + + u8 ver_string[8]; + u64 *ver = (u64 *)ver_string; + u64 expect_ver = + afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + if (NZLIBREAD(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 { + + ACTF("fastresume.bin not found, cannot perform FAST RESUME!"); + + } + + // If the fast resume file is not valid we will be unable to start, so + // we remove the file but keep the file descriptor open. + unlink(fn); + + } + + } read_testcases(afl, NULL); - // read_foreign_testcases(afl, 1); for the moment dont do this - OKF("Loaded a total of %u seeds.", afl->queued_items); pivot_inputs(afl); @@ -2140,6 +2309,9 @@ int main(int argc, char **argv_orig, char **envp) { } + // read_foreign_testcases(afl, 1); for the moment dont do this + OKF("Loaded a total of %u seeds.", afl->queued_items); + /* If we don't have a file name chosen yet, use a safe default. */ if (!afl->fsrv.out_file) { @@ -2196,8 +2368,6 @@ int main(int argc, char **argv_orig, char **envp) { } - check_binary(afl, argv[optind]); - #ifdef AFL_PERSISTENT_RECORD if (unlikely(afl->fsrv.persistent_record)) { @@ -2416,7 +2586,7 @@ int main(int argc, char **argv_orig, char **envp) { } - OKF("Cmplog forkserver successfully started"); + OKF("CMPLOG forkserver successfully started"); } @@ -2454,29 +2624,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 + ZLIBREAD(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBREAD(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBREAD(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBREAD(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]; + ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ZLIBREAD(fr_fd, res, 1, "check map"); + if (res[0]) { + + q->trace_mini = ck_alloc(m_len); + ZLIBREAD(fr_fd, q->trace_mini, m_len, "trace_mini"); + r += q_len + m_len + 1; + + } 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; - memset(afl->virgin_tmout, 255, map_size); - memset(afl->virgin_crash, 255, map_size); + } + + if (q->var_behavior) { ++afl->queued_variable; } + if (q->favored) { - if (likely(!afl->afl_env.afl_no_startup_calibration)) { + ++afl->queued_favored; + if (!q->was_fuzzed) { ++afl->pending_favored; } - perform_dry_run(afl); + } + + } + + u8 buf[4]; + if (NZLIBREAD(fr_fd, buf, 3) > 0) { + + FATAL("invalid trailing data in fastresume.bin"); + + } + + OKF("Successfully loaded fastresume.bin (%u bytes)!", r); + ZLIBCLOSE(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); + + } } @@ -2562,7 +2805,7 @@ int main(int argc, char **argv_orig, char **envp) { // (void)nice(-20); // does not improve the speed #ifdef INTROSPECTION - u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; + u32 prev_saved_crashes = 0, prev_saved_tmouts = 0, stat_prev_queued_items = 0; #endif u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1; u8 skipped_fuzz; @@ -2879,10 +3122,11 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if (unlikely(afl->queued_items > prev_queued_items)) { + if (unlikely(afl->queued_items > stat_prev_queued_items)) { - afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items; - prev_queued_items = afl->queued_items; + afl->queue_cur->stats_finds += + afl->queued_items - stat_prev_queued_items; + stat_prev_queued_items = afl->queued_items; } @@ -2984,6 +3228,28 @@ stop_fuzzing: write_bitmap(afl); save_auto(afl); + #ifdef __AFL_CODE_COVERAGE + if (afl->fsrv.persistent_trace_bits) { + + char cfn[4096]; + snprintf(cfn, sizeof(cfn), "%s/covmap.dump", afl->out_dir); + + FILE *cov_fd; + if ((cov_fd = fopen(cfn, "w")) == NULL) { + + PFATAL("could not create '%s'", cfn); + + } + + // Write the real map size, as the map size must exactly match the pointer + // map in length. + fwrite(afl->fsrv.persistent_trace_bits, 1, afl->fsrv.real_map_size, cov_fd); + fclose(cov_fd); + + } + + #endif + if (afl->pizza_is_served) { SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST, @@ -3067,6 +3333,74 @@ stop_fuzzing: fclose(afl->fsrv.det_plot_file); #endif + if (!afl->afl_env.afl_no_fastresume) { + + /* create fastresume.bin */ + u8 fr[PATH_MAX]; + snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + ACTF("Writing %s ...", fr); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) { + + #else + if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= + 0) { + + #endif + + u8 ver_string[8]; + u32 w = 0; + u64 *ver = (u64 *)ver_string; + *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string"); + ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBWRITE(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBWRITE(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBWRITE(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); + w += sizeof(ver_string) + afl->fsrv.map_size * 4; + + 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]; + ZLIBWRITE(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + if (!q->trace_mini) { + + ZLIBWRITE(fr_fd, off, 1, "no_mini"); + w += q_len + 1; + + } else { + + ZLIBWRITE(fr_fd, on, 1, "yes_mini"); + ZLIBWRITE(fr_fd, q->trace_mini, m_len, "trace_mini"); + w += q_len + m_len + 1; + + } + + } + + ZLIBCLOSE(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); diff --git a/src/afl-performance.c b/src/afl-performance.c index e8ece6b5..b824fd35 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -99,11 +99,13 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { u64 get_binary_hash(u8 *fn) { + if (!fn) { return 0; } int fd = open(fn, O_RDONLY); if (fd < 0) { PFATAL("Unable to open '%s'", fn); } struct stat st; if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } u32 f_len = st.st_size; + if (!f_len) { return 0; } u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); diff --git a/src/hashmap.c b/src/hashmap.c index a0a9283c..5834802f 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -59,7 +59,7 @@ static inline unsigned int hash(uint64_t key) { bool hashmap_search_and_add(uint8_t type, uint64_t key) { if (unlikely(type >= 8)) return false; - uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56); + uint64_t val = (key & 0xf8ffffffffffffff) + ((uint64_t)type << 56); unsigned int index = hash(val); HashNode *node = _hashmap->table[index]; while (node) { |