From 3ab18d286142e2e19e37850c051e0b07b9d7b296 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Apr 2023 19:44:12 +0200 Subject: mode switch --- include/afl-fuzz.h | 69 +++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 58d02af5..6573eabf 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -490,7 +490,9 @@ typedef struct afl_state { *orig_cmdline, /* Original command line */ *infoexec; /* Command to execute on a new crash */ - u32 hang_tmout; /* Timeout used for hang det (ms) */ + u32 hang_tmout, /* Timeout used for hang det (ms) */ + stats_update_freq, /* Stats update frequency (execs) */ + switch_fuzz_mode; /* auto or fixed fuzz mode */ u8 havoc_stack_pow2, /* HAVOC_STACK_POW2 */ no_unlink, /* do not unlink cur_input */ @@ -499,40 +501,37 @@ typedef struct afl_state { custom_splice_optout, /* Custom mutator no splice buffer */ is_main_node, /* if this is the main node */ is_secondary_node, /* if this is a secondary instance */ - pizza_is_served; /* pizza mode */ - - u32 stats_update_freq; /* Stats update frequency (execs) */ - - u8 schedule; /* Power schedule (default: EXPLORE)*/ - u8 havoc_max_mult; - - u8 skip_deterministic, /* Skip deterministic stages? */ - use_splicing, /* Recombine input files? */ - non_instrumented_mode, /* Run in non-instrumented mode? */ - score_changed, /* Scoring for favorites changed? */ - resuming_fuzz, /* Resuming an older fuzzing job? */ - timeout_given, /* Specific timeout given? */ - not_on_tty, /* stdout is not a tty */ - term_too_small, /* terminal dimensions too small */ - no_forkserver, /* Disable forkserver? */ - crash_mode, /* Crash mode! Yeah! */ - in_place_resume, /* Attempt in-place resume? */ - autoresume, /* Resume if afl->out_dir exists? */ - auto_changed, /* Auto-generated tokens changed? */ - no_cpu_meter_red, /* Feng shui on the status screen */ - no_arith, /* Skip most arithmetic ops */ - shuffle_queue, /* Shuffle input queue? */ - bitmap_changed, /* Time to update bitmap? */ - unicorn_mode, /* Running in Unicorn mode? */ - use_wine, /* Use WINE with QEMU mode */ - skip_requested, /* Skip request, via SIGUSR1 */ - run_over10m, /* Run time over 10 minutes? */ - persistent_mode, /* Running in persistent mode? */ - deferred_mode, /* Deferred forkserver mode? */ - fixed_seed, /* do not reseed */ - fast_cal, /* Try to calibrate faster? */ - disable_trim, /* Never trim in fuzz_one */ - shmem_testcase_mode, /* If sharedmem testcases are used */ + pizza_is_served, /* pizza mode */ + text_input, /* target wants text inputs */ + fuzz_mode, /* current mode: coverage/exploration or crash/exploitation */ + schedule, /* Power schedule (default: EXPLORE)*/ + havoc_max_mult, skip_deterministic, /* Skip deterministic stages? */ + use_splicing, /* Recombine input files? */ + non_instrumented_mode, /* Run in non-instrumented mode? */ + score_changed, /* Scoring for favorites changed? */ + resuming_fuzz, /* Resuming an older fuzzing job? */ + timeout_given, /* Specific timeout given? */ + not_on_tty, /* stdout is not a tty */ + term_too_small, /* terminal dimensions too small */ + no_forkserver, /* Disable forkserver? */ + crash_mode, /* Crash mode! Yeah! */ + in_place_resume, /* Attempt in-place resume? */ + autoresume, /* Resume if afl->out_dir exists? */ + auto_changed, /* Auto-generated tokens changed? */ + no_cpu_meter_red, /* Feng shui on the status screen */ + no_arith, /* Skip most arithmetic ops */ + shuffle_queue, /* Shuffle input queue? */ + bitmap_changed, /* Time to update bitmap? */ + unicorn_mode, /* Running in Unicorn mode? */ + use_wine, /* Use WINE with QEMU mode */ + skip_requested, /* Skip request, via SIGUSR1 */ + run_over10m, /* Run time over 10 minutes? */ + persistent_mode, /* Running in persistent mode? */ + deferred_mode, /* Deferred forkserver mode? */ + fixed_seed, /* do not reseed */ + fast_cal, /* Try to calibrate faster? */ + disable_trim, /* Never trim in fuzz_one */ + shmem_testcase_mode, /* If sharedmem testcases are used */ expand_havoc, /* perform expensive havoc after no find */ cycle_schedules, /* cycle power schedules? */ old_seed_selection, /* use vanilla afl seed selection */ -- cgit 1.4.1 From a74561b0e7434282ad214ca634b5c19c2f345e8e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 12:12:05 +0200 Subject: implement switch mode --- include/afl-fuzz.h | 6 +++--- src/afl-fuzz-bitmap.c | 12 ++++++++++++ src/afl-fuzz-state.c | 2 +- src/afl-fuzz.c | 30 ++++++++++++++++++++++++++---- 4 files changed, 42 insertions(+), 8 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 6573eabf..23a04f42 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -491,8 +491,7 @@ typedef struct afl_state { *infoexec; /* Command to execute on a new crash */ u32 hang_tmout, /* Timeout used for hang det (ms) */ - stats_update_freq, /* Stats update frequency (execs) */ - switch_fuzz_mode; /* auto or fixed fuzz mode */ + stats_update_freq; /* Stats update frequency (execs) */ u8 havoc_stack_pow2, /* HAVOC_STACK_POW2 */ no_unlink, /* do not unlink cur_input */ @@ -592,7 +591,8 @@ typedef struct afl_state { last_hang_time, /* Time for most recent hang (ms) */ longest_find_time, /* Longest time taken for a find */ exit_on_time, /* Delay to exit if no new paths */ - sync_time; /* Sync time (ms) */ + sync_time, /* Sync time (ms) */ + switch_fuzz_mode; /* auto or fixed fuzz mode */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ subseq_tmouts; /* Number of timeouts in a row */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d9c792d1..a937c96d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -529,6 +529,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { close(fd); add_to_queue(afl, queue_fn, len, 0); + if (unlikely(afl->fuzz_mode) && likely(afl->switch_fuzz_mode)) { + + if (afl->afl_env.afl_no_ui) { + + ACTF("New coverage found, switching back to exploration mode."); + + } + + afl->fuzz_mode = 0; + + } + #ifdef INTROSPECTION if (afl->custom_mutators_count && afl->current_custom_fuzz) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 907861e9..9dc258b1 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -108,7 +108,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->cmplog_lvl = 2; afl->min_length = 1; afl->max_length = MAX_FILE; - afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME; + afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000; #ifndef NO_SPLICING afl->use_splicing = 1; #endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 315107d7..c50b271b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -577,7 +577,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) { afl->fuzz_mode = 0; - afl->switch_fuzz_mode = 1; + afl->switch_fuzz_mode = 0; } else if (!stricmp(optarg, "exploit") || @@ -588,12 +588,16 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if ((s32)(afl->switch_fuzz_mode = (u32)atoi(optarg)) < 1) { + if ((afl->switch_fuzz_mode = (u32)atoi(optarg)) > INT_MAX) { FATAL( "Parameter for option -P must be \"explore\", \"exploit\" or a " "number!"); + } else { + + afl->switch_fuzz_mode *= 1000; + } } @@ -2689,13 +2693,31 @@ int main(int argc, char **argv_orig, char **envp) { } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon); + u64 cur_time = get_cur_time(); + + if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0) && + unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) { + + if (afl->afl_env.afl_no_ui) { + + ACTF( + "No new coverage found for %llu seconds, switching to exploitation " + "strategy.", + afl->switch_fuzz_mode / 1000); + + } + + afl->fuzz_mode = 1; + + } + if (likely(!afl->stop_soon && afl->sync_id)) { if (likely(afl->skip_deterministic)) { if (unlikely(afl->is_main_node)) { - if (unlikely(get_cur_time() > + if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) { if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { @@ -2708,7 +2730,7 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if (unlikely(get_cur_time() > afl->sync_time + afl->last_sync_time)) { + if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) { if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } -- cgit 1.4.1 From a2daef29f9c323c0a6a7a64013aadb79ffd3e534 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 27 Apr 2023 17:57:22 +0200 Subject: slightly different weighting algo (#1719) * better seed selection * slightly different weighting calculation * remove unnecessary memset --- include/afl-fuzz.h | 4 +-- src/afl-fuzz-queue.c | 92 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 65 insertions(+), 31 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 831a0dbc..8fb7ecb1 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1223,7 +1223,7 @@ double rand_next_percent(afl_state_t *afl); static inline u32 rand_below(afl_state_t *afl, u32 limit) { - if (limit <= 1) return 0; + if (unlikely(limit <= 1)) return 0; /* The boundary not being necessarily a power of 2, we need to ensure the result uniformity. */ @@ -1256,7 +1256,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { expand havoc mode */ static inline u32 rand_below_datalen(afl_state_t *afl, u32 limit) { - if (limit <= 1) return 0; + if (unlikely(limit <= 1)) return 0; switch (rand_below(afl, 3)) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 8ad7cd97..b10bf749 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { u32 s = rand_below(afl, afl->queued_items); double p = rand_next_percent(afl); + /* fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u" " ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p < afl->alias_probability[s] ? s : afl->alias_table[s]); */ + return (p < afl->alias_probability[s] ? s : afl->alias_table[s]); } @@ -87,25 +89,28 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, void create_alias_table(afl_state_t *afl) { - u32 n = afl->queued_items, i = 0, a, g; + u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1; double sum = 0; + double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double)); + u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); + u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); + afl->alias_table = (u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32)); afl->alias_probability = (double *)afl_realloc( (void **)&afl->alias_probability, n * sizeof(double)); - double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double)); - int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); - int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); - if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) { + if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) { FATAL("could not acquire memory for alias table"); } - memset((void *)afl->alias_table, 0, n * sizeof(u32)); memset((void *)afl->alias_probability, 0, n * sizeof(double)); + memset((void *)afl->alias_table, 0, n * sizeof(u32)); + memset((void *)Small, 0, n * sizeof(u32)); + memset((void *)Large, 0, n * sizeof(u32)); if (likely(afl->schedule < RARE)) { @@ -166,7 +171,15 @@ void create_alias_table(afl_state_t *afl) { for (i = 0; i < n; i++) { // weight is always 0 for disabled entries - P[i] = (afl->queue_buf[i]->weight * n) / sum; + if (unlikely(afl->queue_buf[i]->disabled)) { + + P[i] = 0; + + } else { + + P[i] = (afl->queue_buf[i]->weight * n) / sum; + + } } @@ -176,60 +189,81 @@ void create_alias_table(afl_state_t *afl) { struct queue_entry *q = afl->queue_buf[i]; - if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); } + if (likely(!q->disabled)) { + + q->perf_score = calculate_score(afl, q); + sum += q->perf_score; - sum += q->perf_score; + } } for (i = 0; i < n; i++) { // perf_score is always 0 for disabled entries - P[i] = (afl->queue_buf[i]->perf_score * n) / sum; + if (unlikely(afl->queue_buf[i]->disabled)) { + + P[i] = 0; + + } else { + + P[i] = (afl->queue_buf[i]->perf_score * n) / sum; + + } } } - int nS = 0, nL = 0, s; - for (s = (s32)n - 1; s >= 0; --s) { + // Done collecting weightings in P, now create the arrays. + + for (s32 j = (s32)(n - 1); j >= 0; j--) { - if (P[s] < 1) { + if (P[j] < 1) { - S[nS++] = s; + Small[nSmall++] = (u32)j; } else { - L[nL++] = s; + Large[nLarge--] = (u32)j; } } - while (nS && nL) { + while (nSmall && nLarge != n - 1) { + + u32 small = Small[--nSmall]; + u32 large = Large[++nLarge]; + + afl->alias_probability[small] = P[small]; + afl->alias_table[small] = large; - a = S[--nS]; - g = L[--nL]; - afl->alias_probability[a] = P[a]; - afl->alias_table[a] = g; - P[g] = P[g] + P[a] - 1; - if (P[g] < 1) { + P[large] = P[large] - (1 - P[small]); - S[nS++] = g; + if (P[large] < 1) { + + Small[nSmall++] = large; } else { - L[nL++] = g; + Large[nLarge--] = large; } } - while (nL) - afl->alias_probability[L[--nL]] = 1; + while (nSmall) { + + afl->alias_probability[Small[--nSmall]] = 1; + + } - while (nS) - afl->alias_probability[S[--nS]] = 1; + while (nLarge != n - 1) { + + afl->alias_probability[Large[++nLarge]] = 1; + + } afl->reinit_table = 0; @@ -264,7 +298,7 @@ void create_alias_table(afl_state_t *afl) { */ /* fprintf(stderr, " entry alias probability perf_score weight - filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u + filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u %0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i], afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight, afl->queue_buf[i]->fname); -- cgit 1.4.1 From abd6eace9d767e4db6019e8eb69080d2352015c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 May 2023 10:32:15 +0200 Subject: improved symqemu custom mutator --- custom_mutators/symqemu/README.md | 2 +- custom_mutators/symqemu/symqemu.c | 239 +++++++++++++++----------------------- include/afl-fuzz.h | 1 + src/afl-fuzz-one.c | 1 + 4 files changed, 98 insertions(+), 145 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/custom_mutators/symqemu/README.md b/custom_mutators/symqemu/README.md index 55ce05c5..b7702c06 100644 --- a/custom_mutators/symqemu/README.md +++ b/custom_mutators/symqemu/README.md @@ -8,4 +8,4 @@ on how to build symqemu-x86_x64 and put it in your `PATH`. just type `make` to build this custom mutator. -```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_SYNC_TIME=1 AFL_DISABLE_TRIM=1 afl-fuzz ...``` +```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_DISABLE_TRIM=1 afl-fuzz ...``` diff --git a/custom_mutators/symqemu/symqemu.c b/custom_mutators/symqemu/symqemu.c index 9030397b..163ae240 100644 --- a/custom_mutators/symqemu/symqemu.c +++ b/custom_mutators/symqemu/symqemu.c @@ -13,6 +13,9 @@ afl_state_t *afl_struct; static u32 debug = 0; +static u32 found_items = 0; + +#define SYMQEMU_LOCATION "symqemu" #define DBG(x...) \ if (debug) { fprintf(stderr, x); } @@ -22,7 +25,6 @@ typedef struct my_mutator { afl_state_t *afl; u8 *mutator_buf; u8 *out_dir; - u8 *queue_dir; u8 *target; u8 *symqemu; u8 *input_file; @@ -67,8 +69,13 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { if (!data->symqemu) FATAL("symqemu binary %s not found", exec_name); DBG("Found %s\n", data->symqemu); - if (getenv("AFL_CUSTOM_MUTATOR_ONLY")) - FATAL("the symqemu module cannot be used with AFL_CUSTOM_MUTATOR_ONLY."); + if (getenv("AFL_CUSTOM_MUTATOR_ONLY")) { + + WARNF( + "the symqemu module is not very effective with " + "AFL_CUSTOM_MUTATOR_ONLY."); + + } if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) { @@ -84,14 +91,11 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { u32 len = strlen(path_tmp) + 32; u8 *symqemu_path = malloc(len); data->out_dir = malloc(len); - data->queue_dir = malloc(len); - snprintf(symqemu_path, len, "%s/../symqemu", path_tmp); - snprintf(data->out_dir, len, "%s/../symqemu/out", path_tmp); - snprintf(data->queue_dir, len, "%s/../symqemu/queue", path_tmp); + snprintf(symqemu_path, len, "%s/%s", path_tmp, SYMQEMU_LOCATION); + snprintf(data->out_dir, len, "%s/out", symqemu_path, path_tmp); - mkdir(symqemu_path, 0755); - mkdir(data->out_dir, 0755); - mkdir(data->queue_dir, 0755); + (void)mkdir(symqemu_path, 0755); + (void)mkdir(data->out_dir, 0755); setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1); @@ -153,8 +157,8 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { data->argv[0] = data->symqemu; data->argv[1] = data->target; - DBG("out_dir=%s, queue_dir=%s, target=%s, input_file=%s, argc=%u\n", - data->out_dir, data->queue_dir, data->target, + DBG("out_dir=%s, target=%s, input_file=%s, argc=%u\n", data->out_dir, + data->target, data->input_file ? (char *)data->input_file : (char *)"", data->argc); @@ -174,29 +178,39 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { } - OKF("Custom mutator symqemu loaded - note that the initial startup of " - "afl-fuzz will be delayed the more starting seeds are present. This is " - "fine, do not worry!"); - return data; } -/* When a new queue entry is added we run this input with the symqemu - instrumented binary */ -uint8_t afl_custom_queue_new_entry(my_mutator_t *data, - const uint8_t *filename_new_queue, - const uint8_t *filename_orig_queue) { +/* No need to receive a splicing item */ +void afl_custom_splice_optout(void *data) { + + (void)(data); + +} + +u32 afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, size_t buf_size) { + + if (likely(!afl_struct->queue_cur->favored || + afl_struct->queue_cur->was_fuzzed)) { + + return 0; + + } int pipefd[2]; struct stat st; - if (data->afl->afl_env.afl_no_ui) - ACTF("Sending to symqemu: %s", filename_new_queue); - u8 *fn = alloc_printf("%s", filename_new_queue); - if (!(stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size)) { - ck_free(fn); - PFATAL("Couldn't find enqueued file: %s", fn); + if (afl_struct->afl_env.afl_no_ui) { + + ACTF("Sending to symqemu: %s", afl_struct->queue_cur->fname); + + } + + if (!(stat(afl_struct->queue_cur->fname, &st) == 0 && S_ISREG(st.st_mode) && + st.st_size)) { + + PFATAL("Couldn't find enqueued file: %s", afl_struct->queue_cur->fname); } @@ -204,7 +218,6 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, if (pipe(pipefd) == -1) { - ck_free(fn); PFATAL( "Couldn't create a pipe for interacting with symqemu child process"); @@ -212,19 +225,12 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, } - int fd = open(fn, O_RDONLY); - if (fd < 0) return 0; - ssize_t r = read(fd, data->mutator_buf, MAX_FILE); - DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r); - ck_free(fn); - close(fd); - if (data->input_file) { - fd = open(data->input_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - ssize_t s = write(fd, data->mutator_buf, r); + int fd = open(data->input_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + ssize_t s = write(fd, buf, buf_size); close(fd); - DBG("wrote %zd/%zd to %s\n", s, r, data->input_file); + DBG("wrote %zd/%zd to %s\n", s, buf_size, data->input_file); } @@ -232,35 +238,20 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, if (pid == -1) return 0; - if (pid) { + if (likely(pid)) { if (!data->input_file || afl_struct->fsrv.use_stdin) { close(pipefd[0]); - if (fd >= 0) { - - if (r <= 0) { - - close(pipefd[1]); - return 0; - - } + if (fcntl(pipefd[1], F_GETPIPE_SZ)) { - if (r > fcntl(pipefd[1], F_GETPIPE_SZ)) - fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE); - ck_write(pipefd[1], data->mutator_buf, r, filename_new_queue); - - } else { - - ck_free(fn); - close(pipefd[1]); - PFATAL( - "Something happened to the enqueued file before sending its " - "contents to symqemu binary"); + fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE); } + ck_write(pipefd[1], buf, buf_size, data->input_file); + close(pipefd[1]); } @@ -268,46 +259,6 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, pid = waitpid(pid, NULL, 0); DBG("symqemu finished executing!\n"); - // At this point we need to transfer files to output dir, since their names - // collide and symqemu will just overwrite them - - struct dirent **nl; - int32_t items = scandir(data->out_dir, &nl, NULL, NULL); - u8 *origin_name = basename(filename_new_queue); - u8 source_name[4096], destination_name[4096]; - int32_t i; - - if (items > 0) { - - for (i = 0; i < (u32)items; ++i) { - - // symqemu output files start with a digit - if (!isdigit(nl[i]->d_name[0])) continue; - - struct stat st; - snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir, - nl[i]->d_name); - DBG("file=%s\n", source_name); - - if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { - - snprintf(destination_name, sizeof(destination_name), "%s/id:%06u,%s", - data->queue_dir, data->counter++, nl[i]->d_name); - DBG("src=%s dst=%s\n", source_name, destination_name); - rename(source_name, destination_name); - - } - - free(nl[i]); - - } - - free(nl); - - } - - DBG("Done!\n"); - } else /* (pid == 0) */ { // child if (afl_struct->fsrv.use_stdin) { @@ -338,33 +289,31 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, } - return 0; - -} - -/* -uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, - size_t buf_size) { + /* back in mother process */ - uint32_t count = 0, i; struct dirent **nl; - int32_t items = scandir(data->out_dir, &nl, NULL, NULL); + s32 i, items = scandir(data->out_dir, &nl, NULL, NULL); + found_items = 0; + char source_name[4096]; if (items > 0) { for (i = 0; i < (u32)items; ++i) { + // symqemu output files start with a digit + if (!isdigit(nl[i]->d_name[0])) continue; + struct stat st; - u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name); - DBG("test=%s\n", fn); - if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { + snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir, + nl[i]->d_name); + DBG("file=%s\n", source_name); + + if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { - DBG("found=%s\n", fn); - count++; + ++found_items; } - ck_free(fn); free(nl[i]); } @@ -373,65 +322,67 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, } - DBG("dir=%s, count=%u\n", data->out_dir, count); - return count; + DBG("Done, found %u items!\n", found_items); -} + return found_items; -*/ +} -// here we actually just read the files generated from symqemu -/* -size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, - u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, +size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, + u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { struct dirent **nl; - int32_t i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL); - ssize_t size = 0; + s32 done = 0, i, items = scandir(data->out_dir, &nl, NULL, NULL); + char source_name[4096]; - if (items <= 0) return 0; + if (items > 0) { - for (i = 0; i < (u32)items; ++i) { + for (i = 0; i < (u32)items; ++i) { - struct stat st; - u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name); + // symqemu output files start with a digit + if (!isdigit(nl[i]->d_name[0])) continue; - if (done == 0) { + struct stat st; + snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir, + nl[i]->d_name); + DBG("file=%s\n", source_name); - if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { + if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { - int fd = open(fn, O_RDONLY); + int fd = open(source_name, O_RDONLY); + if (fd < 0) { goto got_an_issue; } - if (fd >= 0) { + ssize_t r = read(fd, data->mutator_buf, MAX_FILE); + close(fd); - size = read(fd, data->mutator_buf, max_size); - *out_buf = data->mutator_buf; + DBG("fn=%s, fd=%d, size=%ld\n", source_name, fd, r); - close(fd); - done = 1; + if (r < 1) { goto got_an_issue; } - } + done = 1; + --found_items; + unlink(source_name); + + *out_buf = data->mutator_buf; + return (u32)r; } - unlink(fn); + free(nl[i]); } - ck_free(fn); - free(nl[i]); + free(nl); } - free(nl); - DBG("FUZZ size=%lu\n", size); - return (uint32_t)size; +got_an_issue: + *out_buf = NULL; + return 0; } -*/ - /** * Deinitialize everything * diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 8fb7ecb1..beb2de2a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -184,6 +184,7 @@ struct queue_entry { handicap, /* Number of queue cycles behind */ depth, /* Path depth */ exec_cksum, /* Checksum of the execution trace */ + custom, /* Marker for custom mutators */ stats_mutated; /* stats: # of mutations performed */ u8 *trace_mini; /* Trace bytes, if kept */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c6e9a295..5c71fc59 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1912,6 +1912,7 @@ custom_mutator_stage: afl->stage_name = "custom mutator"; afl->stage_short = "custom"; + afl->stage_cur = 0; afl->stage_val_type = STAGE_VAL_NONE; bool has_custom_fuzz = false; u32 shift = unlikely(afl->custom_only) ? 7 : 8; -- cgit 1.4.1 From c28779adc543ffd3c68696867eef0f719ecee9d4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Jun 2023 12:32:51 +0200 Subject: show fuzzing state --- include/afl-fuzz.h | 1 + src/afl-fuzz-one.c | 5 +++-- src/afl-fuzz-stats.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 5 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e1359dc8..c6c45fbd 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1202,6 +1202,7 @@ u8 check_if_text_buf(u8 *buf, u32 len); #ifndef AFL_SHOWMAP void setup_signal_handlers(void); #endif +char *get_fuzzing_state(afl_state_t *afl); /* CmpLog */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 9685885b..af5e57a0 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -402,11 +402,12 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->not_on_tty)) { ACTF( - "Fuzzing test case #%u (%u total, %llu crashes saved, mode=%s, " + "Fuzzing test case #%u (%u total, %llu crashes saved, state: %s, " + "mode=%s, " "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, " "exec_us=%llu, hits=%u, map=%u, ascii=%u)...", afl->current_entry, afl->queued_items, afl->saved_crashes, - afl->fuzz_mode ? "exploit" : "explore", + get_fuzzing_state(afl), afl->fuzz_mode ? "exploit" : "explore", afl->queue_cur->perf_score, afl->queue_cur->weight, afl->queue_cur->favored, afl->queue_cur->was_fuzzed, afl->queue_cur->exec_us, diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4ffb2536..9a60fd47 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -27,6 +27,45 @@ #include "envs.h" #include +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(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 >= 90 && percent_total >= 90)) { + + return fuzzing_state[3]; + + } else if (unlikely(percent_cur >= 75 && percent_total >= 75)) { + + 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) { @@ -1283,9 +1322,10 @@ void show_stats_normal(afl_state_t *afl) { /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP - " strategy:%s %s " bSTG bH20 bH10 bH2 bRB bSTOP cRST RESET_G1, - cPIN, afl->fuzz_mode == 0 ? "explore" : "exploit"); + 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 -- cgit 1.4.1 From 3e1d7941077b1457f702988063d6b9fdd9b80740 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Jun 2023 16:57:20 +0200 Subject: update mutation strategy --- docs/Changelog.md | 4 +++- include/afl-fuzz.h | 59 +++++++++++++++++++++++++------------------------ include/afl-mutations.h | 6 ++--- src/afl-fuzz-one.c | 56 +++++++++++++++++++++++++++------------------- src/afl-fuzz.c | 26 +++++++++++++++++----- 5 files changed, 90 insertions(+), 61 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index e6b90d3d..ad58e99e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,7 +8,8 @@ - new mutation engine: mutations that favor discovery more paths are prefered until no new finds for 10 minutes then switching to mutations that favor triggering crashes. Modes and switch time can be configured - with `-P`. + with `-P`. Also input mode for the target can be defined with `-a` to + be `text` or `binary` (defaults to `generic`) - new custom mutator that has the new afl++ engine (so it can easily incorporated into new custom mutators), and also comes with a standalone command line tool! See custom_mutators/aflpp/standalone/ @@ -23,6 +24,7 @@ Thanks to @amykweon for spotting and fixing! - @toka fixed a bug in laf-intel signed integer comparison splitting, thanks a lot!! + - more LLVM compatability - frida_mode: - support for long form instrumentation on x86_x64 and arm64 diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c6c45fbd..9da5cc03 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -505,36 +505,37 @@ typedef struct afl_state { is_main_node, /* if this is the main node */ is_secondary_node, /* if this is a secondary instance */ pizza_is_served, /* pizza mode */ - text_input, /* target wants text inputs */ - fuzz_mode, /* current mode: coverage/exploration or crash/exploitation */ + input_mode, /* target wants text inputs */ + fuzz_mode, /* coverage/exploration or crash/exploitation mode */ schedule, /* Power schedule (default: EXPLORE)*/ - havoc_max_mult, skip_deterministic, /* Skip deterministic stages? */ - use_splicing, /* Recombine input files? */ - non_instrumented_mode, /* Run in non-instrumented mode? */ - score_changed, /* Scoring for favorites changed? */ - resuming_fuzz, /* Resuming an older fuzzing job? */ - timeout_given, /* Specific timeout given? */ - not_on_tty, /* stdout is not a tty */ - term_too_small, /* terminal dimensions too small */ - no_forkserver, /* Disable forkserver? */ - crash_mode, /* Crash mode! Yeah! */ - in_place_resume, /* Attempt in-place resume? */ - autoresume, /* Resume if afl->out_dir exists? */ - auto_changed, /* Auto-generated tokens changed? */ - no_cpu_meter_red, /* Feng shui on the status screen */ - no_arith, /* Skip most arithmetic ops */ - shuffle_queue, /* Shuffle input queue? */ - bitmap_changed, /* Time to update bitmap? */ - unicorn_mode, /* Running in Unicorn mode? */ - use_wine, /* Use WINE with QEMU mode */ - skip_requested, /* Skip request, via SIGUSR1 */ - run_over10m, /* Run time over 10 minutes? */ - persistent_mode, /* Running in persistent mode? */ - deferred_mode, /* Deferred forkserver mode? */ - fixed_seed, /* do not reseed */ - fast_cal, /* Try to calibrate faster? */ - disable_trim, /* Never trim in fuzz_one */ - shmem_testcase_mode, /* If sharedmem testcases are used */ + havoc_max_mult, /* havoc multiplier */ + skip_deterministic, /* Skip deterministic stages? */ + use_splicing, /* Recombine input files? */ + non_instrumented_mode, /* Run in non-instrumented mode? */ + score_changed, /* Scoring for favorites changed? */ + resuming_fuzz, /* Resuming an older fuzzing job? */ + timeout_given, /* Specific timeout given? */ + not_on_tty, /* stdout is not a tty */ + term_too_small, /* terminal dimensions too small */ + no_forkserver, /* Disable forkserver? */ + crash_mode, /* Crash mode! Yeah! */ + in_place_resume, /* Attempt in-place resume? */ + autoresume, /* Resume if afl->out_dir exists? */ + auto_changed, /* Auto-generated tokens changed? */ + no_cpu_meter_red, /* Feng shui on the status screen */ + no_arith, /* Skip most arithmetic ops */ + shuffle_queue, /* Shuffle input queue? */ + bitmap_changed, /* Time to update bitmap? */ + unicorn_mode, /* Running in Unicorn mode? */ + use_wine, /* Use WINE with QEMU mode */ + skip_requested, /* Skip request, via SIGUSR1 */ + run_over10m, /* Run time over 10 minutes? */ + persistent_mode, /* Running in persistent mode? */ + deferred_mode, /* Deferred forkserver mode? */ + fixed_seed, /* do not reseed */ + fast_cal, /* Try to calibrate faster? */ + disable_trim, /* Never trim in fuzz_one */ + shmem_testcase_mode, /* If sharedmem testcases are used */ expand_havoc, /* perform expensive havoc after no find */ cycle_schedules, /* cycle power schedules? */ old_seed_selection, /* use vanilla afl seed selection */ diff --git a/include/afl-mutations.h b/include/afl-mutations.h index cc4840c8..0a9bbbf4 100644 --- a/include/afl-mutations.h +++ b/include/afl-mutations.h @@ -14,14 +14,14 @@ Parameters: afl_state_t *afl - the *afl state pointer u8 *buf - the input buffer to mutate which will be mutated into. - NOTE: must be able to contain a size of at least max_len (see below)! + NOTE: must be able to contain a size of at least max_len!! (see below) u32 len - the length of the input u32 steps - how many mutations to perform on the input bool is_text - is the target expecting text inputs bool is_exploration - mutate for exploration mode (instead of exploitation) splice_buf - a buffer from another corpus item to splice with. - If NULL then no splicing - splice_len - the length of the splice buffer. If 0 then no splicing + If NULL then no splicing is done (obviously). + splice_len - the length of the splice buffer. If 0 then no splicing. u32 max_len - the maximum size the mutated buffer may grow to */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c6e49653..0d3c29f2 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2085,47 +2085,57 @@ havoc_stage: u32 *mutation_array; u32 stack_max, rand_max; // stack_max_pow = afl->havoc_stack_pow2; - /* + switch (afl->input_mode) { - if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { + case 1: { // TEXT - mutation_array = full_splice_array; - rand_max = MUT_SPLICE_ARRAY_SIZE; + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&binary_array; + rand_max = MUT_BIN_ARRAY_SIZE; - } else { + } else { // exploitation mode - mutation_array = normal_splice_array; - rand_max = MUT_NORMAL_ARRAY_SIZE; + mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + rand_max = MUT_STRATEGY_ARRAY_SIZE; - } + } - */ + break; - if (unlikely(afl->text_input)) { // is text? + } - if (likely(afl->fuzz_mode == 0)) { // is exploration? + case 2: { // BINARY - mutation_array = (unsigned int *)&text_array; - rand_max = MUT_TXT_ARRAY_SIZE; + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; - } else { // is exploitation! + } else { // exploitation mode - mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; + + } + + break; } - } else { // is binary! + default: { // DEFAULT/GENERIC - if (likely(afl->fuzz_mode == 0)) { // is exploration? + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&binary_array; + rand_max = MUT_BIN_ARRAY_SIZE; - mutation_array = (unsigned int *)&binary_array; - rand_max = MUT_BIN_ARRAY_SIZE; + } else { // exploitation mode - } else { // is exploitation! + // this will need to be changed I guess + mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + rand_max = MUT_STRATEGY_ARRAY_SIZE; + + } - mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + break; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 79b05da7..ab7d6534 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -125,7 +125,8 @@ static void usage(u8 *argv0, int more_help) { "Required parameters:\n" " -i dir - input directory with test cases (or '-' to resume, " - "also see AFL_AUTORESUME)\n" + "also see \n" + " AFL_AUTORESUME)\n" " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" @@ -164,8 +165,8 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target expects ascii text input (prefer text " - "mutators)\n" + " -a - target input format, \"text\" or \"binary\" (default: " + "generic)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" @@ -506,13 +507,28 @@ int main(int argc, char **argv_orig, char **envp) { // still available: HjJkKqruvwz while ((opt = getopt(argc, argv, - "+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" + "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" "T:UV:WXx:YZ")) > 0) { switch (opt) { case 'a': - afl->text_input = 1; + + if (!stricmp(optarg, "text") || !stricmp(optarg, "ascii") || + !stricmp(optarg, "txt") || !stricmp(optarg, "asc")) { + + afl->input_mode = 1; + + } else if (!stricmp(optarg, "bin") || !stricmp(optarg, "binary")) { + + afl->input_mode = 2; + + } else { + + FATAL("-a input mode needs to be \"text\" or \"binary\"."); + + } + break; case 'P': -- cgit 1.4.1 From 2a34e845072204b29200bf0e480d1d4f2201b332 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Jul 2023 16:08:22 +0200 Subject: nits --- include/afl-fuzz.h | 2 +- include/android-ashmem.h | 4 +++- src/afl-ld-lto.c | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 9da5cc03..27668da0 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -31,7 +31,7 @@ #define MESSAGES_TO_STDOUT #ifndef _GNU_SOURCE - #define _GNU_SOURCE 1 + #define _GNU_SOURCE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 1bfd3220..065c213b 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -2,7 +2,9 @@ #ifndef _ANDROID_ASHMEM_H #define _ANDROID_ASHMEM_H - #define _GNU_SOURCE + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #endif #include #include #include diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index b306c8d5..b1e6c848 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -23,7 +23,9 @@ */ #define AFL_MAIN -#define _GNU_SOURCE +#ifndef _GNU_SOURCE + #define _GNU_SOURCE +#endif #include "config.h" #include "types.h" -- cgit 1.4.1 From 5f813bbb86e1c9e2480669c44501e9780043728c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Jul 2023 18:02:30 +0200 Subject: improve cmplog level 3 --- docs/Changelog.md | 1 + include/afl-fuzz.h | 3 +- include/config.h | 8 +-- src/afl-fuzz-redqueen.c | 171 +++++++++++++++++++++++++----------------------- src/afl-fuzz.c | 7 +- 5 files changed, 100 insertions(+), 90 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index d61ce8ec..75167172 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,6 +15,7 @@ command line tool! See custom_mutators/aflpp/standalone/ - display the state of the fuzzing run in the UI :-) - fix timeout setting if '+' is used or a session is restarted + - -c X option to enable base64 transformation solving - afl-cmin/afl-cmin.bash: - fixed a bug inherited from vanilla AFL where a coverage of map[123] = 11 would be the same as map[1123] = 1 diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 27668da0..e114b0fc 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -674,7 +674,8 @@ typedef struct afl_state { u32 cmplog_max_filesize; u32 cmplog_lvl; u32 colorize_success; - u8 cmplog_enable_arith, cmplog_enable_transform, cmplog_random_colorization; + u8 cmplog_enable_arith, cmplog_enable_transform, + cmplog_enable_xtreme_transform, cmplog_random_colorization; struct afl_pass_stat *pass_stats; struct cmp_map *orig_cmp_map; diff --git a/include/config.h b/include/config.h index 7c29a674..df545583 100644 --- a/include/config.h +++ b/include/config.h @@ -60,10 +60,6 @@ * */ -/* if TRANSFORM is enabled with '-l T', this additionally enables base64 - encoding/decoding */ -// #define CMPLOG_SOLVE_TRANSFORM_BASE64 - /* If a redqueen pass finds more than one solution, try to combine them? */ #define CMPLOG_COMBINE @@ -71,10 +67,10 @@ #define CMPLOG_CORPUS_PERCENT 5U /* Number of potential positions from which we decide if cmplog becomes - useless, default 8096 */ + useless, default 12288 */ #define CMPLOG_POSITIONS_MAX (12 * 1024) -/* Maximum allowed fails per CMP value. Default: 128 */ +/* Maximum allowed fails per CMP value. Default: 96 */ #define CMPLOG_FAIL_MAX 96 /* -------------------------------------*/ diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 73e188e7..5a1f512d 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -571,7 +571,6 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -// #ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -656,7 +655,6 @@ static int is_hex(const char *str) { } -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // tests 4 bytes at location static int is_base64(const char *str) { @@ -769,10 +767,6 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } -#endif - -// #endif - static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -797,42 +791,54 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - // fprintf(stderr, - // "Encode: %llx->%llx into %llx(<-%llx) at idx=%u " - // "taint_len=%u shape=%u attr=%u\n", - // o_pattern, pattern, repl, changed_val, idx, taint_len, - // hshape, attr); + /* + fprintf(stderr, + "Encode: %llx->%llx into %llx(<-%llx) at idx=%u " + "taint_len=%u shape=%u attr=%u\n", + o_pattern, pattern, repl, changed_val, idx, taint_len, + hshape, attr); + */ - // #ifdef CMPLOG_SOLVE_TRANSFORM // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 *endptr; u8 use_num = 0, use_unum = 0; - unsigned long long unum; - long long num; + unsigned long long unum = 0; + long long num = 0; + + // if (afl->queue_cur->is_ascii) { + + // we first check if our input are ascii numbers that are transformed to + // an integer and used for comparison: - if (afl->queue_cur->is_ascii) { + endptr = buf_8; + if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) { - endptr = buf_8; - if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) { + if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) { - if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) - use_unum = 1; + use_unum = 1; - } else + } + + } else { - use_num = 1; + use_num = 1; } + //} + #ifdef _DEBUG if (idx == 0) - fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n", - afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern); + fprintf(stderr, + "ASCII is=%u use_num=%u>%lld use_unum=%u>%llu idx=%u " + "pattern=0x%llx\n", + afl->queue_cur->is_ascii, use_num, num, use_unum, unum, idx, + pattern); #endif - // num is likely not pattern as atoi("AAA") will be zero... + // atoi("AAA") == 0 so !num means we have to investigate if (use_num && ((u64)num == pattern || !num)) { u8 tmp_buf[32]; @@ -961,10 +967,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..." s64 diff = pattern - b_val; s64 o_diff = o_pattern - o_b_val; - /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, - hshape, o_pattern, o_b_val, o_diff); - fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, - b_val, diff); */ + /* + fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, + hshape, o_pattern, o_b_val, o_diff); + fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, + b_val, diff); + */ if (diff == o_diff && diff) { // this could be an arithmetic transformation @@ -1275,7 +1283,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) - // #ifdef CMPLOG_SOLVE_ARITHMETIC if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { return 0; @@ -2009,8 +2016,12 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, its_len = MIN(its_len, taint_len); u32 saved_its_len = its_len; + if (its_len <= 1) { return 0; } + if (lvl & LVL3) { + if (memcmp(changed_val, repl, its_len) != 0) { return 0; } + u32 max_to = MIN(4U, idx); if (!(lvl & LVL1) && max_to) { from = 1; } to = max_to; @@ -2089,9 +2100,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (afl->cmplog_enable_transform && (lvl & LVL3)) { u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0; -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 u32 tob64 = 0, fromb64 = 0; -#endif u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0; u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0; u8 xor_val[32], arith_val[32], tmp[48]; @@ -2144,7 +2153,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if (i < 16 && is_hex(repl + (i << 1))) { + if (afl->cmplog_enable_xtreme_transform && i < 16 && + is_hex(repl + (i << 1))) { ++tohex; @@ -2163,7 +2173,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if ((i % 2)) { + if (afl->cmplog_enable_xtreme_transform && (i % 2)) { if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) { @@ -2187,20 +2197,21 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - if (i % 3 == 2 && i < 24) { + if (afl->cmplog_enable_xtreme_transform) { - if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; + if (i % 3 == 2 && i < 24) { - } + if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; + + } - if (i % 4 == 3 && i < 24) { + if (i % 4 == 3 && i < 24) { - if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4; + if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4; - } + } -#endif + } if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) { @@ -2229,45 +2240,50 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } #ifdef _DEBUG + fprintf(stderr, "RTN %s %s %s %s\n", buf, pattern, orig_buf, o_pattern); fprintf(stderr, - "RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " + "RTN idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " "from_0=%u from_slash=%u from_x=%u\n", - idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0, - to_slash, to_x, from_0, from_slash, from_x); - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64, - fromb64); - #endif + idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, + to_0, to_slash, to_x, from_0, from_slash, from_x); + if (afl->cmplog_enable_xtreme_transform) { + + fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", idx, i, + tob64, fromb64); + + } + #endif -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - // input is base64 and converted to binary? convert repl to base64! - if ((i % 4) == 3 && i < 24 && fromb64 > i) { + if (afl->cmplog_enable_xtreme_transform) { - to_base64(repl, tmp, i + 1); - memcpy(buf + idx, tmp, i + 1); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64, - // *status); + // input is base64 and converted to binary? convert repl to base64! + if ((i % 4) == 3 && i < 24 && fromb64 > i) { - } + to_base64(repl, tmp, i + 1); + memcpy(buf + idx, tmp, i + 1); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64, + // *status); + + } - // input is converted to base64? decode repl with base64! - if ((i % 3) == 2 && i < 24 && tob64 > i) { + // input is converted to base64? decode repl with base64! + if ((i % 3) == 2 && i < 24 && tob64 > i) { - u32 olen = from_base64(repl, tmp, i + 1); - memcpy(buf + idx, tmp, olen); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64, - // idx, *status); + u32 olen = from_base64(repl, tmp, i + 1); + memcpy(buf + idx, tmp, olen); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64, + // idx, *status); - } + } -#endif + } // input is converted to hex? convert repl to binary! - if (i < 16 && tohex > i) { + if (afl->cmplog_enable_xtreme_transform && i < 16 && tohex > i) { u32 off; if (to_slash + to_x + to_0 == 2) { @@ -2292,8 +2308,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } // input is hex and converted to binary? convert repl to hex! - if (i && (i % 2) && i < 16 && fromhex && - fromhex + from_slash + from_x + from_0 > i) { + if (afl->cmplog_enable_xtreme_transform && i && (i % 2) && i < 16 && + fromhex && fromhex + from_slash + from_x + from_0 > i) { u8 off = 0; if (from_slash && from_x) { @@ -2401,11 +2417,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if ((i >= 7 && (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i > - (fromhex + from_0 + from_x + from_slash + 1) -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - && i > tob64 + 3 && i > fromb64 + 4 -#endif - )) || + (fromhex + from_0 + from_x + from_slash + 1) && + (afl->cmplog_enable_xtreme_transform && i > tob64 + 3 && + i > fromb64 + 4))) || repl[i] != changed_val[i] || *status == 1) { break; @@ -2418,8 +2432,6 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - // #endif - return 0; } @@ -2818,12 +2830,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } - } else if ((lvl & LVL1) - - // #ifdef CMPLOG_SOLVE_TRANSFORM - || ((lvl & LVL3) && afl->cmplog_enable_transform) - // #endif - ) { + } else if ((lvl & LVL1) || ((lvl & LVL3) && afl->cmplog_enable_transform)) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d8a88f00..21a8915c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -185,7 +185,8 @@ static void usage(u8 *argv0, int more_help) { " 1=small files, 2=larger files (default), 3=all " "files,\n" " A=arithmetic solving, T=transformational solving,\n" - " R=random colorization bytes.\n\n" + " X=extreme transform solving, R=random colorization " + "bytes.\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " "random\n" @@ -1120,6 +1121,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'T': afl->cmplog_enable_transform = 1; break; + case 'x': + case 'X': + afl->cmplog_enable_xtreme_transform = 1; + break; case 'r': case 'R': afl->cmplog_random_colorization = 1; -- cgit 1.4.1 From 1429c9724efb62e5ac90ec27d93a64c28632ba5d Mon Sep 17 00:00:00 2001 From: Junwha Date: Wed, 2 Aug 2023 02:59:07 +0900 Subject: Add option for treating crashing input as new crash Signed-off-by: Junwha Hong --- include/afl-fuzz.h | 3 +- include/envs.h | 1 + src/afl-fuzz-init.c | 99 +++++++++++++++++++++++++++++++++++++++++++---------- src/afl-fuzz.c | 3 +- 4 files changed, 86 insertions(+), 20 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e114b0fc..7bedc98f 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -539,7 +539,8 @@ typedef struct afl_state { expand_havoc, /* perform expensive havoc after no find */ cycle_schedules, /* cycle power schedules? */ old_seed_selection, /* use vanilla afl seed selection */ - reinit_table; /* reinit the queue weight table */ + reinit_table, /* reinit the queue weight table */ + crashing_seeds_as_new_crash; /* treat crashing seeds as normal corpus */ u8 *virgin_bits, /* Regions yet untouched by fuzzing */ *virgin_tmout, /* Bits we haven't seen in tmouts */ diff --git a/include/envs.h b/include/envs.h index edfd06e4..e396acd2 100644 --- a/include/envs.h +++ b/include/envs.h @@ -35,6 +35,7 @@ static char *afl_environment_variables[] = { "AFL_COMPCOV_BINNAME", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE", + "AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 24fd7077..6b7f3036 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1056,6 +1056,13 @@ void perform_dry_run(afl_state_t *afl) { "skipping", fn, (int)(s8)afl->fsrv.crash_exitcode); + } else if (afl->crashing_seeds_as_new_crash) { + + WARNF( + "Test case '%s' results in a crash," + "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " + "saving as a crash", fn); + } else { WARNF("Test case '%s' results in a crash, skipping", fn); @@ -1078,38 +1085,94 @@ void perform_dry_run(afl_state_t *afl) { } - q->disabled = 1; - q->perf_score = 0; + /* Crashing corpus will regrad as normal, and categorized as new crash at fuzzing */ + if (afl->crashing_seeds_as_new_crash) { + + ++afl->total_crashes; - u32 i = 0; - while (unlikely(i < afl->queued_items && afl->queue_buf[i] && - afl->queue_buf[i]->disabled)) { + if (likely(!afl->non_instrumented_mode)) { - ++i; + classify_counts(&afl->fsrv); + + simplify_trace(afl, afl->fsrv.trace_bits); - } + if (!has_new_bits(afl, afl->virgin_crash)) { break; } + + } + + + if (unlikely(!afl->saved_crashes) && + (afl->afl_env.afl_no_crash_readme != 1)) { + + write_crash_readme(afl); + + } + + u8 crash_fn[PATH_MAX]; + u8 *use_name = strstr(q->fname, ",orig:"); + + afl->stage_name = "dry_run"; + afl->stage_short = "dry_run"; + + #ifndef SIMPLE_FILES + + snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), use_name); + + #else + + snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal); + + #endif - if (i < afl->queued_items && afl->queue_buf[i]) { + ++afl->saved_crashes; - afl->queue = afl->queue_buf[i]; + fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); } + ck_write(fd, use_mem, read_len, crash_fn); + close(fd); + + afl->last_crash_time = get_cur_time(); + afl->last_crash_execs = afl->fsrv.total_execs; } else { - afl->queue = afl->queue_buf[0]; + q->disabled = 1; + q->perf_score = 0; - } + u32 i = 0; + while (unlikely(i < afl->queued_items && afl->queue_buf[i] && + afl->queue_buf[i]->disabled)) { - afl->max_depth = 0; - for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) { + ++i; - if (!afl->queue_buf[i]->disabled && - afl->queue_buf[i]->depth > afl->max_depth) - afl->max_depth = afl->queue_buf[i]->depth; + } - } + if (i < afl->queued_items && afl->queue_buf[i]) { - break; + afl->queue = afl->queue_buf[i]; + + } else { + afl->queue = afl->queue_buf[0]; + + } + + afl->max_depth = 0; + for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) { + + if (!afl->queue_buf[i]->disabled && + afl->queue_buf[i]->depth > afl->max_depth) + afl->max_depth = afl->queue_buf[i]->depth; + + } + + } + + break; + case FSRV_RUN_ERROR: FATAL("Unable to execute target application ('%s')", afl->argv[0]); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bacbafc4..5cbebb0e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1573,7 +1573,8 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - + if (get_afl_env("AFL_CRASHING_SEEDS_AS_NEW_CRASH")) { afl->crashing_seeds_as_new_crash = 1; } + if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; -- cgit 1.4.1 From fcdfe9e990d84ab477cd3c571cbf540e8bc8e15a Mon Sep 17 00:00:00 2001 From: Junwha Date: Fri, 4 Aug 2023 18:36:58 +0900 Subject: Define AFL_CRASHING_SEEDS_AS_NEW_CRASH as env variable - and fix typo Signed-off-by: Junwha --- include/afl-fuzz.h | 6 +++--- src/afl-fuzz-init.c | 30 ++++++++++++++++-------------- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 1 - 4 files changed, 26 insertions(+), 18 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7bedc98f..18352acb 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1,3 +1,4 @@ + /* american fuzzy lop++ - fuzzer header ------------------------------------ @@ -408,7 +409,7 @@ typedef struct afl_env_vars { *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries, *afl_child_kill_signal, *afl_fsrv_kill_signal, - *afl_target_env, *afl_persistent_record, *afl_exit_on_time; + *afl_target_env, *afl_persistent_record, *afl_exit_on_time, *afl_crashing_seeds_as_new_crash; s32 afl_pizza_mode; @@ -539,8 +540,7 @@ typedef struct afl_state { expand_havoc, /* perform expensive havoc after no find */ cycle_schedules, /* cycle power schedules? */ old_seed_selection, /* use vanilla afl seed selection */ - reinit_table, /* reinit the queue weight table */ - crashing_seeds_as_new_crash; /* treat crashing seeds as normal corpus */ + reinit_table; /* reinit the queue weight table */ u8 *virgin_bits, /* Regions yet untouched by fuzzing */ *virgin_tmout, /* Bits we haven't seen in tmouts */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 6b7f3036..d994d749 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1056,17 +1056,19 @@ void perform_dry_run(afl_state_t *afl) { "skipping", fn, (int)(s8)afl->fsrv.crash_exitcode); - } else if (afl->crashing_seeds_as_new_crash) { - - WARNF( - "Test case '%s' results in a crash," - "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " - "saving as a crash", fn); - } else { + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { + + WARNF( + "Test case '%s' results in a crash, " + "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " + "saving as a new crash", fn); + + } else { - WARNF("Test case '%s' results in a crash, skipping", fn); - + WARNF("Test case '%s' results in a crash, skipping", fn); + + } } if (afl->afl_env.afl_exit_on_seed_issues) { @@ -1085,8 +1087,8 @@ void perform_dry_run(afl_state_t *afl) { } - /* Crashing corpus will regrad as normal, and categorized as new crash at fuzzing */ - if (afl->crashing_seeds_as_new_crash) { + /* Crashing seeds will be regarded as new crashes on startup */ + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { ++afl->total_crashes; @@ -1139,9 +1141,6 @@ void perform_dry_run(afl_state_t *afl) { } else { - q->disabled = 1; - q->perf_score = 0; - u32 i = 0; while (unlikely(i < afl->queued_items && afl->queue_buf[i] && afl->queue_buf[i]->disabled)) { @@ -1171,6 +1170,9 @@ void perform_dry_run(afl_state_t *afl) { } + q->disabled = 1; + q->perf_score = 0; + break; case FSRV_RUN_ERROR: diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 99f69314..5a6b95cf 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -200,6 +200,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_exit_on_time = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_CRASHING_SEEDS_AS_NEW_CRASH", + + afl_environment_variable_len)) { + + afl->afl_env.afl_crashing_seeds_as_new_crash = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + } else if (!strncmp(env, "AFL_NO_AFFINITY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5cbebb0e..51ca4ee6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1573,7 +1573,6 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - if (get_afl_env("AFL_CRASHING_SEEDS_AS_NEW_CRASH")) { afl->crashing_seeds_as_new_crash = 1; } if (afl->afl_env.afl_autoresume) { -- cgit 1.4.1 From 55d696fbae435e0e69adf75cb2df1361186fb999 Mon Sep 17 00:00:00 2001 From: marc Date: Wed, 9 Aug 2023 17:14:13 +0200 Subject: code format --- include/afl-fuzz.h | 4 ++-- src/afl-fuzz-init.c | 42 ++++++++++++++++++++++++------------------ src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz.c | 2 +- 4 files changed, 28 insertions(+), 22 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 18352acb..ef84a18c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -402,14 +402,14 @@ typedef struct afl_env_vars { afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, - afl_post_process_keep_original; + afl_post_process_keep_original, afl_crashing_seeds_as_new_crash; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries, *afl_child_kill_signal, *afl_fsrv_kill_signal, - *afl_target_env, *afl_persistent_record, *afl_exit_on_time, *afl_crashing_seeds_as_new_crash; + *afl_target_env, *afl_persistent_record, *afl_exit_on_time; s32 afl_pizza_mode; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d994d749..5a530821 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1057,18 +1057,21 @@ void perform_dry_run(afl_state_t *afl) { fn, (int)(s8)afl->fsrv.crash_exitcode); } else { + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { - + WARNF( "Test case '%s' results in a crash, " "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " - "saving as a new crash", fn); - + "saving as a new crash", + fn); + } else { WARNF("Test case '%s' results in a crash, skipping", fn); - + } + } if (afl->afl_env.afl_exit_on_seed_issues) { @@ -1089,20 +1092,19 @@ void perform_dry_run(afl_state_t *afl) { /* Crashing seeds will be regarded as new crashes on startup */ if (afl->afl_env.afl_crashing_seeds_as_new_crash) { - + ++afl->total_crashes; if (likely(!afl->non_instrumented_mode)) { classify_counts(&afl->fsrv); - + simplify_trace(afl, afl->fsrv.trace_bits); if (!has_new_bits(afl, afl->virgin_crash)) { break; } } - if (unlikely(!afl->saved_crashes) && (afl->afl_env.afl_no_crash_readme != 1)) { @@ -1116,18 +1118,22 @@ void perform_dry_run(afl_state_t *afl) { afl->stage_name = "dry_run"; afl->stage_short = "dry_run"; - #ifndef SIMPLE_FILES +#ifndef SIMPLE_FILES - snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), use_name); + snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, + NAME_MAX - strlen("id:000000,sig:00,") - + strlen(use_name)), + use_name); - #else +#else - snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal); + snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", + afl->out_dir, afl->saved_crashes, + afl->fsrv.last_kill_signal); - #endif +#endif ++afl->saved_crashes; @@ -1169,12 +1175,12 @@ void perform_dry_run(afl_state_t *afl) { } } - + q->disabled = 1; q->perf_score = 0; - break; - + break; + case FSRV_RUN_ERROR: FATAL("Unable to execute target application ('%s')", afl->argv[0]); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 509f66a3..db4991db 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2525,7 +2525,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, */ #ifdef _DEBUG - u32 j; + u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, hshape, h->attribute); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 733c7429..cdb3f996 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1592,7 +1592,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - + if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; -- cgit 1.4.1 From 8823f22a9c87123c1bfcc5bff10044de4c7a4a1f Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 11 Aug 2023 11:22:18 +0200 Subject: add AFL_FINAL_SYNC --- docs/Changelog.md | 7 +++---- docs/env_variables.md | 13 +++++++++---- include/afl-fuzz.h | 3 ++- include/envs.h | 1 + src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 9 +++++++++ 6 files changed, 31 insertions(+), 9 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index 94b4c502..8f2b2545 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,7 +4,9 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.09a (dev) - - something cool :-) + - afl-fuzz: + - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) + before terminating. ### Version ++4.08c (release) @@ -22,7 +24,6 @@ - -l X option to enable base64 transformation solving - allow to disable CMPLOG with '-c -' (e.g. afl.rs enforces '-c 0' on every instance which is counterproductive). - - afl-cmin/afl-cmin.bash: - fixed a bug inherited from vanilla AFL where a coverage of map[123] = 11 would be the same as map[1123] = 1 @@ -40,7 +41,6 @@ - qemu_mode: - added qemu_mode/utils/qemu_get_symbol_addr.sh - ### Version ++4.07c (release) - afl-fuzz: - reverse reading the seeds only on restarts (increases performance) @@ -69,7 +69,6 @@ - TritonDSE in custom_mutators/aflpp_tritondse - SymQEMU in custom_mutators/symqemu - ### Version ++4.06c (release) - afl-fuzz: - ensure temporary file descriptor is closed when not used diff --git a/docs/env_variables.md b/docs/env_variables.md index affc9e3c..2ce274d3 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -412,10 +412,15 @@ checks or alter some of the more exotic semantics of the tool: set `AFL_IGNORE_PROBLEMS`. If you additionally want to also ignore coverage from late loaded libraries, you can set `AFL_IGNORE_PROBLEMS_COVERAGE`. - - When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the - fuzzer to import test cases from other instances before doing anything else. - This makes the "own finds" counter in the UI more accurate. Beyond counter - aesthetics, not much else should change. + - When running with multiple afl-fuzz or with `-F`, setting `AFL_IMPORT_FIRST` + causes the fuzzer to import test cases from other instances before doing + anything else. This makes the "own finds" counter in the UI more accurate. + + - When running with multiple afl-fuzz or with `-F`, setting `AFL_FINAL_SYNC` + will cause the fuzzer to perform a final import of test cases when + terminating. This is beneficial for `-M` main fuzzers to ensure it has all + unique test cases and hence you only need to `afl-cmin` this single + queue. - Setting `AFL_INPUT_LEN_MIN` and `AFL_INPUT_LEN_MAX` are an alternative to the afl-fuzz -g/-G command line option to control the minimum/maximum diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index ef84a18c..1f89bbd8 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -402,7 +402,8 @@ typedef struct afl_env_vars { afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, - afl_post_process_keep_original, afl_crashing_seeds_as_new_crash; + afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, + afl_final_sync; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 0007d5a8..3f5a9e1c 100644 --- a/include/envs.h +++ b/include/envs.h @@ -59,6 +59,7 @@ static char *afl_environment_variables[] = { "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", + "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DRIVER_NO_HOOK", diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 5a6b95cf..97e00415 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -269,6 +269,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_import_first = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_FINAL_SYNC", + + afl_environment_variable_len)) { + + afl->afl_env.afl_final_sync = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index cdb3f996..c2ec4a1d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2899,6 +2899,15 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif + if (afl->afl_env.afl_final_sync) { + + SAYF(cYEL "[!] " cRST "\nPerforming final sync, this make take some time ...\n"); + sync_fuzzers(afl); + write_bitmap(afl); + SAYF(cYEL "[!] " cRST "Done!\n\n"); + + } + if (afl->is_main_node) { u8 path[PATH_MAX]; -- cgit 1.4.1 From 4d8d8633ff39cda2f1d48b66c45e5ae6cd2af477 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 13 Aug 2023 11:44:37 +0200 Subject: update faq --- docs/FAQ.md | 40 ++++++++++++++++++++++++++++++++++++++-- include/afl-fuzz.h | 9 ++++----- 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/FAQ.md b/docs/FAQ.md index 9275eb94..242a379b 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -29,8 +29,8 @@ If you find an interesting or important question missing, submit it via which then implemented their own research and features, making it now by far the most flexible and feature rich guided fuzzer available as open source. And in independent fuzzing benchmarks it is one of the best fuzzers available, - e.g., [Fuzzbench - Report](https://www.fuzzbench.com/reports/2020-08-03/index.html). + e.g., + [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html).

@@ -103,6 +103,42 @@ If you find an interesting or important question missing, submit it via to itself, this too would be an edge.

+
+ Should you ever stop afl-fuzz, minimize the corpus and restart?

+ + To stop afl-fuzz, minimize it's corpus and restart you would usually do: + + ``` + Control-C # to terminate afl-fuzz + $ afl-cmin -T nproc -i out/default/queue -o minimized_queue -- ./target + $ AFL_FAST_CAL=1 AFL_CMPLOG_ONLY_NEW=1 afl-fuzz -i minimized_queue -o out2 [other options] -- ./target + ``` + + If this improves fuzzing or not is debated and no consensus has been reached + or in-depth analysis been performed. + + On the pro side: + * The queue/corpus is reduced (up to 20%) by removing intermediate paths + that are maybe not needed anymore. + + On the con side: + * Fuzzing time is lost for the time the fuzzing is stopped, minimized and + restarted. + + The the big question: + * Does a minimized queue/corpus improve finding new coverage or does it + hinder it? + + The AFL++ team's own limited analysis seem to to show that keeping + intermediate paths help to find more coverage, at least for afl-fuzz. + + For honggfuzz in comparison it is a good idea to restart it from time to + time if you have other fuzzers (e.g: AFL++) running in parallel to sync + the finds of other fuzzers to honggfuzz as it has no syncing feature like + AFL++ or libfuzzer. + +

+ ## Targets
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1f89bbd8..3dfd2b2c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -158,6 +158,7 @@ struct queue_entry { u8 colorized, /* Do not run redqueen stage again */ cal_failed; /* Calibration failed? */ + bool trim_done, /* Trimmed? */ was_fuzzed, /* historical, but needed for MOpt */ passed_det, /* Deterministic stages passed? */ @@ -169,17 +170,15 @@ struct queue_entry { disabled; /* Is disabled from fuzz selection */ u32 bitmap_size, /* Number of bits set in bitmap */ - fuzz_level, /* Number of fuzzing iterations */ - n_fuzz_entry /* offset in n_fuzz */ #ifdef INTROSPECTION - , stats_selected, /* stats: how often selected */ stats_skipped, /* stats: how often skipped */ stats_finds, /* stats: # of saved finds */ stats_crashes, /* stats: # of saved crashes */ - stats_tmouts /* stats: # of saved timeouts */ + stats_tmouts, /* stats: # of saved timeouts */ #endif - ; + fuzz_level, /* Number of fuzzing iterations */ + n_fuzz_entry; /* offset in n_fuzz */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ -- cgit 1.4.1 From 549e5dd9269238ac43ff482d439f7f671946185c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Aug 2023 18:02:33 +0200 Subject: AFL_IGNORE_SEED_PROBLEMS --- docs/Changelog.md | 2 ++ docs/env_variables.md | 3 +++ include/afl-fuzz.h | 7 +++---- include/envs.h | 1 + src/afl-fuzz-init.c | 53 +++++++++++++++++++++++++++++++++++++++------------ src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 2 ++ 7 files changed, 59 insertions(+), 16 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index 961b2940..87c01f21 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,8 @@ - afl-fuzz: - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) before terminating. + - added AFL_IGNORE_SEED_PROBLEMS to skip over seeds that time out instead + of exiting with an error message - afl-whatsup: - detect instanced that are starting up and show them as such as not dead - now also shows coverage reached diff --git a/docs/env_variables.md b/docs/env_variables.md index 2ce274d3..3bb4e844 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -327,6 +327,9 @@ checks or alter some of the more exotic semantics of the tool: (`-i in`). This is an important feature to set when resuming a fuzzing session. + - `AFL_IGNORE_SEED_PROBLEMS` will skip over crashes and timeouts in the seeds + instead of exiting. + - Setting `AFL_CRASH_EXITCODE` sets the exit code AFL++ treats as crash. For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting in a `-1` return code (i.e. `exit(-1)` got called), will be treated as if a crash had diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 3dfd2b2c..d02e852e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1,4 +1,3 @@ - /* american fuzzy lop++ - fuzzer header ------------------------------------ @@ -175,10 +174,10 @@ struct queue_entry { stats_skipped, /* stats: how often skipped */ stats_finds, /* stats: # of saved finds */ stats_crashes, /* stats: # of saved crashes */ - stats_tmouts, /* stats: # of saved timeouts */ + stats_tmouts, /* stats: # of saved timeouts */ #endif fuzz_level, /* Number of fuzzing iterations */ - n_fuzz_entry; /* offset in n_fuzz */ + n_fuzz_entry; /* offset in n_fuzz */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ @@ -402,7 +401,7 @@ typedef struct afl_env_vars { afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, - afl_final_sync; + afl_final_sync, afl_ignore_seed_problems; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 3f5a9e1c..4259d6dd 100644 --- a/include/envs.h +++ b/include/envs.h @@ -113,6 +113,7 @@ static char *afl_environment_variables[] = { "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS", "AFL_IGNORE_PROBLEMS_COVERAGE", + "AFL_IGNORE_SEED_PROBLEMS", "AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 4c09fab7..9fc0cc57 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -951,19 +951,47 @@ void perform_dry_run(afl_state_t *afl) { } else { - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial " - "test cases.\n" - " This is bad news; raising the limit with the -t option is " - "possible, but\n" - " will probably make the fuzzing process extremely slow.\n\n" + static int say_once = 0; + + if (!say_once) { + + SAYF( + "\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the " + "initial " + "test cases.\n" + " This is bad news; raising the limit with the -t option is " + "possible, but\n" + " will probably make the fuzzing process extremely slow.\n\n" + + " If this test case is just a fluke, the other option is to " + "just avoid it\n" + " altogether, and find one that is less of a CPU hog.\n", + afl->fsrv.exec_tmout); + + if (!afl->afl_env.afl_ignore_seed_problems) { + + FATAL("Test case '%s' results in a timeout", fn); + + } + + say_once = 1; + + } + + if (!q->was_fuzzed) { - " If this test case is just a fluke, the other option is to " - "just avoid it\n" - " altogether, and find one that is less of a CPU hog.\n", - afl->fsrv.exec_tmout); + q->was_fuzzed = 1; + --afl->pending_not_fuzzed; + --afl->active_items; - FATAL("Test case '%s' results in a timeout", fn); + } + + q->disabled = 1; + q->perf_score = 0; + + WARNF("Test case '%s' results in a timeout, skipping", fn); + break; } @@ -2270,7 +2298,8 @@ void check_crash_handling(void) { reporting the awful way. */ #if !TARGET_OS_IPHONE - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) return; + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) + return; SAYF( "\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 97e00415..db82536d 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -316,6 +316,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_ignore_problems = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_IGNORE_SEED_PROBLEMS", + + afl_environment_variable_len)) { + + afl->afl_env.afl_ignore_seed_problems = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_IGNORE_TIMEOUTS", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 43834172..08960ac6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -275,6 +275,8 @@ static void usage(u8 *argv0, int more_help) { "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n" "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n" " ignore those libs for coverage\n" + "AFL_IGNORE_SEED_PROBLEMS: skip over crashes and timeouts in the seeds instead of\n" + " exiting\n" "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n" "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" -- cgit 1.4.1 From a809c3c50ce32fde390769b607b020dd68730474 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 3 Sep 2023 11:22:54 +0200 Subject: less impact --- frida_mode/src/instrument/instrument_arm64.c | 14 +++++--------- include/afl-fuzz.h | 1 + src/afl-fuzz-one.c | 10 ++++++++-- src/afl-fuzz-queue.c | 13 ++++++++++++- src/afl-fuzz.c | 28 +++++++++++++++++++--------- 5 files changed, 45 insertions(+), 21 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index a0c66697..1147275f 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -402,17 +402,13 @@ bool instrument_write_inline(GumArm64Writer *cw, GumAddress code_addr, } - /* - * The mov instruction supports up to a 16-bit offset. If our offset is out of - * range, then it can end up clobbering the op-code portion of the instruction - * rather than just the operands. So return false and fall back to the + /* + * The mov instruction supports up to a 16-bit offset. If our offset is out of + * range, then it can end up clobbering the op-code portion of the instruction + * rather than just the operands. So return false and fall back to the * alternative instrumentation. */ - if (area_offset > UINT16_MAX) { - - return false; - - } + if (area_offset > UINT16_MAX) { return false; } code.code.mov_x0_curr_loc |= area_offset << 5; diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d02e852e..217a720a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -610,6 +610,7 @@ typedef struct afl_state { u32 stage_cur, stage_max; /* Stage progression */ s32 splicing_with; /* Splicing with which test case? */ + s64 smallest_favored; /* smallest queue id favored */ u32 main_node_id, main_node_max; /* Main instance job splitting */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2ad4697e..ae39abe8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3442,7 +3442,12 @@ abandon_entry: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; afl->reinit_table = 1; - if (afl->queue_cur->favored) { --afl->pending_favored; } + if (afl->queue_cur->favored) { + + --afl->pending_favored; + afl->smallest_favored = -1; + + } } @@ -5905,7 +5910,8 @@ pacemaker_fuzzing: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; - if (afl->queue_cur->favored) { --afl->pending_favored; } + if (afl->queue_cur->favored) { --afl->pending_favored; + afl->smallest_favored = -1; } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 14ba1ace..5f915c9a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -826,6 +826,8 @@ void cull_queue(afl_state_t *afl) { /* Let's see if anything in the bitmap isn't captured in temp_v. If yes, and if it has a afl->top_rated[] contender, let's use it. */ + afl->smallest_favored = -1; + for (i = 0; i < afl->fsrv.map_size; ++i) { if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { @@ -849,7 +851,16 @@ void cull_queue(afl_state_t *afl) { afl->top_rated[i]->favored = 1; ++afl->queued_favored; - if (!afl->top_rated[i]->was_fuzzed) { ++afl->pending_favored; } + if (!afl->top_rated[i]->was_fuzzed) { + + ++afl->pending_favored; + if (unlikely(afl->smallest_favored > (s64)afl->top_rated[i]->id)) { + + afl->smallest_favored = (s64)afl->top_rated[i]->id; + + } + + } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c8cc7da6..d34b52db 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2707,20 +2707,30 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->old_seed_selection)) { - if (likely(afl->pending_favored)) { + if (likely(afl->pending_favored && afl->smallest_favored >= 0)) { - for (u32 iter = 0; iter < afl->queued_items; ++iter) { + afl->current_entry = afl->smallest_favored; - if (unlikely(afl->queue_buf[iter]->favored && - !afl->queue_buf[iter]->was_fuzzed)) { + /* - afl->current_entry = iter; - afl->queue_cur = afl->queue_buf[afl->current_entry]; - break; + } else { - } + for (s32 iter = afl->queued_items - 1; iter >= 0; --iter) + { - } + if (unlikely(afl->queue_buf[iter]->favored && + !afl->queue_buf[iter]->was_fuzzed)) { + + afl->current_entry = iter; + break; + + } + + } + + */ + + afl->queue_cur = afl->queue_buf[afl->current_entry]; } else { -- cgit 1.4.1 From 4cdf7a1e3e351f10537683d49a08181b6c1576cc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 23 Oct 2023 18:03:59 +0200 Subject: add scale encode mode for cmplog --- include/afl-fuzz.h | 2 +- src/afl-fuzz-redqueen.c | 263 +++++++++++++++++++++++++++++++++++++++++++----- src/afl-fuzz.c | 4 + 3 files changed, 244 insertions(+), 25 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 217a720a..8112d430 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -675,7 +675,7 @@ typedef struct afl_state { u32 cmplog_max_filesize; u32 cmplog_lvl; u32 colorize_success; - u8 cmplog_enable_arith, cmplog_enable_transform, + u8 cmplog_enable_arith, cmplog_enable_transform, cmplog_enable_scale, cmplog_enable_xtreme_transform, cmplog_random_colorization; struct afl_pass_stat *pass_stats; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index db4991db..b6c54df2 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -40,7 +40,7 @@ enum { IS_FP = 8, // is a floating point, not an integer /* --- below are internal settings, not from target cmplog */ IS_FP_MOD = 16, // arithemtic changed floating point - IS_INT_MOD = 32, // arithmetic changed interger + IS_INT_MOD = 32, // arithmetic changed integer IS_TRANSFORM = 64 // transformed integer }; @@ -775,6 +775,13 @@ static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) { } +#ifdef WORD_SIZE_64 +static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, + u128 pattern, u128 repl, u128 o_pattern, + u128 changed_val, u8 attr, u32 idx, + u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, + u32 len, u8 do_reverse, u8 lvl, u8 *status); +#endif static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -807,6 +814,29 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, hshape, attr); */ + u8 bytes; + + switch (hshape) { + + case 0: + case 1: + bytes = 1; + break; + case 2: + bytes = 2; + break; + case 3: + case 4: + bytes = 4; + break; + default: + bytes = 8; + + } + + // necessary for preventing heap access overflow + bytes = MIN(bytes, len - idx); + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { @@ -895,29 +925,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) { u64 b_val, o_b_val, mask; - u8 bytes; - - switch (hshape) { - - case 0: - case 1: - bytes = 1; - break; - case 2: - bytes = 2; - break; - case 3: - case 4: - bytes = 4; - break; - default: - bytes = 8; - - } - - // necessary for preventing heap access overflow - bytes = MIN(bytes, len - idx); - switch (bytes) { case 0: // cannot happen @@ -1285,6 +1292,125 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + // If 'S' is set for cmplog mode then we try a scale encoding of the value. + // Currently we can only handle bytes up to 1 << 55 + + if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u8 do_call = 1; + u64 new_val = repl << 2; + u32 saved_hshape = hshape; + + if (changed_val <= 255) { + + // nothing + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + + } else { + +#ifndef WORD_SIZE_64 + if (repl <= 0x00ffffffffffffff { + + new_val = repl << 8; + u8 scale_len = 0; + u64 tmp_val = repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = 8; + + } else { + + do_call = 0; + + } + +#else + { + + u128 new_val = ((u128)repl) << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + do_call = 0; + + } + +#endif + + } + + if (do_call) { + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_val, o_pattern, changed_val, 32, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + // here we add and subract 1 from the value, but only if it is not an // == or != comparison // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float @@ -1551,6 +1677,95 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + if (attr < IS_FP && attr < 32 && + (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u128 new_val = repl << 2; + u128 max_scale = (u128)1 << 120; + u32 saved_hshape = hshape; + + if (new_val <= 255) { + + hshape = 1; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (repl < max_scale) { + + u128 new_val = (u128)repl << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + } return 0; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2538f4a4..9fdd2193 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1152,6 +1152,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'A': afl->cmplog_enable_arith = 1; break; + case 's': + case 'S': + afl->cmplog_enable_scale = 1; + break; case 't': case 'T': afl->cmplog_enable_transform = 1; -- cgit 1.4.1 From 770e868d04c0f52a1c57e5471e459dd24a002748 Mon Sep 17 00:00:00 2001 From: yangzao Date: Fri, 24 Nov 2023 11:06:06 -0700 Subject: add custom_post_run.c --- custom_mutators/examples/custom_post_run.c | 53 ++++++++++++++++++++++++++++++ include/afl-fuzz.h | 12 +++++++ src/afl-fuzz-mutators.c | 12 +++++++ src/afl-fuzz-run.c | 2 ++ 4 files changed, 79 insertions(+) create mode 100644 custom_mutators/examples/custom_post_run.c (limited to 'include/afl-fuzz.h') diff --git a/custom_mutators/examples/custom_post_run.c b/custom_mutators/examples/custom_post_run.c new file mode 100644 index 00000000..073aac96 --- /dev/null +++ b/custom_mutators/examples/custom_post_run.c @@ -0,0 +1,53 @@ +// +// This is an example on how to use afl_custom_post_run +// It executes custom code each time after AFL++ executes the target +// +// cc -O3 -fPIC -shared -g -o custom_send.so -I../../include custom_send.c /////////////////////to_be_edited +// cd ../.. +// afl-cc -o test-instr test-instr.c +// AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/examples/custom_send.so \ +// afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo +// + + +#include "afl-fuzz.h" + +#include +#include +#include +#include + +typedef struct my_mutator { + + afl_state_t *afl; + +} my_mutator_t; + +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { + + my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); + if (!data) { + + perror("afl_custom_init alloc"); + return NULL; + + } + + data->afl = afl; + + return data; + +} + +void afl_custom_post_run(my_mutator_t *data, uint8_t *buf, size_t buf_size) { + + printf("hello from afl_custom_post_run\n"); + return; +} + + +void afl_custom_deinit(my_mutator_t *data) { + + free(data); + +} \ No newline at end of file diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 8112d430..7e91dc03 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1020,6 +1020,18 @@ struct custom_mutator { */ void (*afl_custom_fuzz_send)(void *data, const u8 *buf, size_t buf_size); + /** + * This method can be used if you want to run some code or scripts each time + * AFL++ executes the target with afl-fuzz. + * + * (Optional) + * + * @param data pointer returned in afl_custom_init by this custom mutator + * @param buf Buffer containing the test case + * @param buf_size Size of the test case + */ + void (*afl_custom_post_run)(void *data, const u8 *buf, size_t buf_size); + /** * Allow for additional analysis (e.g. calling a different tool that does a * different kind of coverage and saves this for the custom mutator). diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 64dbe7c6..17fb9368 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -397,6 +397,18 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { } + /* "afl_custom_post_run", optional */ + mutator->afl_custom_post_run = dlsym(dh, "afl_custom_post_run"); + if (!mutator->afl_custom_post_run) { + + ACTF("optional symbol 'afl_custom_post_run' not found."); + + } else { + + OKF("Found 'afl_custom_post_run'."); + + } + /* "afl_custom_queue_new_entry", optional */ mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry"); if (!mutator->afl_custom_queue_new_entry) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ac4fb4a9..29cc5352 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,6 +60,8 @@ 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 PROFILING clock_gettime(CLOCK_REALTIME, &spec); time_spent_start = (spec.tv_sec * 1000000000) + spec.tv_nsec; -- cgit 1.4.1 From 8af74bcaeebbe2407006333024d8803baacdb4e2 Mon Sep 17 00:00:00 2001 From: yangzao Date: Fri, 24 Nov 2023 22:47:50 -0700 Subject: update afl-fuzz-run --- custom_mutators/examples/custom_post_run.c | 6 +++--- include/afl-fuzz.h | 4 +--- src/afl-fuzz-run.c | 19 ++++++++++++++++++- 3 files changed, 22 insertions(+), 7 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/custom_mutators/examples/custom_post_run.c b/custom_mutators/examples/custom_post_run.c index 073aac96..828216ea 100644 --- a/custom_mutators/examples/custom_post_run.c +++ b/custom_mutators/examples/custom_post_run.c @@ -2,10 +2,10 @@ // This is an example on how to use afl_custom_post_run // It executes custom code each time after AFL++ executes the target // -// cc -O3 -fPIC -shared -g -o custom_send.so -I../../include custom_send.c /////////////////////to_be_edited +// cc -O3 -fPIC -shared -g -o custom_post_run.so -I../../include custom_post_run.c // cd ../.. // afl-cc -o test-instr test-instr.c -// AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/examples/custom_send.so \ +// AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/examples/custom_post_run.so \ // afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo // @@ -39,7 +39,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { } -void afl_custom_post_run(my_mutator_t *data, uint8_t *buf, size_t buf_size) { +void afl_custom_post_run(my_mutator_t *data) { printf("hello from afl_custom_post_run\n"); return; diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7e91dc03..94f48009 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1027,10 +1027,8 @@ struct custom_mutator { * (Optional) * * @param data pointer returned in afl_custom_init by this custom mutator - * @param buf Buffer containing the test case - * @param buf_size Size of the test case */ - void (*afl_custom_post_run)(void *data, const u8 *buf, size_t buf_size); + void (*afl_custom_post_run)(void *data); /** * Allow for additional analysis (e.g. calling a different tool that does a diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 29cc5352..ac346b86 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,7 +60,7 @@ 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); - + post_run(afl); #ifdef PROFILING clock_gettime(CLOCK_REALTIME, &spec); @@ -1113,3 +1113,20 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } +/* Run some code each time scripts each time AFL++ executes the target + with afl-fuzz. */ + +void post_run(afl_state_t *afl) { + if (unlikely(afl->custom_mutators_count)) { + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_post_run) { + + el->afl_custom_post_run(el->data); + + } + + }); + } +} \ No newline at end of file -- cgit 1.4.1 From faedb3fb29186c29a4f0cf28daa5d07350ed8094 Mon Sep 17 00:00:00 2001 From: yangzao Date: Sat, 25 Nov 2023 21:18:32 -0700 Subject: update python module --- custom_mutators/examples/example.py | 5 +++++ include/afl-fuzz.h | 2 ++ src/afl-fuzz-python.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) (limited to 'include/afl-fuzz.h') diff --git a/custom_mutators/examples/example.py b/custom_mutators/examples/example.py index 3a6d22e4..830f302f 100644 --- a/custom_mutators/examples/example.py +++ b/custom_mutators/examples/example.py @@ -133,6 +133,11 @@ def fuzz(buf, add_buf, max_size): # @return: The buffer containing the test case after # ''' # return buf +# def post_run(): +# ''' +# Called after each time the execution of the target program by AFL++ +# ''' +# pass # # def havoc_mutation(buf, max_size): # ''' diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 94f48009..f1813df6 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -345,6 +345,7 @@ enum { /* 13 */ PY_FUNC_DESCRIBE, /* 14 */ PY_FUNC_FUZZ_SEND, /* 15 */ PY_FUNC_SPLICE_OPTOUT, + /* 16 */ PY_FUNC_POST_RUN, PY_FUNC_COUNT }; @@ -1085,6 +1086,7 @@ void finalize_py_module(void *); u32 fuzz_count_py(void *, const u8 *, size_t); void fuzz_send_py(void *, const u8 *, size_t); +void post_run_py(void *); size_t post_process_py(void *, u8 *, size_t, u8 **); s32 init_trim_py(void *, u8 *, size_t); s32 post_trim_py(void *, u8); diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 7dad0770..1b287405 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -249,6 +249,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "queue_get"); py_functions[PY_FUNC_FUZZ_SEND] = PyObject_GetAttrString(py_module, "fuzz_send"); + py_functions[PY_FUNC_POST_RUN] = + PyObject_GetAttrString(py_module, "post_run"); py_functions[PY_FUNC_SPLICE_OPTOUT] = PyObject_GetAttrString(py_module, "splice_optout"); if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { afl->custom_splice_optout = 1; } @@ -468,6 +470,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, } + if (py_functions[PY_FUNC_POST_RUN]) { + + mutator->afl_custom_post_run = post_run_py; + + } + if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { mutator->afl_custom_splice_optout = splice_optout_py; @@ -925,6 +933,30 @@ void fuzz_send_py(void *py_mutator, const u8 *buf, size_t buf_size) { } +void post_run_py(void *py_mutator) { + + PyObject *py_args, *py_value; + + py_args = PyTuple_New(0); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator) + ->py_functions[PY_FUNC_POST_RUN], + py_args); + Py_DECREF(py_args); + + if (py_value != NULL) { + + Py_DECREF(py_value); + + } else { + + PyErr_Print(); + FATAL("Call failed"); + + } + +} + u8 queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue, const u8 *filename_orig_queue) { -- cgit 1.4.1 From 8fedf4998449d5b6b909a1118fc2e152e4d2e6e7 Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Tue, 23 Jan 2024 19:36:49 +0100 Subject: replay mode support --- .gitignore | 1 + include/afl-fuzz.h | 4 + include/config.h | 5 +- include/persistent_replay.h | 149 ++++++++++++++++++++++++++++ instrumentation/afl-compiler-rt.o.c | 36 +++++++ src/afl-forkserver.c | 79 +++++++++------ src/afl-fuzz-init.c | 6 ++ src/afl-fuzz.c | 2 +- utils/persistent_mode/Makefile | 3 +- utils/persistent_mode/persistent_demo_new.c | 15 +-- 10 files changed, 257 insertions(+), 43 deletions(-) create mode 100644 include/persistent_replay.h (limited to 'include/afl-fuzz.h') diff --git a/.gitignore b/.gitignore index f76a86fc..891ced9f 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ utils/optimin/build utils/optimin/optimin utils/persistent_mode/persistent_demo utils/persistent_mode/persistent_demo_new +utils/persistent_mode/persistent_demo_new_compat utils/persistent_mode/test-instr utils/plot_ui/afl-plot-ui vuln_prog diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f1813df6..864bc6b6 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -124,6 +124,10 @@ #define CASE_PREFIX "id_" #endif /* ^!SIMPLE_FILES */ +#ifdef AFL_PERSISTENT_RECORD + #define RECORD_PREFIX "RECORD:" +#endif + #define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */ // Little helper to access the ptr to afl->##name_buf - for use in afl_realloc. diff --git a/include/config.h b/include/config.h index 63340650..1649f110 100644 --- a/include/config.h +++ b/include/config.h @@ -83,7 +83,10 @@ will be kept and written to the crash/ directory as RECORD:... files. Note that every crash will be written, not only unique ones! */ -// #define AFL_PERSISTENT_RECORD +// #define AFL_PERSISTENT_RECORD + +/* Builds compiler-rt with support to replay persistent records */ +// #define AFL_PERSISTENT_REPLAY /* console output colors: There are three ways to configure its behavior * 1. default: colored outputs fixed on: defined USE_COLOR && defined diff --git a/include/persistent_replay.h b/include/persistent_replay.h new file mode 100644 index 00000000..b1a55e9f --- /dev/null +++ b/include/persistent_replay.h @@ -0,0 +1,149 @@ +#ifndef _HAVE_PERSISTENT_REPLAY_H +#define _HAVE_PERSISTENT_REPLAY_H + +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned short int is_replay_record; +static unsigned int replay_record; +static unsigned int replay_record_cnt; +static char replay_record_path[PATH_MAX]; +static char **record_arg; +static char *replay_record_dir; +static struct dirent **record_list; + +static int select_files(const struct dirent *dirbuf) { + + char fn[4096]; + + if (dirbuf->d_name[0] == '.'){ + return 0; + } else { + snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record); + return !!strstr(dirbuf->d_name, fn); + } +} + +static int compare_files(const struct dirent **da, const struct dirent **db) { + + unsigned int c1=0, c2=0; + + sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1); + sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2); + + return c1-c2; +} + +__attribute__((destructor)) static void __afl_record_replay_destroy(void){ + for (int i=0; i < replay_record_cnt; i++) { + free(record_list[i]); + } + free(record_list); +} + +__attribute__((constructor)) static void __afl_record_replay_init(int argc, char **argv) { + + char **argp; + + /* caveat: if harness uses @@ and we don't pass it, it will regardless loop the number of iterations defined for AFL_LOOP (on the same file)*/ + if(!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))){ + // printf("[warning] AFL_PERSISTENT_REPLAY not set.\n"); + return; + } + + replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY")); + replay_record_dir = getenv("AFL_PERSISTENT_DIR"); + replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./", &record_list, select_files, compare_files); + + if (!replay_record_cnt){ + printf("[error] Can't find the requested record!\n"); + is_replay_record = 0; + } + + argp = argv; + while (*argp){ + if (!strcmp(*argp, "@@")){ + record_arg = argp; + *record_arg = replay_record_path; + break; + } + ++argp; + } + +} + +/* only used if explictly included for compatibility + compiling without afl-cc */ + +#ifdef AFL_COMPAT + +#ifndef PATH_MAX + #define PATH_MAX 4096 +#endif + +#define FUZZ_BUF_SIZE 1024000 + +// extern ssize_t read(int fildes, void *buf, size_t nbyte); + +//extern int __afl_persistent_loop(unsigned int max_cnt); +//extern unsigned char fuzz_buf[]; + +#ifndef __AFL_HAVE_MANUAL_CONTROL + #define __AFL_HAVE_MANUAL_CONTROL +#endif + +#define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE)) +#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf +#define __AFL_FUZZ_INIT() void sync(void); +#define __AFL_INIT() sync() +#define __AFL_LOOP(x) __afl_persistent_loop(x) + +unsigned char fuzz_buf[FUZZ_BUF_SIZE]; + +int __afl_persistent_loop(unsigned int max_cnt) { + + static unsigned int cycle_cnt = 1; + static unsigned short int inited = 0; + char tcase[PATH_MAX]; + + if( is_replay_record ){ + + if (!inited){ + cycle_cnt = replay_record_cnt; + inited = 1; + } + + snprintf(tcase, PATH_MAX, "%s/%s", + replay_record_dir ? replay_record_dir : "./", + record_list[replay_record_cnt-cycle_cnt]->d_name); + + + if (record_arg) { + *record_arg = tcase; + } else { + int fd = open(tcase, O_RDONLY); + dup2(fd, 0); + close(fd); + } + + } else { + + if (!inited){ + cycle_cnt = max_cnt; + inited = 1; + } + + } + + return cycle_cnt--; +} + +#endif // AFL_COMPAT + +#endif // _HAVE_PERSISTENT_REPLAY_H \ No newline at end of file diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 39a762b6..0fa22aee 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -83,6 +83,10 @@ #include #include +#ifdef AFL_PERSISTENT_REPLAY +#include "persistent_replay.h" +#endif + /* Globals needed by the injected instrumentation. The __afl_area_initial region is used for instrumentation output before __afl_map_shm() has a chance to run. It will end up as .comm, so it shouldn't be too wasteful. */ @@ -1338,6 +1342,38 @@ int __afl_persistent_loop(unsigned int max_cnt) { static u8 first_pass = 1; static u32 cycle_cnt; +#ifdef AFL_PERSISTENT_REPLAY + +#ifndef PATH_MAX + #define PATH_MAX 4096 +#endif + + static u8 inited = 0; + char tcase[PATH_MAX]; + + if( unlikely(is_replay_record) ){ + + if (!inited){ + cycle_cnt = replay_record_cnt; + inited = 1; + } + + snprintf(tcase, PATH_MAX, "%s/%s", + replay_record_dir ? replay_record_dir : "./", + record_list[replay_record_cnt-cycle_cnt]->d_name); + + if (record_arg) { + *record_arg = tcase; + } else { + int fd = open(tcase, O_RDONLY); + dup2(fd, 0); + close(fd); + } + return cycle_cnt--; + } else + +#endif + if (first_pass) { /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3f9bfa72..f8dd783f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1591,6 +1591,11 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, u32 exec_ms; u32 write_value = fsrv->last_run_timed_out; +#ifdef AFL_PERSISTENT_RECORD + fsrv_run_result_t retval = FSRV_RUN_OK; + char *persistent_out_fmt; +#endif + #ifdef __linux__ if (fsrv->nyx_mode) { @@ -1684,7 +1689,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } -#ifdef AFL_PERSISTENT_RECORD +#ifdef AFL_eERSISTENT_RECORD // end of persistent loop? if (unlikely(fsrv->persistent_record && fsrv->persistent_record_pid != fsrv->child_pid)) { @@ -1790,8 +1795,14 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (unlikely(fsrv->last_run_timed_out)) { fsrv->last_kill_signal = fsrv->child_kill_signal; - return FSRV_RUN_TMOUT; +#ifndef AFL_PERSISTENT_RECORD + return FSRV_RUN_TMOUT; +#else + retval = FSRV_RUN_TMOUT; + persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; +#endif } /* Did we crash? @@ -1811,48 +1822,58 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, (fsrv->uses_crash_exitcode && WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) { -#ifdef AFL_PERSISTENT_RECORD - if (unlikely(fsrv->persistent_record)) { + /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */ + fsrv->last_kill_signal = + WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; - char fn[PATH_MAX]; - u32 i, writecnt = 0; - for (i = 0; i < fsrv->persistent_record; ++i) { +#ifndef AFL_PERSISTENT_RECORD + return FSRV_RUN_CRASH; +#else + retval = FSRV_RUN_CRASH; + persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; +#endif - u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; - u8 *data = fsrv->persistent_record_data[entry]; - u32 len = fsrv->persistent_record_len[entry]; - if (likely(len && data)) { + } - snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u", - fsrv->persistent_record_dir, fsrv->persistent_record_cnt, - writecnt++); - int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd >= 0) { + /* success :) */ + return FSRV_RUN_OK; + +#ifdef AFL_PERSISTENT_RECORD +store_persistent_record: + if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && + unlikely(fsrv->persistent_record)) { - ck_write(fd, data, len, fn); - close(fd); + char fn[PATH_MAX]; + u32 i, writecnt = 0; + for (i = 0; i < fsrv->persistent_record; ++i) { - } + u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; + u8 *data = fsrv->persistent_record_data[entry]; + u32 len = fsrv->persistent_record_len[entry]; + if (likely(len && data)) { + + snprintf(fn, sizeof(fn), persistent_out_fmt, + fsrv->persistent_record_dir, fsrv->persistent_record_cnt, + writecnt++); + int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd >= 0) { + + ck_write(fd, data, len, fn); + close(fd); } } - ++fsrv->persistent_record_cnt; - } -#endif - - /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */ - fsrv->last_kill_signal = - WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; - return FSRV_RUN_CRASH; + ++fsrv->persistent_record_cnt; } - /* success :) */ - return FSRV_RUN_OK; + return retval; +#endif } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 35932913..5b7dc4c1 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1915,6 +1915,9 @@ static void handle_existing_out_dir(afl_state_t *afl) { } +#ifdef AFL_PERSISTENT_RECORD + delete_files(fn, RECORD_PREFIX); +#endif if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); @@ -1947,6 +1950,9 @@ static void handle_existing_out_dir(afl_state_t *afl) { } +#ifdef AFL_PERSISTENT_RECORD + delete_files(fn, RECORD_PREFIX); +#endif if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 17949fd7..40c30472 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2163,7 +2163,7 @@ int main(int argc, char **argv_orig, char **envp) { } - afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir); + afl->fsrv.persistent_record_dir = alloc_printf("%s", afl->out_dir); } diff --git a/utils/persistent_mode/Makefile b/utils/persistent_mode/Makefile index e348c46c..64de82a7 100644 --- a/utils/persistent_mode/Makefile +++ b/utils/persistent_mode/Makefile @@ -1,10 +1,11 @@ all: ../../afl-clang-fast -o persistent_demo persistent_demo.c ../../afl-clang-fast -o persistent_demo_new persistent_demo_new.c + gcc -g -I ../../include -o persistent_demo_new_compat persistent_demo_new.c AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -o test-instr test-instr.c document: AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c clean: - rm -f persistent_demo persistent_demo_new test-instr + rm -f persistent_demo persistent_demo_new persistent_demo_new_compat test-instr diff --git a/utils/persistent_mode/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c index 285f50aa..40ada9e1 100644 --- a/utils/persistent_mode/persistent_demo_new.c +++ b/utils/persistent_mode/persistent_demo_new.c @@ -31,17 +31,8 @@ /* this lets the source compile without afl-clang-fast/lto */ #ifndef __AFL_FUZZ_TESTCASE_LEN - -ssize_t fuzz_len; -unsigned char fuzz_buf[1024000]; - - #define __AFL_FUZZ_TESTCASE_LEN fuzz_len - #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf - #define __AFL_FUZZ_INIT() void sync(void); - #define __AFL_LOOP(x) \ - ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0) - #define __AFL_INIT() sync() - +#define AFL_COMPAT +#include "persistent_replay.h" #endif __AFL_FUZZ_INIT(); @@ -95,6 +86,8 @@ int main(int argc, char **argv) { if (buf[5] == '!') { printf("six\n"); + char *nullo = NULL+1; + *nullo = 'p'; abort(); } -- cgit 1.4.1 From 06f0982f0f4506e18872efb86b97993f2518988c Mon Sep 17 00:00:00 2001 From: Han Zheng <35988108+kdsjZh@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:13:21 +0100 Subject: Enhancement on Deterministic stage (#1972) * fuzzer: init commit based on aflpp 60dc37a8cf09f8e9048e4b6a2204d6c90b27655a * fuzzers: adding the skip variables and initialize * log: profile the det/havoc finding * log: add profile log output * fuzzers: sperate log/skipdet module * fuzzers: add quick eff_map calc * fuzzers: add skip_eff_map in fuzz_one * fuzzers: mark whole input space in eff_map * fuzzers: add undet bit threshold to skip some seeds * fuzzers: fix one byte overflow * fuzzers: fix overflow * fix code format * add havoc only again * code format * remove log to INTROSPECTION, rename skipdet module * rename skipdet module * remove log to stats * clean redundant code * code format * remove redundant code format check * remove redundant doc * remove redundant objects * clean files * change -d to default skipdet * disable deterministic when using CUSTOM_MUTATOR * revert fix --- include/afl-fuzz.h | 58 +++++++ include/config.h | 12 ++ include/forkserver.h | 3 +- src/afl-fuzz-init.c | 15 ++ src/afl-fuzz-one.c | 166 ++++++++++++++------ src/afl-fuzz-queue.c | 11 ++ src/afl-fuzz-skipdet.c | 403 +++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 10 +- src/afl-fuzz-stats.c | 38 +++++ src/afl-fuzz.c | 13 +- 10 files changed, 680 insertions(+), 49 deletions(-) create mode 100644 src/afl-fuzz-skipdet.c (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f1813df6..c2b09b2e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -149,6 +149,48 @@ struct tainted { }; +struct inf_profile { + + u32 inf_skipped_bytes; /* Inference Stage Profiling */ + u64 inf_execs_cost, inf_time_cost; + +}; + +/* ToDo: add cmplog profile as well */ +struct havoc_profile { + + u32 queued_det_stage, /* Det/Havoc Stage Profiling */ + queued_havoc_stage, total_queued_det, edge_det_stage, edge_havoc_stage, + total_det_edge; + + u64 det_stage_time, havoc_stage_time, total_det_time; + +}; + +struct skipdet_entry { + + u8 continue_inf, done_eff; + u32 undet_bits, quick_eff_bytes; + + u8 *skip_eff_map, /* we'v finish the eff_map */ + *done_inf_map; /* some bytes are not done yet */ + +}; + +struct skipdet_global { + + u8 use_skip_havoc; + + u32 undet_bits_threshold; + + u64 last_cov_undet; + + u8 *virgin_det_bits; /* global fuzzed bits */ + + struct inf_profile *inf_prof; + +}; + struct queue_entry { u8 *fname; /* File name for the test case */ @@ -203,6 +245,8 @@ struct queue_entry { struct queue_entry *mother; /* queue entry this based on */ + struct skipdet_entry *skipdet_e; + }; struct extra_data { @@ -247,6 +291,8 @@ enum { /* 19 */ STAGE_CUSTOM_MUTATOR, /* 20 */ STAGE_COLORIZATION, /* 21 */ STAGE_ITS, + /* 22 */ STAGE_INF, + /* 23 */ STAGE_QUICK, STAGE_NUM_MAX @@ -782,6 +828,11 @@ typedef struct afl_state { * is too large) */ struct queue_entry **q_testcase_cache; + /* Global Profile Data for deterministic/havoc-splice stage */ + struct havoc_profile *havoc_prof; + + struct skipdet_global *skipdet_g; + #ifdef INTROSPECTION char mutation[8072]; char m_tmp[4096]; @@ -1232,6 +1283,13 @@ AFL_RAND_RETURN rand_next(afl_state_t *afl); /* probability between 0.0 and 1.0 */ double rand_next_percent(afl_state_t *afl); +/* SkipDet Functions */ + +u8 skip_deterministic_stage(afl_state_t *, u8 *, u8 *, u32, u64); +u8 is_det_timeout(u64, u8); + +void plot_profile_data(afl_state_t *, struct queue_entry *); + /**** Inline routines ****/ /* Generate a random number (from 0 to limit - 1). This may diff --git a/include/config.h b/include/config.h index 63340650..7ad73c2f 100644 --- a/include/config.h +++ b/include/config.h @@ -52,6 +52,18 @@ /* Default file permission umode when creating files (default: 0600) */ #define DEFAULT_PERMISSION 0600 +/* SkipDet's global configuration */ + +#define MINIMAL_BLOCK_SIZE 64 +#define SMALL_DET_TIME (60 * 1000 * 1000U) +#define MAXIMUM_INF_EXECS (16 * 1024U) +#define MAXIMUM_QUICK_EFF_EXECS (64 * 1024U) +#define THRESHOLD_DEC_TIME (20 * 60 * 1000U) + +/* Set the Prob of selecting eff_bytes 3 times more than original, + Now disabled */ +#define EFF_HAVOC_RATE 3 + /* CMPLOG/REDQUEEN TUNING * * Here you can modify tuning and solving options for CMPLOG. diff --git a/include/forkserver.h b/include/forkserver.h index f6230fe8..f1d3b5b1 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -126,7 +126,8 @@ typedef struct afl_forkserver { u8 *out_file, /* File to fuzz, if any */ *target_path; /* Path of the target */ - FILE *plot_file; /* Gnuplot output file */ + FILE *plot_file, /* Gnuplot output file */ + *det_plot_file; /* Note: last_run_timed_out is u32 to send it to the child as 4 byte array */ u32 last_run_timed_out; /* Traced process timed out? */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 8ab44a3b..057d8cf5 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2236,6 +2236,21 @@ void setup_dirs_fds(afl_state_t *afl) { fflush(afl->fsrv.plot_file); +#ifdef INTROSPECTION + + tmp = alloc_printf("%s/plot_det_data", afl->out_dir); + + int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); + if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } + ck_free(tmp); + + afl->fsrv.det_plot_file = fdopen(fd, "w"); + if (!afl->fsrv.det_plot_file) { PFATAL("fdopen() failed"); } + + if (afl->in_place_resume) { fseek(afl->fsrv.det_plot_file, 0, SEEK_END); } + +#endif + /* ignore errors */ } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 01e34b69..4a7d3fad 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -545,12 +545,37 @@ u8 fuzz_one_original(afl_state_t *afl) { } + u64 before_det_time = get_cur_time(); +#ifdef INTROSPECTION + + u64 before_havoc_time; + u32 before_det_findings = afl->queued_items, + before_det_edges = count_non_255_bytes(afl, afl->virgin_bits), + before_havoc_findings, before_havoc_edges; + u8 is_logged = 0; + +#endif + if (!afl->skip_deterministic) { + + if (!skip_deterministic_stage(afl, in_buf, out_buf, len, before_det_time)) { + + goto abandon_entry; + + } + + } + + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map; + /* Skip right away if -d is given, if it has not been chosen sufficiently often to warrant the expensive deterministic stage (fuzz_level), or if it has gone through deterministic testing in earlier, resumed runs (passed_det). */ + /* if skipdet decide to skip the seed or no interesting bytes found, + we skip the whole deterministic stage as well */ if (likely(afl->skip_deterministic) || likely(afl->queue_cur->passed_det) || + likely(!afl->queue_cur->skipdet_e->quick_eff_bytes) || likely(perf_score < (afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100 ? afl->queue_cur->depth * 30 @@ -609,6 +634,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); #ifdef INTROSPECTION @@ -725,6 +754,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -760,6 +793,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); FLIP_BIT(out_buf, afl->stage_cur + 2); @@ -828,6 +865,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + out_buf[afl->stage_cur] ^= 0xFF; #ifdef INTROSPECTION @@ -837,37 +878,6 @@ u8 fuzz_one_original(afl_state_t *afl) { if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } - /* We also use this stage to pull off a simple trick: we identify - bytes that seem to have no effect on the current execution path - even when fully flipped - and we skip them during more expensive - deterministic stages, such as arithmetics or known ints. */ - - if (!eff_map[EFF_APOS(afl->stage_cur)]) { - - u64 cksum; - - /* If in non-instrumented mode or if the file is very short, just flag - everything without wasting time on checksums. */ - - if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { - - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - - } else { - - cksum = ~prev_cksum; - - } - - if (cksum != prev_cksum) { - - eff_map[EFF_APOS(afl->stage_cur)] = 1; - ++eff_cnt; - - } - - } - out_buf[afl->stage_cur] ^= 0xFF; } @@ -876,18 +886,8 @@ u8 fuzz_one_original(afl_state_t *afl) { whole thing as worth fuzzing, since we wouldn't be saving much time anyway. */ - if (eff_cnt != (u32)EFF_ALEN(len) && - eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) { - - memset(eff_map, 1, EFF_ALEN(len)); - - afl->blocks_eff_select += EFF_ALEN(len); - - } else { - - afl->blocks_eff_select += eff_cnt; - - } + memset(eff_map, 1, EFF_ALEN(len)); + afl->blocks_eff_select += EFF_ALEN(len); afl->blocks_eff_total += EFF_ALEN(len); @@ -921,6 +921,10 @@ u8 fuzz_one_original(afl_state_t *afl) { } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; *(u16 *)(out_buf + i) ^= 0xFFFF; @@ -967,6 +971,10 @@ u8 fuzz_one_original(afl_state_t *afl) { } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; @@ -1023,6 +1031,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1110,6 +1122,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1244,6 +1260,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1381,6 +1401,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < (u32)sizeof(interesting_8); ++j) { @@ -1444,6 +1468,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < sizeof(interesting_16) / 2; ++j) { @@ -1536,6 +1564,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < sizeof(interesting_32) / 4; ++j) { @@ -1626,6 +1658,10 @@ skip_interest: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; /* Extras are sorted by size, from smallest to largest. This means @@ -1693,6 +1729,10 @@ skip_interest: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->extras_cnt; ++j) { @@ -1755,6 +1795,10 @@ skip_user_extras: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS); @@ -1813,6 +1857,10 @@ skip_user_extras: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->a_extras_cnt; ++j) { @@ -2020,6 +2068,19 @@ custom_mutator_stage: havoc_stage: +#ifdef INTROSPECTION + + if (!is_logged) { + + is_logged = 1; + before_havoc_findings = afl->queued_items; + before_havoc_edges = count_non_255_bytes(afl, afl->virgin_bits); + before_havoc_time = get_cur_time(); + + } + +#endif + if (unlikely(afl->custom_only)) { /* Force UI update */ @@ -3430,6 +3491,25 @@ retry_splicing: ret_val = 0; +#ifdef INTROSPECTION + + afl->havoc_prof->queued_det_stage = + before_havoc_findings - before_det_findings; + afl->havoc_prof->queued_havoc_stage = + afl->queued_items - before_havoc_findings; + afl->havoc_prof->total_queued_det += afl->havoc_prof->queued_det_stage; + afl->havoc_prof->edge_det_stage = before_havoc_edges - before_det_edges; + afl->havoc_prof->edge_havoc_stage = + count_non_255_bytes(afl, afl->virgin_bits) - before_havoc_edges; + afl->havoc_prof->total_det_edge += afl->havoc_prof->edge_det_stage; + afl->havoc_prof->det_stage_time = before_havoc_time - before_det_time; + afl->havoc_prof->havoc_stage_time = get_cur_time() - before_havoc_time; + afl->havoc_prof->total_det_time += afl->havoc_prof->det_stage_time; + + plot_profile_data(afl, afl->queue_cur); + +#endif + /* we are through with this queue entry - for this iteration */ abandon_entry: diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4b9627f7..67931bba 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -664,6 +664,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } + q->skipdet_e = (struct skipdet_entry *)ck_alloc(sizeof(struct skipdet_entry)); + } /* Destroy the entire queue. */ @@ -679,6 +681,15 @@ void destroy_queue(afl_state_t *afl) { q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); + if (q->skipdet_e) { + + if (q->skipdet_e->done_inf_map) ck_free(q->skipdet_e->done_inf_map); + if (q->skipdet_e->skip_eff_map) ck_free(q->skipdet_e->skip_eff_map); + + ck_free(q->skipdet_e); + + } + ck_free(q); } diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c new file mode 100644 index 00000000..e52d59a3 --- /dev/null +++ b/src/afl-fuzz-skipdet.c @@ -0,0 +1,403 @@ + + +#include "afl-fuzz.h" + +void flip_range(u8 *input, u32 pos, u32 size) { + + for (u32 i = 0; i < size; i++) + input[pos + i] ^= 0xFF; + + return; + +} + +#define MAX_EFF_TIMEOUT (10 * 60 * 1000) +#define MAX_DET_TIMEOUT (15 * 60 * 1000) +u8 is_det_timeout(u64 cur_ms, u8 is_flip) { + + if (is_flip) { + + if (unlikely(get_cur_time() - cur_ms > MAX_EFF_TIMEOUT)) return 1; + + } else { + + if (unlikely(get_cur_time() - cur_ms > MAX_DET_TIMEOUT)) return 1; + + } + + return 0; + +} + +/* decide if the seed should be deterministically fuzzed */ + +u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) { + + if (!afl->skipdet_g->virgin_det_bits) { + + afl->skipdet_g->virgin_det_bits = + (u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size); + + } + + if (!q->favored || q->passed_det) return 0; + if (!q->trace_mini) return 0; + + if (!afl->skipdet_g->last_cov_undet) + afl->skipdet_g->last_cov_undet = get_cur_time(); + + if (get_cur_time() - afl->skipdet_g->last_cov_undet >= THRESHOLD_DEC_TIME) { + + if (afl->skipdet_g->undet_bits_threshold >= 2) { + + afl->skipdet_g->undet_bits_threshold *= 0.75; + afl->skipdet_g->last_cov_undet = get_cur_time(); + + } + + } + + u32 new_det_bits = 0; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) { new_det_bits++; } + + } + + } + + if (!afl->skipdet_g->undet_bits_threshold) + afl->skipdet_g->undet_bits_threshold = new_det_bits * 0.05; + + if (new_det_bits >= afl->skipdet_g->undet_bits_threshold) { + + afl->skipdet_g->last_cov_undet = get_cur_time(); + q->skipdet_e->undet_bits = new_det_bits; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) + afl->skipdet_g->virgin_det_bits[i] = 1; + + } + + } + + return 1; + + } + + return 0; + +} + +/* + consists of two stages that + return 0 if exec failed. +*/ + +u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, + u32 len, u64 before_det_time) { + + u64 orig_hit_cnt, new_hit_cnt; + + if (afl->queue_cur->skipdet_e->done_eff) return 1; + + if (!should_det_fuzz(afl, afl->queue_cur)) return 1; + + /* Add check to make sure that for seeds without too much undet bits, + we ignore them */ + + /****************** + * SKIP INFERENCE * + ******************/ + + afl->stage_short = "inf"; + afl->stage_name = "inference"; + afl->stage_cur = 0; + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + memset(inf_eff_map, 1, sizeof(u8) * len); + + if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } + + u64 prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + u64 _prev_cksum = prev_cksum; + + if (MINIMAL_BLOCK_SIZE * 8 < len) { + + // u64 size_skiped = 0, quick_skip_exec = total_execs, quick_skip_time = + // get_cur_time(); + u64 pre_inf_exec = afl->fsrv.total_execs, pre_inf_time = get_cur_time(); + + /* if determine stage time / input size is too small, just go ahead */ + + u32 pos = 0, cur_block_size = MINIMAL_BLOCK_SIZE, max_block_size = len / 8; + + while (pos < len - 1) { + + cur_block_size = MINIMAL_BLOCK_SIZE; + + while (cur_block_size < max_block_size) { + + u32 flip_block_size = + (cur_block_size + pos < len) ? cur_block_size : len - 1 - pos; + + afl->stage_cur += 1; + + flip_range(out_buf, pos, flip_block_size); + + if (common_fuzz_stuff(afl, out_buf, len)) return 0; + + flip_range(out_buf, pos, flip_block_size); + + u64 cksum = + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + // printf("Now trying range %d with %d, %s.\n", pos, cur_block_size, + // (cksum == prev_cksum) ? (u8*)"Yes" : (u8*) "Not"); + + /* continue until we fail or exceed length */ + if (cksum == _prev_cksum) { + + cur_block_size *= 2; + + if (cur_block_size >= len - 1 - pos) break; + + } else { + + break; + + } + + } + + if (cur_block_size == MINIMAL_BLOCK_SIZE) { + + /* we failed early on*/ + + pos += cur_block_size; + + } else { + + u32 cur_skip_len = (cur_block_size / 2 + pos < len) + ? (cur_block_size / 2) + : (len - pos - 1); + + memset(inf_eff_map + pos, 0, cur_skip_len); + + afl->skipdet_g->inf_prof->inf_skipped_bytes += cur_skip_len; + + pos += cur_skip_len; + + } + + } + + afl->skipdet_g->inf_prof->inf_execs_cost += + (afl->fsrv.total_execs - pre_inf_exec); + afl->skipdet_g->inf_prof->inf_time_cost += (get_cur_time() - pre_inf_time); + // PFATAL("Done, now have %d bytes skipped, with exec %lld, time %lld.\n", + // afl->inf_skipped_bytes, afl->inf_execs_cost, afl->inf_time_cost); + + } else + + memset(inf_eff_map, 1, len); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_INF] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_INF] += afl->stage_cur; + + /**************************** + * Quick Skip Effective Map * + ****************************/ + + /* Quick Effective Map Calculation */ + + afl->stage_short = "quick"; + afl->stage_name = "quick eff"; + afl->stage_cur = 0; + afl->stage_max = 32 * 1024; + + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u32 before_skip_inf = afl->queued_items; + + /* clean all the eff bytes, since previous eff bytes are already fuzzed */ + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map, + *done_inf_map = afl->queue_cur->skipdet_e->done_inf_map; + + if (!skip_eff_map) { + + skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map; + + } else { + + memset(skip_eff_map, 0, sizeof(u8) * len); + + } + + /* restore the starting point */ + if (!done_inf_map) { + + done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->done_inf_map = done_inf_map; + + } else { + + for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) { + + if (done_inf_map[afl->stage_cur] == 0) break; + + } + + } + + /* depending on the seed's performance, we could search eff bytes + for multiple rounds */ + + u8 eff_round_continue = 1, eff_round_done = 0, done_eff = 0, repeat_eff = 0, + fuzz_nearby = 0, *non_eff_bytes = 0; + + u64 before_eff_execs = afl->fsrv.total_execs; + + if (getenv("REPEAT_EFF")) repeat_eff = 1; + if (getenv("FUZZ_NEARBY")) fuzz_nearby = 1; + + if (fuzz_nearby) { + + non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + // clean exec cksum + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + } + + do { + + eff_round_continue = 0; + afl->stage_max = 32 * 1024; + + for (; afl->stage_cur < afl->stage_max && afl->stage_cur < len; + ++afl->stage_cur) { + + afl->stage_cur_byte = afl->stage_cur; + + if (!inf_eff_map[afl->stage_cur_byte] || + skip_eff_map[afl->stage_cur_byte]) + continue; + + if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; } + + u8 orig = out_buf[afl->stage_cur_byte], replace = rand_below(afl, 256); + + while (replace == orig) { + + replace = rand_below(afl, 256); + + } + + out_buf[afl->stage_cur_byte] = replace; + + before_skip_inf = afl->queued_items; + + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + + out_buf[afl->stage_cur_byte] = orig; + + if (fuzz_nearby) { + + if (prev_cksum == + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST)) { + + non_eff_bytes[afl->stage_cur_byte] = 1; + + } + + } + + if (afl->queued_items != before_skip_inf) { + + skip_eff_map[afl->stage_cur_byte] = 1; + afl->queue_cur->skipdet_e->quick_eff_bytes += 1; + + if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; } + + if (afl->stage_max == MAXIMUM_QUICK_EFF_EXECS && repeat_eff) + eff_round_continue = 1; + + } + + done_inf_map[afl->stage_cur_byte] = 1; + + } + + afl->stage_cur = 0; + done_eff = 1; + + if (++eff_round_done >= 8) break; + + } while (eff_round_continue); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_QUICK] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_QUICK] += (afl->fsrv.total_execs - before_eff_execs); + +cleanup_skipdet: + + if (fuzz_nearby) { + + u8 *nearby_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + u32 i = 3; + while (i < len) { + + // assume DWORD size, from i - 3 -> i + 3 + if (skip_eff_map[i]) { + + u32 fill_length = (i + 3 < len) ? 7 : len - i + 2; + memset(nearby_bytes + i - 3, 1, fill_length); + i += 3; + + } else + + i += 1; + + } + + for (i = 0; i < len; i++) { + + if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1; + + } + + ck_free(nearby_bytes); + ck_free(non_eff_bytes); + + } + + if (done_eff) { + + afl->queue_cur->skipdet_e->continue_inf = 0; + afl->queue_cur->skipdet_e->done_eff = 1; + + } else { + + afl->queue_cur->skipdet_e->continue_inf = 1; + + } + + return 1; + +} + diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 7d6fdfb9..6cf580ce 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_update_freq = 1; afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000; afl->stats_avg_exec = 0; - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; afl->sync_time = SYNC_TIME; afl->cmplog_lvl = 2; afl->min_length = 1; @@ -140,6 +140,14 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->fsrv.child_pid = -1; afl->fsrv.out_dir_fd = -1; + /* Init SkipDet */ + afl->skipdet_g = + (struct skipdet_global *)ck_alloc(sizeof(struct skipdet_global)); + afl->skipdet_g->inf_prof = + (struct inf_profile *)ck_alloc(sizeof(struct inf_profile)); + afl->havoc_prof = + (struct havoc_profile *)ck_alloc(sizeof(struct havoc_profile)); + init_mopt_globals(afl); list_append(&afl_states, afl); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index deb28b7a..4b83ad29 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -502,6 +502,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) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8cf6c735..7db1aeb3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -955,14 +955,14 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'D': /* enforce deterministic */ + case 'D': /* no deterministic */ - afl->skip_deterministic = 0; + afl->skip_deterministic = 1; break; - case 'd': /* skip deterministic */ + case 'd': /* partial deterministic */ - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; break; case 'B': /* load bitmap */ @@ -3031,6 +3031,11 @@ stop_fuzzing: if (frida_afl_preload) { ck_free(frida_afl_preload); } fclose(afl->fsrv.plot_file); + + #ifdef INTROSPECTION + fclose(afl->fsrv.det_plot_file); + #endif + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); -- cgit 1.4.1 From ed1a6f8a570c6fcabee962f402d8d58f6cea77b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 11:01:31 +0100 Subject: 2024 v4.10c release --- GNUmakefile.gcc_plugin | 2 +- README.md | 4 ++-- afl-cmin.bash | 2 +- afl-whatsup | 2 +- docs/Changelog.md | 3 +-- frida_mode/Scripting.md | 2 +- frida_mode/test/cmplog/cmplog.c | 2 +- frida_mode/test/deferred/testinstr.c | 2 +- frida_mode/test/dynamic/testinstr.c | 2 +- frida_mode/test/entry_point/testinstr.c | 2 +- frida_mode/test/exe/testinstr.c | 2 +- frida_mode/test/js/test.c | 2 +- frida_mode/test/js/test2.c | 2 +- frida_mode/test/output/testinstr.c | 2 +- frida_mode/test/perf/perf.c | 2 +- frida_mode/test/persistent_ret/testinstr.c | 2 +- frida_mode/test/testinstr/testinstr.c | 2 +- frida_mode/test/unstable/unstable.c | 2 +- frida_mode/util/frida_get_symbol_addr.sh | 2 +- include/afl-as.h | 2 +- include/afl-fuzz.h | 2 +- include/afl-prealloc.h | 2 +- include/alloc-inl.h | 2 +- include/cmplog.h | 2 +- include/common.h | 2 +- include/config.h | 4 ++-- include/debug.h | 2 +- include/forkserver.h | 2 +- include/hash.h | 2 +- include/list.h | 2 +- include/sharedmem.h | 2 +- include/snapshot-inl.h | 2 +- include/types.h | 2 +- include/xxhash.h | 2 +- instrumentation/afl-compiler-rt.o.c | 2 +- instrumentation/afl-gcc-cmplog-pass.so.cc | 2 +- instrumentation/afl-gcc-cmptrs-pass.so.cc | 2 +- instrumentation/afl-gcc-common.h | 2 +- instrumentation/afl-gcc-pass.so.cc | 2 +- instrumentation/afl-llvm-dict2file.so.cc | 2 +- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +- instrumentation/afl-llvm-pass.so.cc | 2 +- instrumentation/cmplog-instructions-pass.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 2 +- instrumentation/cmplog-switches-pass.cc | 2 +- instrumentation/injection-pass.cc | 2 +- qemu_mode/build_qemu_support.sh | 2 +- qemu_mode/fastexit/Makefile | 2 +- qemu_mode/libcompcov/Makefile | 2 +- qemu_mode/libcompcov/compcovtest.cc | 2 +- qemu_mode/libcompcov/libcompcov.so.c | 2 +- qemu_mode/libqasan/Makefile | 2 +- qemu_mode/libqasan/hooks.c | 2 +- qemu_mode/libqasan/libqasan.c | 2 +- qemu_mode/libqasan/libqasan.h | 2 +- qemu_mode/libqasan/malloc.c | 2 +- qemu_mode/libqasan/patch.c | 2 +- qemu_mode/libqasan/string.c | 2 +- qemu_mode/libqasan/uninstrument.c | 2 +- qemu_mode/unsigaction/Makefile | 2 +- qemu_mode/util/qemu_get_symbol_addr.sh | 2 +- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 2 +- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- test-instr.c | 2 +- unicorn_mode/build_unicorn_support.sh | 2 +- utils/afl_network_proxy/afl-network-client.c | 2 +- utils/afl_network_proxy/afl-network-server.c | 2 +- utils/afl_proxy/afl-proxy.c | 2 +- utils/afl_untracer/afl-untracer.c | 2 +- utils/afl_untracer/libtestinstr.c | 2 +- utils/argv_fuzzing/Makefile | 2 +- utils/argv_fuzzing/argvfuzz.c | 2 +- utils/distributed_fuzzing/sync_script.sh | 2 +- utils/libdislocator/libdislocator.so.c | 2 +- utils/libtokencap/libtokencap.so.c | 2 +- utils/persistent_mode/test-instr.c | 2 +- 97 files changed, 99 insertions(+), 100 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index 16c98399..8f06792d 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -11,7 +11,7 @@ # from Laszlo Szekeres. # # Copyright 2015 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. diff --git a/README.md b/README.md index fd48cb14..f713e971 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.09c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.10a +GitHub version: 4.10c Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/afl-cmin.bash b/afl-cmin.bash index fda48fb4..6c271220 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -7,7 +7,7 @@ # # Copyright 2014, 2015 Google Inc. All rights reserved. # -# Copyright 2019-2023 AFLplusplus +# Copyright 2019-2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/afl-whatsup b/afl-whatsup index 5b7cbcd6..aa081e41 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2015 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. diff --git a/docs/Changelog.md b/docs/Changelog.md index 29081549..48003f4b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,7 +3,7 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. -### Version ++4.10a (dev) +### Version ++4.10c (release) - afl-fuzz: - default power schedule is now EXPLORE, due a fix in fast schedules explore is slightly better now. @@ -34,7 +34,6 @@ - updated the custom grammar mutator - document afl-cmin does not work on macOS (but afl-cmin.bash does) - ### Version ++4.09c (release) - afl-fuzz: - fixed the new mutation implementation for two bugs diff --git a/frida_mode/Scripting.md b/frida_mode/Scripting.md index dfd09e7b..653687f0 100644 --- a/frida_mode/Scripting.md +++ b/frida_mode/Scripting.md @@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code... -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c index 2565b35c..d397f36e 100644 --- a/frida_mode/test/cmplog/cmplog.c +++ b/frida_mode/test/cmplog/cmplog.c @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2023 Google LLC +// Copyright 2019-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index 0ab44582..4e5124ed 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/dynamic/testinstr.c b/frida_mode/test/dynamic/testinstr.c index 8b285f6d..0abc61fd 100644 --- a/frida_mode/test/dynamic/testinstr.c +++ b/frida_mode/test/dynamic/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index 24d9a615..75e71bda 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/exe/testinstr.c +++ b/frida_mode/test/exe/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c index 87c9cdf6..9799bf3b 100644 --- a/frida_mode/test/js/test.c +++ b/frida_mode/test/js/test.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c index 6b680a24..60b30eb5 100644 --- a/frida_mode/test/js/test2.c +++ b/frida_mode/test/js/test2.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/output/testinstr.c +++ b/frida_mode/test/output/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/perf/perf.c b/frida_mode/test/perf/perf.c index d9626974..55efba26 100644 --- a/frida_mode/test/perf/perf.c +++ b/frida_mode/test/perf/perf.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index 12365ceb..85aa2b80 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/testinstr/testinstr.c +++ b/frida_mode/test/testinstr/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index a87b6c74..16978e7e 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/frida_mode/util/frida_get_symbol_addr.sh b/frida_mode/util/frida_get_symbol_addr.sh index 2e682255..53d5b802 100755 --- a/frida_mode/util/frida_get_symbol_addr.sh +++ b/frida_mode/util/frida_get_symbol_addr.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023 AFLplusplus +# Copyright 2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/include/afl-as.h b/include/afl-as.h index 486314e2..612f34f4 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c2b09b2e..c24f39e2 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index d19a7b52..3c621d79 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index cff808b2..0aa417be 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/cmplog.h b/include/cmplog.h index e4821444..6bfc146b 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/include/common.h b/include/common.h index a9739a7d..0df07dee 100644 --- a/include/common.h +++ b/include/common.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/config.h b/include/config.h index 7ad73c2f..9349828f 100644 --- a/include/config.h +++ b/include/config.h @@ -10,7 +10,7 @@ Heiko Eissfeldt , 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. @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.10a" +#define VERSION "++4.10c" /****************************************************** * * diff --git a/include/debug.h b/include/debug.h index 234d8fc4..4b812f8e 100644 --- a/include/debug.h +++ b/include/debug.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/forkserver.h b/include/forkserver.h index f1d3b5b1..be7f9e8d 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -12,7 +12,7 @@ Dominik Maier > 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. diff --git a/include/hash.h b/include/hash.h index 0243c5b7..5d56a108 100644 --- a/include/hash.h +++ b/include/hash.h @@ -15,7 +15,7 @@ Other code written by Michal Zalewski Copyright 2016 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. diff --git a/include/list.h b/include/list.h index 283bf035..441eccd3 100644 --- a/include/list.h +++ b/include/list.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/sharedmem.h b/include/sharedmem.h index d32bd845..4484066e 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h index 3864e473..b2c81402 100644 --- a/include/snapshot-inl.h +++ b/include/snapshot-inl.h @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/include/types.h b/include/types.h index d6476d82..22332135 100644 --- a/include/types.h +++ b/include/types.h @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/include/xxhash.h b/include/xxhash.h index a8bd6f27..9a880470 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2023 Yann Collet + * Copyright (C) 2012-2024 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 8e55d6a0..caa3c3a8 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -3,7 +3,7 @@ ------------------------------------------------ Copyright 2015, 2016 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. diff --git a/instrumentation/afl-gcc-cmplog-pass.so.cc b/instrumentation/afl-gcc-cmplog-pass.so.cc index b4e6fda9..774dd5fd 100644 --- a/instrumentation/afl-gcc-cmplog-pass.so.cc +++ b/instrumentation/afl-gcc-cmplog-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog pass by Andrea Fioraldi , and diff --git a/instrumentation/afl-gcc-cmptrs-pass.so.cc b/instrumentation/afl-gcc-cmptrs-pass.so.cc index c56263dd..929a9d7a 100644 --- a/instrumentation/afl-gcc-cmptrs-pass.so.cc +++ b/instrumentation/afl-gcc-cmptrs-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog Routines pass by Andrea Fioraldi diff --git a/instrumentation/afl-gcc-common.h b/instrumentation/afl-gcc-common.h index 1d5eb466..80ded57d 100644 --- a/instrumentation/afl-gcc-common.h +++ b/instrumentation/afl-gcc-common.h @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ GCC plugin. diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc index 4d7fd0ef..41b1e5af 100644 --- a/instrumentation/afl-gcc-pass.so.cc +++ b/instrumentation/afl-gcc-pass.so.cc @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL LLVM pass by Laszlo Szekeres and Michal diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index c60f3e06..ac497b5b 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -4,7 +4,7 @@ Written by Marc Heuse - 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. diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 61f97d77..e0899cd3 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -9,7 +9,7 @@ from afl-as.c are Michal's fault. Copyright 2015, 2016 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. diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 052488a9..62f5023d 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -12,7 +12,7 @@ NGRAM previous location coverage comes from Adrian Herrera. Copyright 2015, 2016 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. diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 8be8c294..dc60221e 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 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. diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index b27e06e0..78317d5d 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 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. diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 01da6da7..3e05c13d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 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. diff --git a/instrumentation/injection-pass.cc b/instrumentation/injection-pass.cc index 971b103b..2280208b 100644 --- a/instrumentation/injection-pass.cc +++ b/instrumentation/injection-pass.cc @@ -5,7 +5,7 @@ Written by Marc Heuse Copyright 2015, 2016 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. diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 3f8a88f2..45019cc8 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -13,7 +13,7 @@ # counters by Andrea Fioraldi # # Copyright 2015, 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. diff --git a/qemu_mode/fastexit/Makefile b/qemu_mode/fastexit/Makefile index c7b79277..be80207d 100644 --- a/qemu_mode/fastexit/Makefile +++ b/qemu_mode/fastexit/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. 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. diff --git a/qemu_mode/libcompcov/Makefile b/qemu_mode/libcompcov/Makefile index 7260df87..4761ac02 100644 --- a/qemu_mode/libcompcov/Makefile +++ b/qemu_mode/libcompcov/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. 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. diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc index 23215013..11797091 100644 --- a/qemu_mode/libcompcov/compcovtest.cc +++ b/qemu_mode/libcompcov/compcovtest.cc @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2023 Google LLC +// Copyright 2019-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index b57e9701..36f7b2e2 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -5,7 +5,7 @@ Written and maintained by Andrea Fioraldi - 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. diff --git a/qemu_mode/libqasan/Makefile b/qemu_mode/libqasan/Makefile index 61782894..7366d6f6 100644 --- a/qemu_mode/libqasan/Makefile +++ b/qemu_mode/libqasan/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. 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. diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index a9fd0ce9..cf1b0820 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.c b/qemu_mode/libqasan/libqasan.c index 12be7778..45f47d5a 100644 --- a/qemu_mode/libqasan/libqasan.c +++ b/qemu_mode/libqasan/libqasan.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.h b/qemu_mode/libqasan/libqasan.h index a430c868..f0844e23 100644 --- a/qemu_mode/libqasan/libqasan.h +++ b/qemu_mode/libqasan/libqasan.h @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/malloc.c b/qemu_mode/libqasan/malloc.c index 4448f480..ae470b56 100644 --- a/qemu_mode/libqasan/malloc.c +++ b/qemu_mode/libqasan/malloc.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/patch.c b/qemu_mode/libqasan/patch.c index 38e0903b..4ce8c3d8 100644 --- a/qemu_mode/libqasan/patch.c +++ b/qemu_mode/libqasan/patch.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/string.c b/qemu_mode/libqasan/string.c index e17cff4b..cd14d57b 100644 --- a/qemu_mode/libqasan/string.c +++ b/qemu_mode/libqasan/string.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/uninstrument.c b/qemu_mode/libqasan/uninstrument.c index e37a9b46..996f2a74 100644 --- a/qemu_mode/libqasan/uninstrument.c +++ b/qemu_mode/libqasan/uninstrument.c @@ -7,7 +7,7 @@ for some strange reason. */ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile index c1a7397f..d5e807d8 100644 --- a/qemu_mode/unsigaction/Makefile +++ b/qemu_mode/unsigaction/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. 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. diff --git a/qemu_mode/util/qemu_get_symbol_addr.sh b/qemu_mode/util/qemu_get_symbol_addr.sh index e0a7ae80..5e00f1b2 100755 --- a/qemu_mode/util/qemu_get_symbol_addr.sh +++ b/qemu_mode/util/qemu_get_symbol_addr.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023 AFLplusplus +# Copyright 2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 5b122741..95f32fee 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-as.c b/src/afl-as.c index 772e31b3..09ba75bf 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-cc.c b/src/afl-cc.c index 98310545..e9564277 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 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. diff --git a/src/afl-common.c b/src/afl-common.c index ba498b3b..87003b03 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ded0c21d..0a77d61c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ 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. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5f67347c..d056ac9f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 3e6432ca..21f34e12 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 905431d1..3b1d13f1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 057d8cf5..76291cc4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 17fb9368..ae4d6668 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c163a420..d9c074ec 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 4c7da774..16a398fd 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 67931bba..1ea50418 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. You may obtain a copy of the License at: diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9e9b3822..eead7a8b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 1ee8ebe7..d764952c 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier 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. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b647ac84..4467cae8 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4b83ad29..76577081 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 69064d51..12d67fe7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 4f851099..7aee2985 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 7ce5de41..513c1ae9 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi Dominik Maier - 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. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index a2c81586..daea8f46 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi 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. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 7a639cf6..20ba5a5e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e7442d1d..4e5dab41 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/test-instr.c b/test-instr.c index eda5189c..28552893 100644 --- a/test-instr.c +++ b/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index d3d16ad5..baca2171 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -14,7 +14,7 @@ # # # Copyright 2017 Battelle Memorial Institute. 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. diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index 0416f0f9..1f04dd87 100644 --- a/utils/afl_network_proxy/afl-network-client.c +++ b/utils/afl_network_proxy/afl-network-client.c @@ -4,7 +4,7 @@ Written by Marc Heuse - 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. diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 95b0a551..c4a700f4 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -12,7 +12,7 @@ Dominik Maier 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. diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index 531a97a2..6cf47636 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -4,7 +4,7 @@ Written by Marc Heuse - 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. diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index 0e3f8a45..e6a74518 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -4,7 +4,7 @@ Written by Marc Heuse - 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. diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index b7afc325..0a98778a 100644 --- a/utils/afl_untracer/libtestinstr.c +++ b/utils/afl_untracer/libtestinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 6786467a..ba977e5f 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -2,7 +2,7 @@ # american fuzzy lop++ - argvfuzz # -------------------------------- # -# Copyright 2019-2023 Kjell Braden +# Copyright 2019-2024 Kjell Braden # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c index 41eead0c..47383138 100644 --- a/utils/argv_fuzzing/argvfuzz.c +++ b/utils/argv_fuzzing/argvfuzz.c @@ -2,7 +2,7 @@ american fuzzy lop++ - LD_PRELOAD for fuzzing argv in binaries ------------------------------------------------------------ - Copyright 2019-2023 Kjell Braden + Copyright 2019-2024 Kjell Braden Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index b22816f1..861b65c8 100755 --- a/utils/distributed_fuzzing/sync_script.sh +++ b/utils/distributed_fuzzing/sync_script.sh @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2014 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. diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index 1cd7abc6..b80be1a1 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 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. diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index f4024799..cc499150 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 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. diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 4ead6577..72e26e93 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 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. You may obtain a copy of the License at: -- cgit 1.4.1 From 023fc19ce04bffcbd623e27a1f2d1810c3ec0c3c Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Mon, 5 Feb 2024 18:26:46 +0100 Subject: better replay mode error handling, added replay mode documentation, code formatting --- include/afl-fuzz.h | 2 +- include/config.h | 10 +- include/persistent_replay.h | 152 +++++++++++++++++++--------- instrumentation/README.persistent_mode.md | 30 +++++- instrumentation/afl-compiler-rt.o.c | 58 ++++++----- src/afl-forkserver.c | 5 +- utils/persistent_mode/persistent_demo_new.c | 6 +- 7 files changed, 182 insertions(+), 81 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 864bc6b6..f95dcc20 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -125,7 +125,7 @@ #endif /* ^!SIMPLE_FILES */ #ifdef AFL_PERSISTENT_RECORD - #define RECORD_PREFIX "RECORD:" + #define RECORD_PREFIX "RECORD:" #endif #define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */ diff --git a/include/config.h b/include/config.h index 1649f110..d44cda9c 100644 --- a/include/config.h +++ b/include/config.h @@ -83,10 +83,14 @@ will be kept and written to the crash/ directory as RECORD:... files. Note that every crash will be written, not only unique ones! */ -// #define AFL_PERSISTENT_RECORD +#define AFL_PERSISTENT_RECORD -/* Builds compiler-rt with support to replay persistent records */ -// #define AFL_PERSISTENT_REPLAY +/* Adds support in compiler-rt to replay persistent records */ +#define AFL_PERSISTENT_REPLAY + +/* Adds support in compiler-rt to replay persistent records in @@-style + * harnesses */ +// #define AFL_PERSISTENT_REPLAY_ARGPARSE /* console output colors: There are three ways to configure its behavior * 1. default: colored outputs fixed on: defined USE_COLOR && defined diff --git a/include/persistent_replay.h b/include/persistent_replay.h index b1a55e9f..58b22fb4 100644 --- a/include/persistent_replay.h +++ b/include/persistent_replay.h @@ -11,71 +11,116 @@ #include static unsigned short int is_replay_record; -static unsigned int replay_record; -static unsigned int replay_record_cnt; -static char replay_record_path[PATH_MAX]; -static char **record_arg; -static char *replay_record_dir; -static struct dirent **record_list; +static unsigned int replay_record; +static unsigned int replay_record_cnt; +static char replay_record_path[PATH_MAX]; +static char *replay_record_dir; +static struct dirent **record_list; + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE +static char **record_arg = NULL; +#endif // AFL_PERSISTENT_REPLAY_ARGPARSE static int select_files(const struct dirent *dirbuf) { char fn[4096]; - if (dirbuf->d_name[0] == '.'){ + if (dirbuf->d_name[0] == '.') { + return 0; + } else { + snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record); return !!strstr(dirbuf->d_name, fn); + } + } - + static int compare_files(const struct dirent **da, const struct dirent **db) { - - unsigned int c1=0, c2=0; + + unsigned int c1 = 0, c2 = 0; sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1); sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2); - return c1-c2; + return c1 - c2; + } -__attribute__((destructor)) static void __afl_record_replay_destroy(void){ - for (int i=0; i < replay_record_cnt; i++) { +__attribute__((destructor)) static void __afl_record_replay_destroy(void) { + + for (int i = 0; i < replay_record_cnt; i++) { + free(record_list[i]); + } + free(record_list); + } -__attribute__((constructor)) static void __afl_record_replay_init(int argc, char **argv) { - +__attribute__((constructor)) static void __afl_record_replay_init( +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + int argc, char **argv +#endif // AFL_PERSISTENT_REPLAY_ARGPARSE +) { + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE char **argp; +#endif // AFL_PERSISTENT_REPLAY_ARGPARSE + + struct stat sb; + + /* caveat: if harness uses @@ and we don't pass it, it will regardless loop + * the number of iterations defined for AFL_LOOP (on the same file)*/ + if (!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))) { - /* caveat: if harness uses @@ and we don't pass it, it will regardless loop the number of iterations defined for AFL_LOOP (on the same file)*/ - if(!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))){ // printf("[warning] AFL_PERSISTENT_REPLAY not set.\n"); return; + } replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY")); replay_record_dir = getenv("AFL_PERSISTENT_DIR"); - replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./", &record_list, select_files, compare_files); - if (!replay_record_cnt){ - printf("[error] Can't find the requested record!\n"); + if (!(stat(replay_record_dir, &sb) == 0 && S_ISDIR(sb.st_mode))) { + + fprintf(stderr, "[error] Can't find the requested record directory!\n"); is_replay_record = 0; + return; + } + replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./", + &record_list, select_files, compare_files); + + if (!replay_record_cnt) { + + fprintf(stderr, "[error] Can't find the requested record!\n"); + is_replay_record = 0; + + } + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE argp = argv; - while (*argp){ - if (!strcmp(*argp, "@@")){ + while (*argp) { + + if (!strcmp(*argp, "@@")) { + record_arg = argp; *record_arg = replay_record_path; break; + } + ++argp; + } +#endif // AFL_PERSISTENT_REPLAY_ARGPARSE + } /* only used if explictly included for compatibility @@ -83,67 +128,80 @@ __attribute__((constructor)) static void __afl_record_replay_init(int argc, char #ifdef AFL_COMPAT -#ifndef PATH_MAX - #define PATH_MAX 4096 -#endif + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif -#define FUZZ_BUF_SIZE 1024000 + #define FUZZ_BUF_SIZE 1024000 -// extern ssize_t read(int fildes, void *buf, size_t nbyte); + // extern ssize_t read(int fildes, void *buf, size_t nbyte); -//extern int __afl_persistent_loop(unsigned int max_cnt); -//extern unsigned char fuzz_buf[]; + // extern int __afl_persistent_loop(unsigned int max_cnt); + // extern unsigned char fuzz_buf[]; -#ifndef __AFL_HAVE_MANUAL_CONTROL - #define __AFL_HAVE_MANUAL_CONTROL -#endif + #ifndef __AFL_HAVE_MANUAL_CONTROL + #define __AFL_HAVE_MANUAL_CONTROL + #endif -#define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE)) -#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf -#define __AFL_FUZZ_INIT() void sync(void); -#define __AFL_INIT() sync() -#define __AFL_LOOP(x) __afl_persistent_loop(x) + #define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE)) + #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf + #define __AFL_FUZZ_INIT() void sync(void); + #define __AFL_INIT() sync() + #define __AFL_LOOP(x) __afl_persistent_loop(x) unsigned char fuzz_buf[FUZZ_BUF_SIZE]; int __afl_persistent_loop(unsigned int max_cnt) { - static unsigned int cycle_cnt = 1; + static unsigned int cycle_cnt = 1; static unsigned short int inited = 0; - char tcase[PATH_MAX]; + char tcase[PATH_MAX]; + + if (is_replay_record) { - if( is_replay_record ){ + if (!inited) { - if (!inited){ cycle_cnt = replay_record_cnt; inited = 1; + } snprintf(tcase, PATH_MAX, "%s/%s", - replay_record_dir ? replay_record_dir : "./", - record_list[replay_record_cnt-cycle_cnt]->d_name); - + replay_record_dir ? replay_record_dir : "./", + record_list[replay_record_cnt - cycle_cnt]->d_name); + #ifdef AFL_PERSISTENT_REPLAY_ARGPARSE if (record_arg) { + *record_arg = tcase; - } else { + + } else + + #endif // AFL_PERSISTENT_REPLAY_ARGPARSE + { + int fd = open(tcase, O_RDONLY); dup2(fd, 0); close(fd); + } } else { - if (!inited){ + if (!inited) { + cycle_cnt = max_cnt; inited = 1; + } } return cycle_cnt--; + } #endif // AFL_COMPAT -#endif // _HAVE_PERSISTENT_REPLAY_H \ No newline at end of file +#endif // _HAVE_PERSISTENT_REPLAY_H + diff --git a/instrumentation/README.persistent_mode.md b/instrumentation/README.persistent_mode.md index 14e59f4a..b5d982b0 100644 --- a/instrumentation/README.persistent_mode.md +++ b/instrumentation/README.persistent_mode.md @@ -195,4 +195,32 @@ Then as first line after the `__AFL_LOOP` while loop: int len = __AFL_FUZZ_TESTCASE_LEN; ``` -And that is all! \ No newline at end of file +And that is all! + +## 6) Persistent record, and replay + +If your software under test requires keeping a state between persistent loop iterations (i.e., a stateful network stack), you can use the `AFL_PERSISTENT_RECORD` variable as described in the [environment variables documentation](../docs/env_variables.md). + +To easily replay a crashing, or hanging record, you can use the persistent replay functionality by compiling AFL++ after uncommenting the `AFL_PERSISTENT_REPLAY` define in [config.h](../include/config.h). + +You can then run the test binary specifying the record number via the AFL_PERSISTENT_REPLAY environment variable (i.e., `RECORD:XXXXX`` -> `AFL_PERSISTENT_REPLAY=XXXXX`). +The directory where the record files live can be specified via the `AFL_PERSISTENT_DIR` environment varilable, otherwise by default it will be considered the current directory (`./`). + +If your harness reads the input files from arguments using the special `@@` argument you will need to define `AFL_PERSISTENT_ARGPARSE` in `config.h`, or before including the `persistent_replay.h` header file as show before. +In order to offer transparent support to harnesses using the `@@` command line argument, arguments are parsed by the `__afl_record_replay_init` init function. Since not all systems support passing arguments to initializers, this functionality is disabled by default, it's recommendable to use the `__AFL_FUZZ_TESTCASE_BUF/__AFL_FUZZ_TESTCASE_LEN` shared memory mechanism instead. + +### 7) Drop in replay functionality + +To use the replay functionality without having to use `afl-cc` you can just define `AFL_COMPAT` and include the [include/persistent_replay.h](../include/persistent_replay.h) self contained header file that provides a drop-in replacement for the persistent loop mechanism. + +```c +#ifndef __AFL_FUZZ_TESTCASE_LEN + #define AFL_COMPAT + // #define AFL_PERSISTENT_REPLAY_ARGPARSE + #include "persistent_replay.h" +#endif + +__AFL_FUZZ_INIT(); +``` + +A simple example is provided in [persistent_demo_new.c](../utils/persistent_mode/persistent_demo_new.c). \ No newline at end of file diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 0fa22aee..037caaf0 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -84,7 +84,7 @@ #include #ifdef AFL_PERSISTENT_REPLAY -#include "persistent_replay.h" + #include "persistent_replay.h" #endif /* Globals needed by the injected instrumentation. The __afl_area_initial region @@ -1344,37 +1344,49 @@ int __afl_persistent_loop(unsigned int max_cnt) { #ifdef AFL_PERSISTENT_REPLAY -#ifndef PATH_MAX - #define PATH_MAX 4096 -#endif + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif - static u8 inited = 0; - char tcase[PATH_MAX]; + static u8 inited = 0; + char tcase[PATH_MAX]; - if( unlikely(is_replay_record) ){ + if (unlikely(is_replay_record)) { - if (!inited){ - cycle_cnt = replay_record_cnt; - inited = 1; - } + if (!inited) { - snprintf(tcase, PATH_MAX, "%s/%s", - replay_record_dir ? replay_record_dir : "./", - record_list[replay_record_cnt-cycle_cnt]->d_name); + cycle_cnt = replay_record_cnt; + inited = 1; + + } + + snprintf(tcase, PATH_MAX, "%s/%s", + replay_record_dir ? replay_record_dir : "./", + record_list[replay_record_cnt - cycle_cnt]->d_name); + + #ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + if (record_arg) { + + *record_arg = tcase; + + } else + + #endif // AFL_PERSISTENT_REPLAY_ARGPARSE + { + + int fd = open(tcase, O_RDONLY); + dup2(fd, 0); + close(fd); + + } - if (record_arg) { - *record_arg = tcase; - } else { - int fd = open(tcase, O_RDONLY); - dup2(fd, 0); - close(fd); - } return cycle_cnt--; + } else -#endif +#endif - if (first_pass) { + if (first_pass) { /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate. On subsequent calls, the parent will take care of that, but on the first diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index f8dd783f..36e46444 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1593,7 +1593,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, #ifdef AFL_PERSISTENT_RECORD fsrv_run_result_t retval = FSRV_RUN_OK; - char *persistent_out_fmt; + char *persistent_out_fmt; #endif #ifdef __linux__ @@ -1803,6 +1803,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; goto store_persistent_record; #endif + } /* Did we crash? @@ -1841,7 +1842,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, #ifdef AFL_PERSISTENT_RECORD store_persistent_record: - if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && + if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && unlikely(fsrv->persistent_record)) { char fn[PATH_MAX]; diff --git a/utils/persistent_mode/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c index 40ada9e1..3d9d90a6 100644 --- a/utils/persistent_mode/persistent_demo_new.c +++ b/utils/persistent_mode/persistent_demo_new.c @@ -31,8 +31,8 @@ /* this lets the source compile without afl-clang-fast/lto */ #ifndef __AFL_FUZZ_TESTCASE_LEN -#define AFL_COMPAT -#include "persistent_replay.h" + #define AFL_COMPAT + #include "persistent_replay.h" #endif __AFL_FUZZ_INIT(); @@ -86,8 +86,6 @@ int main(int argc, char **argv) { if (buf[5] == '!') { printf("six\n"); - char *nullo = NULL+1; - *nullo = 'p'; abort(); } -- cgit 1.4.1 From 48a862c503483f64db713fd6a0392148b5584ca4 Mon Sep 17 00:00:00 2001 From: Cornelius Aschermann Date: Wed, 13 Mar 2024 11:43:58 -0700 Subject: :Adds stats tracking time spend in calibration/trim/sync This currently does not affect statsd nor the UI. Only the fuzzer_stats file is updated --- include/afl-fuzz.h | 10 +++- src/afl-fuzz-run.c | 26 ++++++++--- src/afl-fuzz-stats.c | 128 +++++++++++++++++++++++++++++---------------------- src/afl-fuzz.c | 1 - 4 files changed, 100 insertions(+), 65 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index be86910e..91eb6887 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -648,7 +648,10 @@ typedef struct afl_state { longest_find_time, /* Longest time taken for a find */ exit_on_time, /* Delay to exit if no new paths */ sync_time, /* Sync time (ms) */ - switch_fuzz_mode; /* auto or fixed fuzz mode */ + switch_fuzz_mode, /* auto or fixed fuzz mode */ + calibration_time_us, /* Time spend on calibration */ + sync_time_us, /* Time spend on sync */ + trim_time_us; /* Time spend on trimming */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ subseq_tmouts; /* Number of timeouts in a row */ @@ -1215,6 +1218,10 @@ void show_stats_normal(afl_state_t *); void show_stats_pizza(afl_state_t *); void show_init_stats(afl_state_t *); +void update_calibration_time(afl_state_t *afl, u64* time); +void update_trim_time(afl_state_t *afl, u64* time); +void update_sync_time(afl_state_t *afl, u64* time); + /* StatsD */ void statsd_setup_format(afl_state_t *afl); @@ -1402,4 +1409,3 @@ void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem); #endif #endif - diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index d764952c..82cdeb81 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u32 use_tmout = afl->fsrv.exec_tmout; u8 *old_sn = afl->stage_name; + u64 calibration_start_us = get_cur_time_us(); if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; } /* Be a bit more generous about timeouts when resuming sessions, or when @@ -504,6 +505,9 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); + // update the time spend in calibration after each execution, as those may be slow + update_calibration_time(afl, &calibration_start_us); + /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, we want to bail out quickly. */ @@ -650,6 +654,7 @@ abort_calibration: if (!first_run) { show_stats(afl); } + update_calibration_time(afl, &calibration_start_us); return fault; } @@ -669,11 +674,15 @@ void sync_fuzzers(afl_state_t *afl) { afl->stage_max = afl->stage_cur = 0; afl->cur_depth = 0; + u64 sync_start_us = get_cur_time_us(); /* Look at the entries created for every other fuzzer in the sync directory. */ while ((sd_ent = readdir(sd))) { + // since sync can take substantial amounts of time, update time spend every iteration + update_sync_time(afl, &sync_start_us); + u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; u32 min_accept = 0, next_min_accept = 0; @@ -861,6 +870,9 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); + //add time in sync one last time + update_sync_time(afl, &sync_start_us); + afl->last_sync_time = get_cur_time(); afl->last_sync_cycle = afl->queue_cycle; @@ -872,8 +884,9 @@ void sync_fuzzers(afl_state_t *afl) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { + u8 needs_write = 0, fault = 0; u32 orig_len = q->len; - + u64 trim_start_us = get_cur_time_us(); /* Custom mutator trimmer */ if (afl->custom_mutators_count) { @@ -897,11 +910,10 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - if (custom_trimmed) return trimmed_case; + if (custom_trimmed) { fault = trimmed_case; goto abort_trimming; } } - u8 needs_write = 0, fault = 0; u32 trim_exec = 0; u32 remove_len; u32 len_p2; @@ -912,7 +924,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (unlikely(q->len < 5)) { return 0; } + if (unlikely(q->len < 5)) { fault = 0; goto abort_trimming; } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; @@ -946,6 +958,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + update_trim_time(afl, &trim_start_us); + 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? @@ -1039,8 +1053,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } abort_trimming: - afl->bytes_trim_out += q->len; + update_trim_time(afl, &trim_start_us); + return fault; } @@ -1104,4 +1119,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } - diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4f398863..b39c8299 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -133,6 +133,10 @@ 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) { @@ -175,65 +179,54 @@ 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!"); + } + + } + 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); + } + } + } if (afl->saved_crashes) { write_crash_readme(afl); } return; @@ -300,6 +293,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" @@ -345,6 +342,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), + (runtime - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000) / 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) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, @@ -414,7 +415,6 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fclose(f); rename(fn_tmp, fn_final); - } #ifdef INTROSPECTION @@ -2438,4 +2438,20 @@ void show_init_stats(afl_state_t *afl) { #undef IB } +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; +} diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 99491628..102809cd 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -3099,4 +3099,3 @@ stop_fuzzing: } #endif /* !AFL_LIB */ - -- cgit 1.4.1 From 40adc344136c954cdc58e62acb46708816f5870a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Apr 2024 09:24:19 +0200 Subject: fix -V, code format --- docs/Changelog.md | 2 ++ include/afl-fuzz.h | 13 +++---- src/afl-fuzz-run.c | 25 ++++++++++---- src/afl-fuzz-stats.c | 98 +++++++++++++++++++++++++++++++++++++++------------- src/afl-fuzz.c | 21 ++++++++--- 5 files changed, 117 insertions(+), 42 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index 72e20a18..116134ff 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -25,6 +25,8 @@ - fix for `-t xxx+` feature - -e extension option now saves the queue items, crashes, etc. with the extension too + - fixes for trimmming, correct -V time and reading stats on resume by eqv + thanks a lot! - afl-cc: - added collision free caller instrumentation to LTO mode. activate with `AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 91eb6887..c813ae7e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -5,9 +5,9 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , - Andrea Fioraldi , - Dominik Maier + Dominik Maier , + Andrea Fioraldi , and + Heiko Eissfeldt Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2024 AFLplusplus Project. All rights reserved. @@ -1218,9 +1218,9 @@ void show_stats_normal(afl_state_t *); void show_stats_pizza(afl_state_t *); void show_init_stats(afl_state_t *); -void update_calibration_time(afl_state_t *afl, u64* time); -void update_trim_time(afl_state_t *afl, u64* time); -void update_sync_time(afl_state_t *afl, u64* time); +void update_calibration_time(afl_state_t *afl, u64 *time); +void update_trim_time(afl_state_t *afl, u64 *time); +void update_sync_time(afl_state_t *afl, u64 *time); /* StatsD */ @@ -1409,3 +1409,4 @@ void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem); #endif #endif + diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 82cdeb81..1c6ce56a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -505,7 +505,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); - // update the time spend in calibration after each execution, as those may be slow + // update the time spend in calibration after each execution, as those may + // be slow update_calibration_time(afl, &calibration_start_us); /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, @@ -680,7 +681,8 @@ void sync_fuzzers(afl_state_t *afl) { while ((sd_ent = readdir(sd))) { - // since sync can take substantial amounts of time, update time spend every iteration + // since sync can take substantial amounts of time, update time spend every + // iteration update_sync_time(afl, &sync_start_us); u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; @@ -870,7 +872,7 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); - //add time in sync one last time + // add time in sync one last time update_sync_time(afl, &sync_start_us); afl->last_sync_time = get_cur_time(); @@ -910,7 +912,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - if (custom_trimmed) { fault = trimmed_case; goto abort_trimming; } + if (custom_trimmed) { + + fault = trimmed_case; + goto abort_trimming; + + } } @@ -924,7 +931,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (unlikely(q->len < 5)) { fault = 0; goto abort_trimming; } + if (unlikely(q->len < 5)) { + + fault = 0; + goto abort_trimming; + + } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; @@ -986,7 +998,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Let's save a clean trace, which will be needed by update_bitmap_score once we're done with the trimming stuff. */ - if (!needs_write) { needs_write = 1; @@ -1001,7 +1012,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } /* 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; @@ -1119,3 +1129,4 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } + diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index b39c8299..7e1a3b92 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -133,8 +133,10 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { } -static bool starts_with(char* key, char* line) { +static bool starts_with(char *key, char *line) { + return strncmp(key, line, strlen(key)) == 0; + } /* load some of the existing stats file when resuming.*/ @@ -179,25 +181,43 @@ void load_stats_file(afl_state_t *afl) { strcpy(keystring, lstartptr); lptr++; char *nptr; - if (starts_with("run_time", keystring)){ + if (starts_with("run_time", keystring)) { + afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); + } - if (starts_with("cycles_done", keystring)){ + + 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)){ + + if (starts_with("calibration_time", keystring)) { + afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("sync_time", keystring)){ + + if (starts_with("sync_time", keystring)) { + afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("trim_time", keystring)){ + + if (starts_with("trim_time", keystring)) { + afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("execs_done", keystring)){ + + 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); @@ -206,27 +226,46 @@ void load_stats_file(afl_state_t *afl) { WARNF( "queue/ has been modified -- things might not work, you're " "on your own!"); + sleep(3); } } - if (starts_with("corpus_found", keystring)){ + + if (starts_with("corpus_found", keystring)) { + afl->queued_discovered = strtoul(lptr, &nptr, 10); + } - if (starts_with("corpus_imported", keystring)){ + + 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); + } + } + } + if (afl->saved_crashes) { write_crash_readme(afl); } return; @@ -334,7 +373,7 @@ 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->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000, runtime / 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 @@ -342,11 +381,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), - (runtime - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000) / 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) / 1000), + (runtime - + (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / + 1000) / + 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) / 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, @@ -415,6 +456,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fclose(f); rename(fn_tmp, fn_final); + } #ifdef INTROSPECTION @@ -2438,20 +2480,28 @@ void show_init_stats(afl_state_t *afl) { #undef IB } -void update_calibration_time(afl_state_t *afl, u64* time){ - u64 cur = get_cur_time_us(); - afl->calibration_time_us += cur-*time; + +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; +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; +void update_sync_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->sync_time_us += cur - *time; *time = cur; + } + diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 102809cd..00d24ab1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -5,8 +5,9 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and - Andrea Fioraldi + Dominik Meier , + Andrea Fioraldi , and + Heiko Eissfeldt Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2024 AFLplusplus Project. All rights reserved. @@ -199,7 +200,8 @@ static void usage(u8 *argv0, int more_help) { "Test settings:\n" " -s seed - use a fixed seed for the RNG\n" - " -V seconds - fuzz for a specified time then terminate\n" + " -V seconds - fuzz for a specified time then terminate (fuzz time " + "only!)\n" " -E execs - fuzz for an approx. no. of total executions then " "terminate\n" " Note: not precise and can have several more " @@ -2543,8 +2545,6 @@ int main(int argc, char **argv_orig, char **envp) { } // (void)nice(-20); // does not improve the speed - // real start time, we reset, so this works correctly with -V - afl->start_time = get_cur_time(); #ifdef INTROSPECTION u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; @@ -2565,6 +2565,9 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Writing mutation introspection to '%s'", ifn); #endif + // real start time, we reset, so this works correctly with -V + afl->start_time = get_cur_time(); + while (likely(!afl->stop_soon)) { cull_queue(afl); @@ -2585,6 +2588,13 @@ int main(int argc, char **argv_orig, char **envp) { sync_fuzzers(afl); + if (!afl->queue_cycle && afl->afl_env.afl_import_first) { + + // real start time, we reset, so this works correctly with -V + afl->start_time = get_cur_time(); + + } + } ++afl->queue_cycle; @@ -3099,3 +3109,4 @@ stop_fuzzing: } #endif /* !AFL_LIB */ + -- cgit 1.4.1 From 26eaf53a832be0b12dadbbd290b4a7e676818347 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 2 May 2024 08:35:24 +0200 Subject: AFL_DISABLE_REDUNDANT --- docs/Changelog.md | 2 ++ docs/env_variables.md | 3 +++ include/afl-fuzz.h | 2 +- include/envs.h | 3 ++- src/afl-fuzz-init.c | 7 +++++-- src/afl-fuzz-queue.c | 1 + src/afl-fuzz-redqueen.c | 9 +++++---- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 1 + 9 files changed, 27 insertions(+), 8 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index c1b2f62a..5cb6973a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -5,6 +5,7 @@ ### Version ++4.21a (dev) * afl-fuzz + - added AFL_DISABLE_REDUNDANT for huge queues - fix AFL_PERSISTENT_RECORD - prevent filenames in the queue that have spaces - minor fix for FAST schedules @@ -13,6 +14,7 @@ - ensure shared memory variables are visible in weird build setups * afl-cmin - work with input files that have a space + * enhanced the ASAN configuration ### Version ++4.20c (release) diff --git a/docs/env_variables.md b/docs/env_variables.md index 1e4fc7ba..01904aea 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -381,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool: - Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is usually a bad idea! + - Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant. + This can be useful with huge queues. + - Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach new coverage diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c813ae7e..1a958006 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -452,7 +452,7 @@ typedef struct afl_env_vars { afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, - afl_final_sync, afl_ignore_seed_problems; + afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 56a4916c..c895f726 100644 --- a/include/envs.h +++ b/include/envs.h @@ -26,7 +26,8 @@ static char *afl_environment_variables[] = { "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", - "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM", + "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", + "AFL_DISABLE_REDUNDANT", "AFL_DISABLE_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 2d540eb1..b3fe9318 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -933,10 +933,13 @@ void perform_dry_run(afl_state_t *afl) { res = calibrate_case(afl, q, use_mem, 0, 1); /* For AFLFast schedules we update the queue entry */ - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) && likely(q->exec_cksum)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) && + likely(q->exec_cksum)) { + q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE; + } - + if (afl->stop_soon) { return; } if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index df4e7d79..5987ad0c 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -370,6 +370,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; + if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index cfa57c1d..9316da71 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2764,15 +2764,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, #ifdef _DEBUG u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; - fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, - hshape, h->attribute); + fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape, + h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]); - fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, - hshape, hh->attribute); + fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape, + hh->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]); fprintf(stderr, " o1="); @@ -3273,3 +3273,4 @@ exit_its: return r; } + diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index c21ae6be..543fdc1c 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -293,6 +293,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_cmplog_only_new = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_DISABLE_REDUNDANT", + + afl_environment_variable_len)) { + + afl->afl_env.afl_disable_redundant = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 00d24ab1..329ce942 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -264,6 +264,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n" "AFL_DEBUG: extra debugging output for Python mode trimming\n" "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n" + "AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\n" "AFL_DISABLE_TRIM: disable the trimming of test cases\n" "AFL_DUMB_FORKSRV: use fork server without feedback from target\n" "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n" -- cgit 1.4.1 From c03f2897d081b2bf41e179a48d758f1f400b5929 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Fri, 10 May 2024 16:55:32 -0400 Subject: Add `AFL_SHA1_FILENAMES` option --- docs/env_variables.md | 3 + include/afl-fuzz.h | 29 ++++- include/envs.h | 18 +-- src/afl-fuzz-bitmap.c | 91 +++++++++++---- src/afl-fuzz-init.c | 78 +++++++++---- src/afl-fuzz-queue.c | 5 +- src/afl-fuzz-state.c | 7 ++ src/afl-performance.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 479 insertions(+), 62 deletions(-) (limited to 'include/afl-fuzz.h') diff --git a/docs/env_variables.md b/docs/env_variables.md index 01904aea..b3519107 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -550,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool: use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments. + - `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash + of their contents, rather than use the standard `id:000000,...` names. + - `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested by some users for unorthodox parallelized fuzzing setups, but not advisable otherwise. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1a958006..5efe5144 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -452,7 +452,8 @@ typedef struct afl_env_vars { afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, - afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant; + afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant, + afl_sha1_filenames; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, @@ -1404,6 +1405,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in, void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem); +/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the + * result as a `\0`-terminated hex string, which the caller much `ck_free`. */ +char *sha1_hex(const u8 *data, size_t len); + +/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */ +char *sha1_hex_for_file(const char *fname, u32 len); + +/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is + * enabled. */ +static inline int permissive_create(afl_state_t *afl, const char *fn) { + + int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (unlikely(fd < 0)) { + + if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) { + + PFATAL("Unable to create '%s'", fn); + + } + + } + + return fd; + +} + #if TESTCASE_CACHE == 1 #error define of TESTCASE_CACHE must be zero or larger than 1 #endif diff --git a/include/envs.h b/include/envs.h index c895f726..57f4d263 100644 --- a/include/envs.h +++ b/include/envs.h @@ -108,15 +108,15 @@ static char *afl_environment_variables[] = { "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", - "AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", - "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", - "AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", - "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", - "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", - "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", - "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", - "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN", - "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL + "AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE", + "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", + "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT", + "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", + "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", + "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", + "AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", + "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", + "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL }; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5d4d80af..03bc5d6c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -527,12 +527,24 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - queue_fn = alloc_printf( - "%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, - describe_op(afl, new_bits + is_timeout, - NAME_MAX - strlen("id:000000,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + queue_fn = alloc_printf( + "%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, + describe_op(afl, new_bits + is_timeout, + NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + queue_fn = alloc_printf( + "%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -542,10 +554,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ - fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); } - ck_write(fd, mem, len, queue_fn); - close(fd); + fd = permissive_create(afl, queue_fn); + if (likely(fd >= 0)) { + + ck_write(fd, mem, len, queue_fn); + close(fd); + + } + add_to_queue(afl, queue_fn, len, 0); if (unlikely(afl->fuzz_mode) && @@ -743,11 +759,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir, - afl->saved_hangs, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir, + afl->saved_hangs, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -799,11 +827,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", - afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -873,10 +913,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* If we're here, we apparently want to save the crash or hang test case, too. */ - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); } - ck_write(fd, mem, len, fn); - close(fd); + fd = permissive_create(afl, fn); + if (fd >= 0) { + + ck_write(fd, mem, len, fn); + close(fd); + + } #ifdef __linux__ if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 01d0730d..7310e49f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1190,14 +1190,27 @@ void perform_dry_run(afl_state_t *afl) { #ifndef SIMPLE_FILES - snprintf( - crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", - afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op( - afl, 0, - NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), - use_name, afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf( + crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op( + afl, 0, + NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), + use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(use_mem, read_len); + snprintf( + crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -1518,10 +1531,23 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf( - "%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id, - afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + nfn = alloc_printf( + "%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id, + afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex_for_file(q->fname, q->len); + nfn = alloc_printf( + "%s/queue/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } u8 *pos = strrchr(nfn, '/'); no_spaces(pos + 30); @@ -1738,10 +1764,11 @@ double get_runnable_processes(void) { void nuke_resume_dir(afl_state_t *afl) { - u8 *fn; + u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX; + u8 *fn; fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir); @@ -1749,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state", afl->out_dir); @@ -1761,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/_resume", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); return; @@ -1778,8 +1805,9 @@ dir_cleanup_failed: static void handle_existing_out_dir(afl_state_t *afl) { - FILE *f; - u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); + u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX; + FILE *f; + u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); /* See if the output directory is locked. If yes, bail out. If not, create a lock that will persist for the lifetime of the process @@ -1901,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { /* Next, we need to clean up out_dir>/queue/.state/ subdirectories: */ fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir); @@ -1909,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* Then, get rid of the .state subdirectory itself (should be empty by now) @@ -1924,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/queue", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* All right, let's do out_dir>/crashes/id:* and @@ -1971,7 +1999,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { #ifdef AFL_PERSISTENT_RECORD delete_files(fn, RECORD_PREFIX); #endif - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/hangs", afl->out_dir); @@ -2006,7 +2034,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { #ifdef AFL_PERSISTENT_RECORD delete_files(fn, RECORD_PREFIX); #endif - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* And now, for some finishing touches. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 5987ad0c..2318df60 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -371,9 +371,8 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (fd < 0) { PFATAL("Unable to create '%s'", fn); } - close(fd); + fd = permissive_create(afl, fn); + if (fd >= 0) { close(fd); } } else { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 543fdc1c..74edaddf 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -626,6 +626,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } + } else if (!strncmp(env, "AFL_SHA1_FILENAMES", + + afl_environment_variable_len)) { + + afl->afl_env.afl_sha1_filenames = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } } else { diff --git a/src/afl-performance.c b/src/afl-performance.c index f730ca53..6c6e3c8b 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -95,3 +95,313 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { } +// Public domain SHA1 implementation copied from: +// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c + +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ +// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test + +#include +#include + +#ifdef __BIG_ENDIAN__ + #define SHA_BIG_ENDIAN +#elif defined __LITTLE_ENDIAN__ +/* override */ +#elif defined __BYTE_ORDER + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define SHA_BIG_ENDIAN + #endif +#else // ! defined __LITTLE_ENDIAN__ + #include // machine/endian.h + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define SHA_BIG_ENDIAN + #endif +#endif + +/* header */ + +#define HASH_LENGTH 20 +#define BLOCK_LENGTH 64 + +typedef struct sha1nfo { + + uint32_t buffer[BLOCK_LENGTH / 4]; + uint32_t state[HASH_LENGTH / 4]; + uint32_t byteCount; + uint8_t bufferOffset; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[HASH_LENGTH]; + +} sha1nfo; + +/* public API - prototypes - TODO: doxygen*/ + +/** + */ +void sha1_init(sha1nfo *s); +/** + */ +void sha1_writebyte(sha1nfo *s, uint8_t data); +/** + */ +void sha1_write(sha1nfo *s, const char *data, size_t len); +/** + */ +uint8_t *sha1_result(sha1nfo *s); +/** + */ +void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength); +/** + */ +uint8_t *sha1_resultHmac(sha1nfo *s); + +/* code */ +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +void sha1_init(sha1nfo *s) { + + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->byteCount = 0; + s->bufferOffset = 0; + +} + +uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + + return ((number << bits) | (number >> (32 - bits))); + +} + +void sha1_hashBlock(sha1nfo *s) { + + uint8_t i; + uint32_t a, b, c, d, e, t; + + a = s->state[0]; + b = s->state[1]; + c = s->state[2]; + d = s->state[3]; + e = s->state[4]; + for (i = 0; i < 80; i++) { + + if (i >= 16) { + + t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^ + s->buffer[(i + 2) & 15] ^ s->buffer[i & 15]; + s->buffer[i & 15] = sha1_rol32(t, 1); + + } + + if (i < 20) { + + t = (d ^ (b & (c ^ d))) + SHA1_K0; + + } else if (i < 40) { + + t = (b ^ c ^ d) + SHA1_K20; + + } else if (i < 60) { + + t = ((b & c) | (d & (b | c))) + SHA1_K40; + + } else { + + t = (b ^ c ^ d) + SHA1_K60; + + } + + t += sha1_rol32(a, 5) + e + s->buffer[i & 15]; + e = d; + d = c; + c = sha1_rol32(b, 30); + b = a; + a = t; + + } + + s->state[0] += a; + s->state[1] += b; + s->state[2] += c; + s->state[3] += d; + s->state[4] += e; + +} + +void sha1_addUncounted(sha1nfo *s, uint8_t data) { + + uint8_t *const b = (uint8_t *)s->buffer; +#ifdef SHA_BIG_ENDIAN + b[s->bufferOffset] = data; +#else + b[s->bufferOffset ^ 3] = data; +#endif + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + + sha1_hashBlock(s); + s->bufferOffset = 0; + + } + +} + +void sha1_writebyte(sha1nfo *s, uint8_t data) { + + ++s->byteCount; + sha1_addUncounted(s, data); + +} + +void sha1_write(sha1nfo *s, const char *data, size_t len) { + + for (; len--;) + sha1_writebyte(s, (uint8_t)*data++); + +} + +void sha1_pad(sha1nfo *s) { + + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) + sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted( + s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); + +} + +uint8_t *sha1_result(sha1nfo *s) { + + // Pad to complete the last block + sha1_pad(s); + +#ifndef SHA_BIG_ENDIAN + // Swap byte order back + int i; + for (i = 0; i < 5; i++) { + + s->state[i] = (((s->state[i]) << 24) & 0xff000000) | + (((s->state[i]) << 8) & 0x00ff0000) | + (((s->state[i]) >> 8) & 0x0000ff00) | + (((s->state[i]) >> 24) & 0x000000ff); + + } + +#endif + + // Return pointer to hash (20 characters) + return (uint8_t *)s->state; + +} + +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c + +void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) { + + uint8_t i; + memset(s->keyBuffer, 0, BLOCK_LENGTH); + if (keyLength > BLOCK_LENGTH) { + + // Hash long keys + sha1_init(s); + for (; keyLength--;) + sha1_writebyte(s, *key++); + memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); + + } else { + + // Block length keys are used as is + memcpy(s->keyBuffer, key, keyLength); + + } + + // Start inner hash + sha1_init(s); + for (i = 0; i < BLOCK_LENGTH; i++) { + + sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD); + + } + +} + +uint8_t *sha1_resultHmac(sha1nfo *s) { + + uint8_t i; + // Complete inner hash + memcpy(s->innerHash, sha1_result(s), HASH_LENGTH); + // Calculate outer hash + sha1_init(s); + for (i = 0; i < BLOCK_LENGTH; i++) + sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD); + for (i = 0; i < HASH_LENGTH; i++) + sha1_writebyte(s, s->innerHash[i]); + return sha1_result(s); + +} + +// End public domain SHA1 implementation + +void sha1(const u8 *data, size_t len, u8 *out) { + + sha1nfo s; + sha1_init(&s); + sha1_write(&s, (const char *)data, len); + memcpy(out, sha1_result(&s), HASH_LENGTH); + +} + +char *sha1_hex(const u8 *data, size_t len) { + + u8 digest[HASH_LENGTH]; + sha1(data, len, digest); + u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1); + for (size_t i = 0; i < HASH_LENGTH; ++i) { + + sprintf((char *)(hex + i * 2), "%02x", digest[i]); + + } + + return hex; + +} + +char *sha1_hex_for_file(const char *fname, u32 len) { + + int fd = open(fname, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s'", fname); } + + u32 read_len = MIN(len, (u32)MAX_FILE); + u8 *tmp = ck_alloc(read_len); + ck_read(fd, tmp, read_len, fname); + + close(fd); + + char *hex = sha1_hex(tmp, read_len); + ck_free(tmp); + return hex; + +} + -- cgit 1.4.1