diff options
Diffstat (limited to 'src/afl-fuzz-stats.c')
-rw-r--r-- | src/afl-fuzz-stats.c | 354 |
1 files changed, 264 insertions, 90 deletions
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 07157bf7..ffe56cde 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -5,11 +5,12 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse <mh@mh-sec.de>, - Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and - Andrea Fioraldi <andreafioraldi@gmail.com> + Dominik Meier <mail@dmnk.co>, + Andrea Fioraldi <andreafioraldi@gmail.com>, and + Heiko Eissfeldt <heiko.eissfeldt@hexco.de> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -27,6 +28,50 @@ #include "envs.h" #include <limits.h> +static char fuzzing_state[4][12] = {"started :-)", "in progress", "final phase", + "finished..."}; + +char *get_fuzzing_state(afl_state_t *afl) { + + u64 cur_ms = get_cur_time(); + u64 last_find = cur_ms - afl->last_find_time; + u64 cur_run_time = cur_ms - afl->start_time; + u64 cur_total_run_time = afl->prev_run_time + cur_run_time; + + if (unlikely(afl->non_instrumented_mode)) { + + return fuzzing_state[1]; + + } else if (unlikely(cur_run_time < 60 * 3 * 1000 || + + cur_total_run_time < 60 * 5 * 1000)) { + + return fuzzing_state[0]; + + } else { + + u64 last_find_100 = 100 * last_find; + u64 percent_cur = last_find_100 / cur_run_time; + u64 percent_total = last_find_100 / cur_total_run_time; + + if (unlikely(percent_cur >= 80 && percent_total >= 80)) { + + return fuzzing_state[3]; + + } else if (unlikely(percent_cur >= 55 && percent_total >= 55)) { + + return fuzzing_state[2]; + + } else { + + return fuzzing_state[1]; + + } + + } + +} + /* Write fuzzer setup file */ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { @@ -89,6 +134,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { } +static bool starts_with(char *key, char *line) { + + return strncmp(key, line, strlen(key)) == 0; + +} + /* load some of the existing stats file when resuming.*/ void load_stats_file(afl_state_t *afl) { @@ -131,58 +182,84 @@ void load_stats_file(afl_state_t *afl) { strcpy(keystring, lstartptr); lptr++; char *nptr; - switch (lineno) { - - case 3: - if (!strcmp(keystring, "run_time ")) - afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); - break; - case 5: - if (!strcmp(keystring, "cycles_done ")) - afl->queue_cycle = - strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; - break; - case 7: - if (!strcmp(keystring, "execs_done ")) - afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); - break; - case 10: - if (!strcmp(keystring, "corpus_count ")) { - - u32 corpus_count = strtoul(lptr, &nptr, 10); - if (corpus_count != afl->queued_items) { - - WARNF( - "queue/ has been modified -- things might not work, you're " - "on your own!"); - - } - - } - - break; - case 12: - if (!strcmp(keystring, "corpus_found ")) - afl->queued_discovered = strtoul(lptr, &nptr, 10); - break; - case 13: - if (!strcmp(keystring, "corpus_imported ")) - afl->queued_imported = strtoul(lptr, &nptr, 10); - break; - case 14: - if (!strcmp(keystring, "max_depth ")) - afl->max_depth = strtoul(lptr, &nptr, 10); - break; - case 21: - if (!strcmp(keystring, "saved_crashes ")) - afl->saved_crashes = strtoull(lptr, &nptr, 10); - break; - case 22: - if (!strcmp(keystring, "saved_hangs ")) - afl->saved_hangs = strtoull(lptr, &nptr, 10); - break; - default: - break; + if (starts_with("run_time", keystring)) { + + afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); + + } + + if (starts_with("cycles_done", keystring)) { + + afl->queue_cycle = + strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; + + } + + if (starts_with("calibration_time", keystring)) { + + afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000; + + } + + if (starts_with("sync_time", keystring)) { + + afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000; + + } + + if (starts_with("trim_time", keystring)) { + + afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; + + } + + if (starts_with("execs_done", keystring)) { + + afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); + + } + + if (starts_with("corpus_count", keystring)) { + + u32 corpus_count = strtoul(lptr, &nptr, 10); + if (corpus_count != afl->queued_items) { + + WARNF( + "queue/ has been modified -- things might not work, you're " + "on your own!"); + sleep(3); + + } + + } + + if (starts_with("corpus_found", keystring)) { + + afl->queued_discovered = strtoul(lptr, &nptr, 10); + + } + + if (starts_with("corpus_imported", keystring)) { + + afl->queued_imported = strtoul(lptr, &nptr, 10); + + } + + if (starts_with("max_depth", keystring)) { + + afl->max_depth = strtoul(lptr, &nptr, 10); + + } + + if (starts_with("saved_crashes", keystring)) { + + afl->saved_crashes = strtoull(lptr, &nptr, 10); + + } + + if (starts_with("saved_hangs", keystring)) { + + afl->saved_hangs = strtoull(lptr, &nptr, 10); } @@ -206,11 +283,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #endif u64 cur_time = get_cur_time(); - u8 fn[PATH_MAX]; + u8 fn_tmp[PATH_MAX]; + u8 fn_final[PATH_MAX]; FILE *f; - snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); - f = create_ffile(fn); + snprintf(fn_tmp, PATH_MAX, "%s/.fuzzer_stats_tmp", afl->out_dir); + snprintf(fn_final, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); + f = create_ffile(fn_tmp); /* Keep last values in case we're called from another context where exec/sec stats and such are not readily available. */ @@ -242,6 +321,9 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #ifndef __HAIKU__ if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } #endif + u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time; + u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000; + if (!runtime_ms) { runtime_ms = 1; } fprintf( f, @@ -252,6 +334,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "cycles_done : %llu\n" "cycles_wo_finds : %llu\n" "time_wo_finds : %llu\n" + "fuzz_time : %llu\n" + "calibration_time : %llu\n" + "sync_time : %llu\n" + "trim_time : %llu\n" "execs_done : %llu\n" "execs_per_sec : %0.02f\n" "execs_ps_last_min : %0.02f\n" @@ -289,18 +375,18 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "\n" "target_mode : %s%s%s%s%s%s%s%s%s%s\n" "command_line : %s\n", - (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, - (afl->prev_run_time + cur_time - afl->start_time) / 1000, (u32)getpid(), + (afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000, + runtime_ms / 1000, (u32)getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, afl->longest_find_time > cur_time - afl->last_find_time ? afl->longest_find_time / 1000 : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), - afl->fsrv.total_execs, - afl->fsrv.total_execs / - ((double)(afl->prev_run_time + get_cur_time() - afl->start_time) / - 1000), + (runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000, + afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, + afl->trim_time_us / 1000000, afl->fsrv.total_execs, + afl->fsrv.total_execs / ((double)(runtime_ms) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, afl->max_depth, afl->current_entry, afl->pending_favored, @@ -368,6 +454,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } fclose(f); + rename(fn_tmp, fn_final); } @@ -456,6 +543,44 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } +/* Log deterministic stage efficiency */ + +void plot_profile_data(afl_state_t *afl, struct queue_entry *q) { + + u64 current_ms = get_cur_time() - afl->start_time; + + u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); + double det_finding_rate = (double)afl->havoc_prof->total_det_edge * 100.0 / + (double)current_edges, + det_time_rate = (double)afl->havoc_prof->total_det_time * 100.0 / + (double)current_ms; + + u32 ndet_bits = 0; + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (afl->skipdet_g->virgin_det_bits[i]) ndet_bits += 1; + + } + + double det_fuzzed_rate = (double)ndet_bits * 100.0 / (double)current_edges; + + fprintf(afl->fsrv.det_plot_file, + "[%02lld:%02lld:%02lld] fuzz %d (%d), find %d/%d among %d(%02.2f) " + "and spend %lld/%lld(%02.2f), cover %02.2f yet, %d/%d undet bits, " + "continue %d.\n", + current_ms / 1000 / 3600, (current_ms / 1000 / 60) % 60, + (current_ms / 1000) % 60, afl->current_entry, q->fuzz_level, + afl->havoc_prof->edge_det_stage, afl->havoc_prof->edge_havoc_stage, + current_edges, det_finding_rate, + afl->havoc_prof->det_stage_time / 1000, + afl->havoc_prof->havoc_stage_time / 1000, det_time_rate, + det_fuzzed_rate, q->skipdet_e->undet_bits, + afl->skipdet_g->undet_bits_threshold, q->skipdet_e->continue_inf); + + fflush(afl->fsrv.det_plot_file); + +} + /* Check terminal dimensions after resize. */ static void check_term_size(afl_state_t *afl) { @@ -505,9 +630,9 @@ void show_stats_normal(afl_state_t *afl) { cur_ms = get_cur_time(); - if (afl->most_time_key) { + if (afl->most_time_key && afl->queue_cycle) { - if (afl->most_time * 1000 < cur_ms - afl->start_time) { + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < cur_ms - afl->start_time) { afl->most_time_key = 2; afl->stop_soon = 2; @@ -516,7 +641,7 @@ void show_stats_normal(afl_state_t *afl) { } - if (afl->most_execs_key == 1) { + if (afl->most_execs_key == 1 && afl->queue_cycle) { if (afl->most_execs <= afl->fsrv.total_execs) { @@ -734,10 +859,29 @@ void show_stats_normal(afl_state_t *afl) { if (unlikely(!banner[0])) { char *si = ""; + char *fuzzer_name; + if (afl->sync_id) { si = afl->sync_id; } memset(banner, 0, sizeof(banner)); - banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) + - strlen(afl->power_name) + 4 + 6; + + banner_len = strlen(VERSION) + strlen(si) + strlen(afl->power_name) + 4 + 6; + + if (afl->crash_mode) { + + fuzzer_name = "peruvian were-rabbit"; + + } else { + + fuzzer_name = "american fuzzy lop"; + if (banner_len + strlen(fuzzer_name) + strlen(afl->use_banner) > 75) { + + fuzzer_name = "AFL"; + + } + + } + + banner_len += strlen(fuzzer_name); if (strlen(afl->use_banner) + banner_len > 75) { @@ -754,19 +898,18 @@ void show_stats_normal(afl_state_t *afl) { if (afl->fsrv.nyx_mode) { snprintf(banner + banner_pad, sizeof(banner) - banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", - si, afl->use_banner, afl->power_name); + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN + "[%s] - Nyx", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); } else { #endif snprintf(banner + banner_pad, sizeof(banner) - banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", - si, afl->use_banner, afl->power_name); + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); #ifdef __linux__ @@ -774,6 +917,10 @@ void show_stats_normal(afl_state_t *afl) { #endif + if (banner_pad) + for (u32 i = 0; i < banner_pad; ++i) + strcat(banner, " "); + } SAYF("\n%s\n", banner); @@ -995,7 +1142,7 @@ void show_stats_normal(afl_state_t *afl) { sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), u_stringify_int(IB(1), afl->saved_tmouts), - (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp); @@ -1010,7 +1157,7 @@ void show_stats_normal(afl_state_t *afl) { } else if (likely(afl->skip_deterministic)) { - strcpy(tmp, "disabled (default, enable with -D)"); + strcpy(tmp, "disabled (-z switch used)"); } else { @@ -1282,7 +1429,11 @@ void show_stats_normal(afl_state_t *afl) { } /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); + + 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)); #undef IB @@ -1309,9 +1460,9 @@ void show_stats_pizza(afl_state_t *afl) { cur_ms = get_cur_time(); - if (afl->most_time_key) { + if (afl->most_time_key && afl->queue_cycle) { - if (afl->most_time * 1000 < cur_ms - afl->start_time) { + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < cur_ms - afl->start_time) { afl->most_time_key = 2; afl->stop_soon = 2; @@ -1320,7 +1471,7 @@ void show_stats_pizza(afl_state_t *afl) { } - if (afl->most_execs_key == 1) { + if (afl->most_execs_key == 1 && afl->queue_cycle) { if (afl->most_execs <= afl->fsrv.total_execs) { @@ -1823,7 +1974,7 @@ void show_stats_pizza(afl_state_t *afl) { sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), u_stringify_int(IB(1), afl->saved_tmouts), - (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); SAYF(bSTG bV bSTOP " burned pizzas : " cRST "%-20s" bSTG bV "\n", @@ -2260,7 +2411,12 @@ void show_init_stats(afl_state_t *afl) { stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), stringify_int(IB(2), avg_us)); - if (afl->timeout_given != 1) { + if (afl->timeout_given == 3) { + + ACTF("Applying timeout settings from resumed session (%u ms).", + afl->fsrv.exec_tmout); + + } else if (afl->timeout_given != 1) { /* Figure out the appropriate timeout. The basic idea is: 5x average or 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. @@ -2302,11 +2458,6 @@ void show_init_stats(afl_state_t *afl) { afl->timeout_given = 1; - } else if (afl->timeout_given == 3) { - - ACTF("Applying timeout settings from resumed session (%u ms).", - afl->fsrv.exec_tmout); - } else { ACTF("-t option specified. We'll use an exec timeout of %u ms.", @@ -2329,3 +2480,26 @@ void show_init_stats(afl_state_t *afl) { } +void update_calibration_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->calibration_time_us += cur - *time; + *time = cur; + +} + +void update_trim_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->trim_time_us += cur - *time; + *time = cur; + +} + +void update_sync_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->sync_time_us += cur - *time; + *time = cur; + +} |