diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-forkserver.c | 37 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 9 | ||||
-rw-r--r-- | src/afl-fuzz-extras.c | 58 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 8 | ||||
-rw-r--r-- | src/afl-fuzz-redqueen.c | 15 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 10 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 5 | ||||
-rw-r--r-- | src/afl-showmap.c | 104 |
8 files changed, 166 insertions, 80 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 56475320..173cc70f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -58,6 +58,8 @@ static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { + if (fsrv->qemu_mode) setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); + execv(fsrv->target_path, argv); } @@ -122,8 +124,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -static u32 read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, - volatile u8 *stop_soon_p) { +static u32 __attribute__((hot)) +read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, volatile u8 *stop_soon_p) { fd_set readfds; FD_ZERO(&readfds); @@ -638,13 +640,19 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { - if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) { + if (fsrv->autodict_func == NULL || fsrv->afl_ptr == NULL) { // this is not afl-fuzz - we deny and return - if (fsrv->use_shmem_fuzz) + if (fsrv->use_shmem_fuzz) { + status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); - else + + } else { + status = (FS_OPT_ENABLED); + + } + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { FATAL("Writing to forkserver failed."); @@ -657,11 +665,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) { ACTF("Using AUTODICT feature."); } - if (fsrv->use_shmem_fuzz) + if (fsrv->use_shmem_fuzz) { + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); - else + + } else { + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); + } + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { FATAL("Writing to forkserver failed."); @@ -680,7 +693,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - u32 len = status, offset = 0, count = 0; + u32 offset = 0, count = 0; + u32 len = status; u8 *dict = ck_alloc(len); if (dict == NULL) { @@ -711,8 +725,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, while (offset < (u32)status && (u8)dict[offset] + offset < (u32)status) { - fsrv->function_ptr(fsrv->function_opt, dict + offset + 1, - (u8)dict[offset]); + fsrv->autodict_func(fsrv->afl_ptr, dict + offset + 1, + (u8)dict[offset]); offset += (1 + dict[offset]); count++; @@ -871,7 +885,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " - the target was compiled with afl-clang-lto and a constructor " "was\n" " instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve " - "your problem\n\n" + "your \n" + " problem\n\n" " - Less likely, there is a horrible bug in the fuzzer. If other " "options\n" diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d273818d..db57061d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -57,7 +57,7 @@ void write_bitmap(afl_state_t *afl) { This function is called after every exec() on a fairly large buffer, so it needs to be fast. We do this in 32-bit and 64-bit flavors. */ -u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { +u8 __attribute__((hot)) has_new_bits(afl_state_t *afl, u8 *virgin_map) { #ifdef WORD_SIZE_64 @@ -407,7 +407,7 @@ void init_count_class16(void) { #ifdef WORD_SIZE_64 -void classify_counts(afl_forkserver_t *fsrv) { +void __attribute__((hot)) classify_counts(afl_forkserver_t *fsrv) { u64 *mem = (u64 *)fsrv->trace_bits; @@ -436,7 +436,7 @@ void classify_counts(afl_forkserver_t *fsrv) { #else -void classify_counts(afl_forkserver_t *fsrv) { +void __attribute__((hot)) classify_counts(afl_forkserver_t *fsrv) { u32 *mem = (u32 *)fsrv->trace_bits; @@ -594,7 +594,8 @@ static void write_crash_readme(afl_state_t *afl) { save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ -u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { +u8 __attribute__((hot)) +save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(len == 0)) { return 0; } diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 097871c8..17f02984 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -25,23 +25,28 @@ #include "afl-fuzz.h" -/* Helper function for load_extras. */ +/* helper function for auto_extras qsort */ +static int compare_auto_extras_len(const void *ae1, const void *ae2) { + + return ((struct auto_extra_data *)ae1)->len - + ((struct auto_extra_data *)ae2)->len; + +} -static int compare_extras_len(const void *p1, const void *p2) { +/* descending order */ - struct extra_data *e1 = (struct extra_data *)p1, - *e2 = (struct extra_data *)p2; +static int compare_auto_extras_use_d(const void *ae1, const void *ae2) { - return e1->len - e2->len; + return ((struct auto_extra_data *)ae2)->hit_cnt - + ((struct auto_extra_data *)ae1)->hit_cnt; } -static int compare_extras_use_d(const void *p1, const void *p2) { +/* Helper function for load_extras. */ - struct extra_data *e1 = (struct extra_data *)p1, - *e2 = (struct extra_data *)p2; +static int compare_extras_len(const void *e1, const void *e2) { - return e2->hit_cnt - e1->hit_cnt; + return ((struct extra_data *)e1)->len - ((struct extra_data *)e2)->len; } @@ -354,14 +359,10 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) { } /* Maybe add automatic extra. */ -/* Ugly hack: afl state is transfered as u8* because we import data via - afl-forkserver.c - which is shared with other afl tools that do not - have the afl state struct */ -void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { +void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) { - afl_state_t *afl = (afl_state_t *)afl_tmp; - u32 i; + u32 i; /* Allow users to specify that they don't want auto dictionaries. */ @@ -375,7 +376,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { } - if (i == len) { return; } + if (i == len || unlikely(len > MAX_AUTO_EXTRA)) { return; } /* Reject builtin interesting values. */ @@ -452,10 +453,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { if (afl->a_extras_cnt < MAX_AUTO_EXTRAS) { - afl->a_extras = ck_realloc_block( - afl->a_extras, (afl->a_extras_cnt + 1) * sizeof(struct extra_data)); - - afl->a_extras[afl->a_extras_cnt].data = ck_memdup(mem, len); + memcpy(afl->a_extras[afl->a_extras_cnt].data, mem, len); afl->a_extras[afl->a_extras_cnt].len = len; ++afl->a_extras_cnt; @@ -463,9 +461,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { i = MAX_AUTO_EXTRAS / 2 + rand_below(afl, (MAX_AUTO_EXTRAS + 1) / 2); - ck_free(afl->a_extras[i].data); - - afl->a_extras[i].data = ck_memdup(mem, len); + memcpy(afl->a_extras[i].data, mem, len); afl->a_extras[i].len = len; afl->a_extras[i].hit_cnt = 0; @@ -475,13 +471,13 @@ sort_a_extras: /* First, sort all auto extras by use count, descending order. */ - qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct extra_data), - compare_extras_use_d); + qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct auto_extra_data), + compare_auto_extras_use_d); /* Then, sort the top USE_AUTO_EXTRAS entries by size. */ qsort(afl->a_extras, MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt), - sizeof(struct extra_data), compare_extras_len); + sizeof(struct auto_extra_data), compare_auto_extras_len); } @@ -544,7 +540,7 @@ void load_auto(afl_state_t *afl) { if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) { - maybe_add_auto((u8 *)afl, tmp, len); + maybe_add_auto(afl, tmp, len); } @@ -579,13 +575,5 @@ void destroy_extras(afl_state_t *afl) { ck_free(afl->extras); - for (i = 0; i < afl->a_extras_cnt; ++i) { - - ck_free(afl->a_extras[i].data); - - } - - ck_free(afl->a_extras); - } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 4db6febf..6d52b2b4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -841,7 +841,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { - maybe_add_auto((u8 *)afl, a_collect, a_len); + maybe_add_auto(afl, a_collect, a_len); } @@ -852,7 +852,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { - maybe_add_auto((u8 *)afl, a_collect, a_len); + maybe_add_auto(afl, a_collect, a_len); } @@ -3108,7 +3108,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { - maybe_add_auto((u8 *)afl, a_collect, a_len); + maybe_add_auto(afl, a_collect, a_len); } @@ -3119,7 +3119,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { - maybe_add_auto((u8 *)afl, a_collect, a_len); + maybe_add_auto(afl, a_collect, a_len); } diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9716be95..f21dd0b0 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -151,7 +151,8 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) { /* Discard if the mutations change the paths or if it is too decremental in speed */ if (cksum != exec_cksum || - (stop_us - start_us > 2 * afl->queue_cur->exec_us)) { + ((stop_us - start_us > 2 * afl->queue_cur->exec_us) && + likely(!afl->fixed_seed))) { ranges = add_range(ranges, rng->start, rng->start + s / 2); ranges = add_range(ranges, rng->start + s / 2 + 1, rng->end); @@ -499,7 +500,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { } - maybe_add_auto((u8 *)afl, (u8 *)&v, shape); + maybe_add_auto(afl, (u8 *)&v, shape); u64 rev; switch (shape) { @@ -508,15 +509,15 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { break; case 2: rev = SWAP16((u16)v); - maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); + maybe_add_auto(afl, (u8 *)&rev, shape); break; case 4: rev = SWAP32((u32)v); - maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); + maybe_add_auto(afl, (u8 *)&rev, shape); break; case 8: rev = SWAP64(v); - maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); + maybe_add_auto(afl, (u8 *)&rev, shape); break; } @@ -771,8 +772,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { if (afl->pass_stats[key].total == 0) { - maybe_add_auto((u8 *)afl, o->v0, SHAPE_BYTES(h->shape)); - maybe_add_auto((u8 *)afl, o->v1, SHAPE_BYTES(h->shape)); + maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape)); + maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape)); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 94cfc383..5381723d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -38,8 +38,8 @@ u64 time_spent_working = 0; /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, - u32 timeout) { +fsrv_run_result_t __attribute__((hot)) +fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { #ifdef PROFILING static u64 time_spent_start = 0; @@ -72,7 +72,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { +void __attribute__((hot)) +write_to_testcase(afl_state_t *afl, void *mem, u32 len) { #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; @@ -871,7 +872,8 @@ abort_trimming: error conditions, returning 1 if it's time to bail out. This is a helper function for fuzz_one(). */ -u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { +u8 __attribute__((hot)) +common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index aab785e1..a8416eb1 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,8 +102,9 @@ void afl_state_init_1(afl_state_t *afl, uint32_t map_size) { afl->fsrv.use_stdin = 1; afl->fsrv.map_size = map_size; - afl->fsrv.function_opt = (u8 *)afl; - afl->fsrv.function_ptr = &maybe_add_auto; + // afl_state_t is not available in forkserver.c + afl->fsrv.afl_ptr = (void *)afl; + afl->fsrv.autodict_func = (void (*)(void *, u8 *, u32)) & maybe_add_auto; afl->cal_cycles = CAL_CYCLES; afl->cal_cycles_long = CAL_CYCLES_LONG; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0aa116e5..47c615d8 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -68,9 +68,11 @@ static char *stdin_file; /* stdin file */ static u8 *in_dir = NULL, /* input folder */ *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */ -static u8 *in_data; /* Input data */ +static u8 *in_data, /* Input data */ + *coverage_map; /* Coverage map */ -static u32 total, highest; /* tuple content information */ +static u64 total; /* tuple content information */ +static u32 tcnt, highest; /* tuple content information */ static u32 in_len, /* Input data length */ arg_offset; /* Total number of execs */ @@ -83,7 +85,8 @@ static u8 quiet_mode, /* Hide non-essential messages? */ cmin_mode, /* Generate output in afl-cmin mode? */ binary_mode, /* Write output as a binary map */ keep_cores, /* Allow coredumps? */ - remove_shm = 1; /* remove shmem? */ + remove_shm = 1, /* remove shmem? */ + collect_coverage; /* collect coverage */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -175,6 +178,25 @@ static void at_exit_handler(void) { } +/* Analyze results. */ + +static void analyze_results(afl_forkserver_t *fsrv) { + + u32 i; + for (i = 0; i < map_size; i++) { + + if (fsrv->trace_bits[i]) { + + total += fsrv->trace_bits[i]; + if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i]; + if (!coverage_map[i]) { coverage_map[i] = 1; } + + } + + } + +} + /* Write results. */ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { @@ -588,9 +610,14 @@ static void usage(u8 *argv0) { " (Not necessary, here for consistency with other afl-* " "tools)\n\n" "Other settings:\n" - " -i dir - process all files in this directory, -o must be a " + " -i dir - process all files in this directory, must be combined " + "with -o.\n" + " With -C, -o is a file, without -C it must be a " "directory\n" " and each bitmap will be written there individually.\n" + " -C - collect coverage, writes all edges to -o and gives a " + "summary\n" + " Must be combined with -i.\n" " -q - sink program's output and don't show messages\n" " -e - show edge coverage only, ignore hit counts\n" " -r - show real tuple values instead of AFL filter values\n" @@ -624,7 +651,6 @@ int main(int argc, char **argv_orig, char **envp) { s32 opt, i; u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; - u32 tcnt = 0; char **use_argv; char **argv = argv_cpy_dup(argc, argv_orig); @@ -639,10 +665,14 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrh")) > 0) { switch (opt) { + case 'C': + collect_coverage = 1; + break; + case 'i': if (in_dir) { FATAL("Multiple -i options not supported"); } in_dir = optarg; @@ -820,6 +850,13 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !out_file) { usage(argv[0]); } + if (in_dir) { + + if (!out_file && !collect_coverage) + FATAL("for -i you need to specify either -C and/or -o"); + + } + if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; } if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; } @@ -910,7 +947,7 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir) { - DIR * dir_in, *dir_out; + DIR * dir_in, *dir_out = NULL; struct dirent *dir_ent; int done = 0; u8 infile[PATH_MAX], outfile[PATH_MAX]; @@ -924,20 +961,43 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->dev_null_fd = open("/dev/null", O_RDWR); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } + // if a queue subdirectory exists switch to that + u8 *dn = alloc_printf("%s/queue", in_dir); + if ((dir_in = opendir(dn)) != NULL) { + + closedir(dir_in); + in_dir = dn; + + } else + + ck_free(dn); + if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir); + if (!(dir_in = opendir(in_dir))) { PFATAL("cannot open directory %s", in_dir); } - if (!(dir_out = opendir(out_file))) { + if (!collect_coverage) { + + if (!(dir_out = opendir(out_file))) { + + if (mkdir(out_file, 0700)) { - if (mkdir(out_file, 0700)) { + PFATAL("cannot create output directory %s", out_file); - PFATAL("cannot create output directory %s", out_file); + } } + } else { + + if ((coverage_map = (u8 *)malloc(map_size)) == NULL) + FATAL("coult not grab memory"); + edges_only = 0; + raw_instr_output = 1; + } u8 *use_dir = "."; @@ -978,6 +1038,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_start(fsrv, use_argv, &stop_soon, get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0); + map_size = fsrv->map_size; if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); @@ -1005,7 +1066,8 @@ int main(int argc, char **argv_orig, char **envp) { if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue; #endif - snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name); + if (!collect_coverage) + snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name); if (read_file(infile)) { @@ -1019,7 +1081,10 @@ int main(int argc, char **argv_orig, char **envp) { showmap_run_target_forkserver(fsrv, in_data, in_len); ck_free(in_data); - tcnt = write_results_to_file(fsrv, outfile); + if (collect_coverage) + analyze_results(fsrv); + else + tcnt = write_results_to_file(fsrv, outfile); } @@ -1030,6 +1095,13 @@ int main(int argc, char **argv_orig, char **envp) { closedir(dir_in); if (dir_out) { closedir(dir_out); } + if (collect_coverage) { + + memcpy(fsrv->trace_bits, coverage_map, map_size); + tcnt = write_results_to_file(fsrv, out_file); + + } + } else { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) @@ -1043,8 +1115,14 @@ int main(int argc, char **argv_orig, char **envp) { if (!quiet_mode) { if (!tcnt) { FATAL("No instrumentation detected" cRST); } - OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST, + OKF("Captured %u tuples (highest value %u, total values %llu) in " + "'%s'." cRST, tcnt, highest, total, out_file); + if (collect_coverage) + OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) " + "with %llu input files.", + tcnt, map_size, ((float)tcnt * 100) / (float)map_size, + fsrv->total_execs); } |