From 39ad3b89467d6de12cbb9d08ccd77d331c0d1f9e Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Wed, 28 Apr 2021 09:25:26 +0100 Subject: Frida persistent (#880) * Added x64 support for persistent mode (function call only), in-memory teest cases and complog * Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC * Various minor fixes and finished support for AFL_INST_LIBS * Review changes Co-authored-by: Your Name --- src/afl-forkserver.c | 3 ++- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-init.c | 8 ++++++++ src/afl-fuzz.c | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 727e7f8d..d533fd4a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -416,7 +416,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, struct rlimit r; - if (!fsrv->cmplog_binary && fsrv->qemu_mode == false) { + if (!fsrv->cmplog_binary && fsrv->qemu_mode == false && + fsrv->frida_mode == false) { unsetenv(CMPLOG_SHM_ENV_VAR); // we do not want that in non-cmplog fsrv diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 27c6c413..c2e9c80f 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -35,7 +35,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } - if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) { + if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) { argv[0] = fsrv->cmplog_binary; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index b6bfbc29..547311c7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2774,6 +2774,14 @@ void check_binary(afl_state_t *afl, u8 *fname) { WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { + + OKF("FRIDA Persistent mode configuration options detected."); + setenv(PERSIST_ENV_VAR, "1", 1); + afl->persistent_mode = 1; + + afl->shmem_testcase_mode = 1; + } if (afl->fsrv.frida_mode || diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3606533d..58b0a5c2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1697,13 +1697,14 @@ int main(int argc, char **argv_orig, char **envp) { // TODO: this is semi-nice afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; + afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.init_child_func = cmplog_exec_child; if ((map_size <= DEFAULT_SHMEM_SIZE || afl->cmplog_fsrv.map_size < map_size) && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->unicorn_mode) { + !afl->fsrv.frida_mode && !afl->unicorn_mode) { afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); char vbuf[16]; -- cgit 1.4.1 From 29dbe665a7a7dc6b2232487dbc6c1ebecbbdfb06 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Apr 2021 09:12:21 +0200 Subject: nits --- src/afl-fuzz.c | 2 ++ utils/libdislocator/libdislocator.so.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 58b0a5c2..1b3e303c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1358,6 +1358,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_preload = getenv("AFL_PRELOAD"); u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); if (afl_preload) { frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); @@ -1383,6 +1384,7 @@ int main(int argc, char **argv_orig, char **envp) { } else if (afl->fsrv.frida_mode) { u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); setenv("LD_PRELOAD", frida_binary, 1); setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); ck_free(frida_binary); diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index 7c651afd..dde78f7b 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -145,7 +145,7 @@ typedef struct { /* Configurable stuff (use AFL_LD_* to set): */ static size_t max_mem = MAX_ALLOC; /* Max heap usage to permit */ -static u8 alloc_verbose, /* Additional debug messages */ +static u8 alloc_verbose, /* Additional debug messages */ hard_fail, /* abort() when max_mem exceeded? */ no_calloc_over, /* abort() on calloc() overflows? */ align_allocations; /* Force alignment to sizeof(void*) */ @@ -504,7 +504,7 @@ __attribute__((constructor)) void __dislocator_init(void) { if (tmp) { - char *tok; + char * tok; unsigned long long mmem = strtoull(tmp, &tok, 10); if (*tok != '\0' || errno == ERANGE || mmem > SIZE_MAX / 1024 / 1024) FATAL("Bad value for AFL_LD_LIMIT_MB"); @@ -550,3 +550,4 @@ void *erealloc(void *ptr, size_t len) { return realloc(ptr, len); } + -- cgit 1.4.1 From e9d2f72382cab75832721d859c3e731da071435d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 30 Apr 2021 13:35:24 +0200 Subject: fixed potential double free in custom trim (#881) --- include/afl-fuzz.h | 4 ++-- src/afl-fuzz-mutators.c | 23 +++++++++++++++++------ src/afl-fuzz-one.c | 8 ++++---- src/afl-fuzz-run.c | 8 ++++++-- 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f201782a..040d7ae9 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1003,7 +1003,7 @@ void read_afl_environment(afl_state_t *, char **); /* Custom mutators */ void setup_custom_mutators(afl_state_t *); void destroy_custom_mutators(afl_state_t *); -u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf, +u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 **in_buf, struct custom_mutator *mutator); /* Python */ @@ -1093,7 +1093,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); -u8 trim_case(afl_state_t *, struct queue_entry *, u8 *); +u8 trim_case(afl_state_t *, struct queue_entry *, u8 **); u8 common_fuzz_stuff(afl_state_t *, u8 *, u32); /* Fuzz one */ diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index c99d9a4d..d8db8676 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -305,9 +305,13 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { } -u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, +// Custom testcase trimming. +u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p, struct custom_mutator *mutator) { + // We need to pass pointers around, as growing testcases may need to realloc. + u8 *in_buf = *in_buf_p; + u8 needs_write = 0, fault = 0; u32 trim_exec = 0; u32 orig_len = q->len; @@ -397,14 +401,21 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (likely(retlen && cksum == q->exec_cksum)) { - if (afl_realloc((void **)&in_buf, retlen) == NULL) { + // Check if we got a new retbuf and to memcpy our buf. + if (in_buf != retbuf) { - FATAL("can not allocate memory for trim"); + if (afl_realloc((void **)in_buf_p, retlen) == NULL) { - } + FATAL("can not allocate memory for trim"); + + } - memcpy(in_buf, retbuf, retlen); - q->len = retlen; + in_buf = *in_buf_p; + + memcpy(in_buf, retbuf, retlen); + q->len = retlen; + + } /* Let's save a clean trace, which will be needed by update_bitmap_score once we're done with the trimming stuff. */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index d72d4145..ed815cb4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -508,7 +508,7 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 old_len = afl->queue_cur->len; - u8 res = trim_case(afl, afl->queue_cur, in_buf); + u8 res = trim_case(afl, afl->queue_cur, &in_buf); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -3007,16 +3007,16 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u32 old_len = afl->queue_cur->len; - u8 res = trim_case(afl, afl->queue_cur, in_buf); + u8 res = trim_case(afl, afl->queue_cur, &in_buf); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); - if (res == FSRV_RUN_ERROR) { + if (unlikely(res == FSRV_RUN_ERROR)) { FATAL("Unable to execute target application"); } - if (afl->stop_soon) { + if (unlikely(afl->stop_soon)) { ++afl->cur_skipped_paths; goto abandon_entry; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 832f17bb..a7b071a5 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -720,7 +720,10 @@ void sync_fuzzers(afl_state_t *afl) { trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of file size, to keep the stage short and sweet. */ -u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { +u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p) { + + // We need to pass pointers around, as growing testcases may need to realloc. + u8 *in_buf = *in_buf_p; u32 orig_len = q->len; @@ -734,7 +737,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (el->afl_custom_trim) { - trimmed_case = trim_case_custom(afl, q, in_buf, el); + trimmed_case = trim_case_custom(afl, q, in_buf_p, el); + in_buf = *in_buf_p; custom_trimmed = true; } -- cgit 1.4.1 From 38f1394e3ab5ccacff07e27f370f3edf1ce77afb Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 30 Apr 2021 13:36:35 +0200 Subject: error handling, freeing mem --- src/afl-cc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 1f89bac5..09009334 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -560,12 +560,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !have_c) { u8 *ld_path = strdup(AFL_REAL_LD); - if (!*ld_path) ld_path = "ld.lld"; + if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); } + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); #else cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path); #endif + free(ld_path); cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; -- cgit 1.4.1 From 56882f3a496fd287b50a18ec7c83d23e1630ef81 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 30 Apr 2021 13:44:59 +0200 Subject: fix statsd writing --- src/afl-fuzz-stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 22c0cbd2..fd9af5e4 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -544,7 +544,7 @@ void show_stats(afl_state_t *afl) { if (unlikely(afl->afl_env.afl_statsd)) { - if (unlikely(afl->force_ui_update && cur_ms - afl->statsd_last_send_ms > + if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000)) { /* reset counter, even if send failed. */ -- cgit 1.4.1 From 86452cc959bd4b0d5fe6e60d0eefbc7848fe38e2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 30 Apr 2021 23:41:06 +0200 Subject: fix stdin trimming --- docs/Changelog.md | 1 + src/afl-forkserver.c | 2 +- src/afl-fuzz-run.c | 10 ++++------ utils/afl_proxy/afl-proxy.c | 23 +++++++++++++++-------- 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 459c2f35..6a25865d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,7 @@ sending a mail to . - add recording of previous fuzz attempts for persistent mode to allow replay of non-reproducable crashes, see AFL_PERSISTENT_RECORD in config.h and docs/envs.h + - fixed a bug when trimming for stdin targets - default cmplog level (-l) is now 2, better efficiency. - cmplog level 3 (-l 3) now performs redqueen on everything. use with care. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index d533fd4a..a07e78b4 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1090,7 +1090,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { #endif - if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) { + if (likely(fsrv->use_shmem_fuzz)) { if (unlikely(len > MAX_FILE)) len = MAX_FILE; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index a7b071a5..397d62bf 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -203,7 +203,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, } - if (afl->fsrv.shmem_fuzz) { + if (likely(afl->fsrv.use_shmem_fuzz)) { if (!post_process_skipped) { @@ -211,9 +211,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, memcpy(afl->fsrv.shmem_fuzz, new_mem, new_size); - } - - else { + } else { memcpy(afl->fsrv.shmem_fuzz, mem, skip_at); @@ -244,7 +242,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, return; - } else if (afl->fsrv.out_file) { + } else if (unlikely(!afl->fsrv.use_stdin)) { if (unlikely(afl->no_unlink)) { @@ -279,7 +277,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, } - if (!afl->fsrv.out_file) { + if (afl->fsrv.use_stdin) { if (ftruncate(fd, new_size)) { PFATAL("ftruncate() failed"); } lseek(fd, 0, SEEK_SET); diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index 2d8ba991..6006e238 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -195,10 +195,7 @@ static u32 __afl_next_testcase(u8 *buf, u32 max_len) { /* report that we are starting the target */ if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0; - if (status < 1) - return 0; - else - return status; + return status; } @@ -216,7 +213,7 @@ int main(int argc, char *argv[]) { /* This is were the testcase data is written into */ u8 buf[1024]; // this is the maximum size for a test case! set it! - u32 len; + s32 len; /* here you specify the map size you need that you are reporting to afl-fuzz. Any value is fine as long as it can be divided by 32. */ @@ -228,10 +225,20 @@ int main(int argc, char *argv[]) { while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { - /* here you have to create the magic that feeds the buf/len to the - target and write the coverage to __afl_area_ptr */ + if (len > 4) { // the minimum data size you need for the target - // ... the magic ... + /* here you have to create the magic that feeds the buf/len to the + target and write the coverage to __afl_area_ptr */ + + // ... the magic ... + + // remove this, this is just to make afl-fuzz not complain when run + if (buf[0] == 0xff) + __afl_area_ptr[1] = 1; + else + __afl_area_ptr[2] = 2; + + } /* report the test case is done and wait for the next */ __afl_end_testcase(); -- cgit 1.4.1 From 6119c2eb5f4349c93abbeb19f0f9ec2f41aaabd1 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 1 May 2021 14:03:28 +0200 Subject: remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used --- qemu_mode/qemuafl | 2 +- src/afl-fuzz.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index d73b0336..ddc4a974 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit d73b0336b451fd034e5f469089fb7ee96c80adf2 +Subproject commit ddc4a9748d59857753fb33c30a356f354595f36d diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1b3e303c..8c3ba575 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2212,6 +2212,31 @@ stop_fuzzing: } afl_fsrv_deinit(&afl->fsrv); + + /* remove tmpfile */ + if (afl->tmp_dir != NULL && !afl->in_place_resume) { + + char tmpfile[PATH_MAX]; + + if (afl->file_extension) { + + snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, + afl->file_extension); + + } else { + + snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); + + } + + if (unlink(tmpfile) != 0) { + + FATAL("Could not unlink current input file: %s.", tmpfile); + + } + + } + if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); -- cgit 1.4.1 From 1d9a3d955cb4b1350ecad1e008b7c24c5ea3af57 Mon Sep 17 00:00:00 2001 From: realmadsci <71108352+realmadsci@users.noreply.github.com> Date: Thu, 6 May 2021 18:14:16 -0400 Subject: Fix memory errors when trim causes testcase growth (#881) (#903) * Revert "fixed potential double free in custom trim (#881)" This reverts commit e9d2f72382cab75832721d859c3e731da071435d. * Revert "fix custom trim for increasing data" This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667. * Fix memory errors when trim causes testcase growth Modify trim_case_custom to avoid writing into in_buf because some custom mutators can cause the testcase to grow rather than shrink. Instead of modifying in_buf directly, we write the update out to the disk when trimming is complete, and then the caller is responsible for refreshing the in-memory buffer from the file. This is still a bit sketchy because it does need to modify q->len in order to notify the upper layers that something changed, and it could end up telling upper layer code that the q->len is *bigger* than the buffer (q->testcase_buf) that contains it, which is asking for trouble down the line somewhere... * Fix an unlikely situation Put back some `unlikely()` calls that were in the e9d2f72382cab75832721d859c3e731da071435d commit that was reverted. --- include/afl-fuzz.h | 4 +-- src/afl-fuzz-mutators.c | 65 +++++++++++++++++++++++-------------------------- src/afl-fuzz-one.c | 4 +-- src/afl-fuzz-run.c | 8 ++---- 4 files changed, 37 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 040d7ae9..f201782a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1003,7 +1003,7 @@ void read_afl_environment(afl_state_t *, char **); /* Custom mutators */ void setup_custom_mutators(afl_state_t *); void destroy_custom_mutators(afl_state_t *); -u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 **in_buf, +u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf, struct custom_mutator *mutator); /* Python */ @@ -1093,7 +1093,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); -u8 trim_case(afl_state_t *, struct queue_entry *, u8 **); +u8 trim_case(afl_state_t *, struct queue_entry *, u8 *); u8 common_fuzz_stuff(afl_state_t *, u8 *, u32); /* Fuzz one */ diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index d8db8676..3bb37a89 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -305,16 +305,14 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { } -// Custom testcase trimming. -u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p, +u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, struct custom_mutator *mutator) { - // We need to pass pointers around, as growing testcases may need to realloc. - u8 *in_buf = *in_buf_p; - - u8 needs_write = 0, fault = 0; + u8 fault = 0; u32 trim_exec = 0; u32 orig_len = q->len; + u32 out_len = 0; + u8* out_buf = NULL; u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; @@ -401,40 +399,33 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p, if (likely(retlen && cksum == q->exec_cksum)) { - // Check if we got a new retbuf and to memcpy our buf. - if (in_buf != retbuf) { - - if (afl_realloc((void **)in_buf_p, retlen) == NULL) { - - FATAL("can not allocate memory for trim"); - - } + /* Let's save a clean trace, which will be needed by + update_bitmap_score once we're done with the trimming stuff. + Use out_buf NULL check to make this only happen once per trim. */ - in_buf = *in_buf_p; + if (!out_buf) { - memcpy(in_buf, retbuf, retlen); - q->len = retlen; + memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, + afl->fsrv.map_size); } - /* 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) { + if (afl_realloc((void **)&out_buf, retlen) == NULL) { - needs_write = 1; - memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, - afl->fsrv.map_size); + FATAL("can not allocate memory for trim"); } + out_len = retlen; + memcpy(out_buf, retbuf, retlen); + /* Tell the custom mutator that the trimming was successful */ afl->stage_cur = mutator->afl_custom_post_trim(mutator->data, 1); if (afl->not_on_tty && afl->debug) { SAYF("[Custom Trimming] SUCCESS: %u/%u iterations (now at %u bytes)", - afl->stage_cur, afl->stage_max, q->len); + afl->stage_cur, afl->stage_max, out_len); } @@ -467,16 +458,10 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p, } - if (afl->not_on_tty && afl->debug) { - - SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len); - - } - - /* If we have made changes to in_buf, we also need to update the on-disk + /* If we have made changes, we also need to update the on-disk version of the test case. */ - if (needs_write) { + if (out_buf) { s32 fd; @@ -486,16 +471,28 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p, if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } - ck_write(fd, in_buf, q->len, q->fname); + ck_write(fd, out_buf, out_len, q->fname); close(fd); + /* Update the queue's knowledge of length as soon as we write the file. + We do this here so that exit/error cases that *don't* update the file also + don't update q->len. */ + q->len = out_len; + memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size); update_bitmap_score(afl, q); } + if (afl->not_on_tty && afl->debug) { + + SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len); + + } + abort_trimming: + if (out_buf) afl_free(out_buf); afl->bytes_trim_out += q->len; return fault; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ed815cb4..4eeb93de 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -508,7 +508,7 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 old_len = afl->queue_cur->len; - u8 res = trim_case(afl, afl->queue_cur, &in_buf); + u8 res = trim_case(afl, afl->queue_cur, in_buf); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -3007,7 +3007,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u32 old_len = afl->queue_cur->len; - u8 res = trim_case(afl, afl->queue_cur, &in_buf); + u8 res = trim_case(afl, afl->queue_cur, in_buf); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); if (unlikely(res == FSRV_RUN_ERROR)) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 397d62bf..6e5210b8 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -718,10 +718,7 @@ void sync_fuzzers(afl_state_t *afl) { trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of file size, to keep the stage short and sweet. */ -u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p) { - - // We need to pass pointers around, as growing testcases may need to realloc. - u8 *in_buf = *in_buf_p; +u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u32 orig_len = q->len; @@ -735,8 +732,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p) { if (el->afl_custom_trim) { - trimmed_case = trim_case_custom(afl, q, in_buf_p, el); - in_buf = *in_buf_p; + trimmed_case = trim_case_custom(afl, q, in_buf, el); custom_trimmed = true; } -- cgit 1.4.1 From 069e61dfc67050154b649ba286552b563b27e9ba Mon Sep 17 00:00:00 2001 From: "Roman M. Iudichev" Date: Fri, 7 May 2021 18:32:17 +0300 Subject: Exit on time (#904) * Variable AFL_EXIT_ON_TIME description has been added. Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added. afl->exit_on_time variable initialization has been added. The asignment of a value to the afl->afl_env.afl_exit_on_time variable from environment variables has been added. Code to exit on timeout if new path not found has been added. * Type of afl_exit_on_time variable has been changed. Variable exit_on_time has been added to the afl_state_t structure. * Command `export AFL_EXIT_WHEN_DONE=1` has been added. * Millisecond to second conversion has been added. Call get_cur_time() has been added. * Revert to using the saved current time value. * Useless check has been removed. --- docs/env_variables.md | 4 ++++ include/afl-fuzz.h | 5 +++-- include/envs.h | 1 + src/afl-fuzz-state.c | 8 ++++++++ src/afl-fuzz-stats.c | 10 ++++++++++ src/afl-fuzz.c | 8 ++++++++ test/test-performance.sh | 1 + test/test-pre.sh | 1 + 8 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/docs/env_variables.md b/docs/env_variables.md index 0100ffac..8879db72 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -284,6 +284,10 @@ checks or alter some of the more exotic semantics of the tool: normally indicated by the cycle counter in the UI turning green. May be convenient for some types of automated jobs. + - `AFL_EXIT_ON_TIME` Causes afl-fuzz to terminate if no new paths were + found within a specified period of time. May be convenient for some + types of automated jobs. + - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behaviour which does not allow crashes or timeout seeds in the initial -i corpus. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f201782a..a09d6f79 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -392,7 +392,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_kill_signal, *afl_target_env, - *afl_persistent_record; + *afl_persistent_record, *afl_exit_on_time; } afl_env_vars_t; @@ -575,7 +575,8 @@ typedef struct afl_state { last_sync_cycle, /* Cycle no. of the last sync */ last_path_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time; /* Time for most recent hang (ms) */ + last_hang_time, /* Time for most recent hang (ms) */ + exit_on_time; /* Delay to exit if no new paths */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ subseq_tmouts; /* Number of timeouts in a row */ diff --git a/include/envs.h b/include/envs.h index cd23ca3f..9175005e 100644 --- a/include/envs.h +++ b/include/envs.h @@ -49,6 +49,7 @@ static char *afl_environment_variables[] = { "AFL_DUMB_FORKSRV", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", + "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", "AFL_FORCE_UI", diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 28d3339a..73ba7a52 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -99,6 +99,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->cal_cycles = CAL_CYCLES; afl->cal_cycles_long = CAL_CYCLES_LONG; afl->hang_tmout = EXEC_TIMEOUT; + afl->exit_on_time = 0; afl->stats_update_freq = 1; afl->stats_avg_exec = 0; afl->skip_deterministic = 1; @@ -187,6 +188,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_exit_when_done = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_EXIT_ON_TIME", + + afl_environment_variable_len)) { + + afl->afl_env.afl_exit_on_time = + (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-stats.c b/src/afl-fuzz-stats.c index fd9af5e4..ee8bd2da 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -574,6 +574,16 @@ void show_stats(afl_state_t *afl) { } + /* AFL_EXIT_ON_TIME. */ + + if (unlikely(afl->last_path_time && !afl->non_instrumented_mode && + afl->afl_env.afl_exit_on_time && + (cur_ms - afl->last_path_time) > afl->exit_on_time)) { + + afl->stop_soon = 2; + + } + if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) { afl->stop_soon = 2; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8c3ba575..8de3ed6b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -204,6 +204,7 @@ static void usage(u8 *argv0, int more_help) { "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" + "AFL_EXIT_ON_TIME: exit when no new paths are found within the specified time period\n" "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n" "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n" "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n" @@ -1246,6 +1247,13 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->afl_env.afl_exit_on_time) { + + u64 exit_on_time = atoi(afl->afl_env.afl_exit_on_time); + afl->exit_on_time = (u64)exit_on_time * 1000; + + } + if (afl->afl_env.afl_max_det_extras) { s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras); diff --git a/test/test-performance.sh b/test/test-performance.sh index cd9f6caf..d61e2f2a 100755 --- a/test/test-performance.sh +++ b/test/test-performance.sh @@ -18,6 +18,7 @@ export AFL_QUIET=1 export AFL_PATH=`pwd`/.. unset AFL_EXIT_WHEN_DONE +unset AFL_EXIT_ON_TIME unset AFL_SKIP_CPUFREQ unset AFL_DEBUG unset AFL_HARDEN diff --git a/test/test-pre.sh b/test/test-pre.sh index 174f2f7f..7819da47 100755 --- a/test/test-pre.sh +++ b/test/test-pre.sh @@ -62,6 +62,7 @@ $ECHO \\101 2>&1 | grep -qE '^A' || { test -z "$ECHO" && { printf Error: printf command does not support octal character codes ; exit 1 ; } export AFL_EXIT_WHEN_DONE=1 +export AFL_EXIT_ON_TIME=60 export AFL_SKIP_CPUFREQ=1 export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 unset AFL_NO_X86 -- cgit 1.4.1 From 6c274546c42f05292df6c8bcf3c524c4cfc3f031 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 8 May 2021 11:03:49 +0200 Subject: ensure crashes/README.txt exists --- include/afl-fuzz.h | 1 + src/afl-fuzz-stats.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index a09d6f79..72f956b9 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1135,6 +1135,7 @@ void check_if_tty(afl_state_t *); void setup_signal_handlers(void); void save_cmdline(afl_state_t *, u32, char **); void read_foreign_testcases(afl_state_t *, int); +void write_crash_readme(afl_state_t *afl); /* CmpLog */ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index ee8bd2da..bccd2f31 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -179,6 +179,8 @@ void load_stats_file(afl_state_t *afl) { } + if (afl->unique_crashes) { write_crash_readme(afl); } + return; } -- cgit 1.4.1 From b409d63fd30dd2dcbdc7be5fc559f246124ac110 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 8 May 2021 11:24:04 +0200 Subject: fix --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 3d0228db..97f10e6f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -397,7 +397,7 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) { /* Write a message accompanying the crash directory :-) */ -static void write_crash_readme(afl_state_t *afl) { +void write_crash_readme(afl_state_t *afl) { u8 fn[PATH_MAX]; s32 fd; -- cgit 1.4.1 From ceb138cefe46e4412f54f31a812c125cebbb5b65 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 10 May 2021 10:30:57 +0200 Subject: afl-plot: relative time --- afl-plot | 6 +++--- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-stats.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/afl-plot b/afl-plot index f5bb041d..26c8d1b7 100755 --- a/afl-plot +++ b/afl-plot @@ -111,9 +111,9 @@ set terminal png truecolor enhanced size 1000,300 butt set output '$outputdir/high_freq.png' -set xdata time -set timefmt '%s' -set format x "%b %d\n%H:%M" +#set xdata time +#set timefmt '%s' +#set format x "%b %d\n%H:%M" set tics font 'small' unset mxtics unset mytics diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 547311c7..cb586111 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2031,7 +2031,7 @@ void setup_dirs_fds(afl_state_t *afl) { fprintf( afl->fsrv.plot_file, - "# unix_time, cycles_done, cur_path, paths_total, " + "# relative_time, cycles_done, cur_path, paths_total, " "pending_total, pending_favs, map_size, unique_crashes, " "unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n"); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bccd2f31..2dea1bcb 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -386,7 +386,7 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, /* Fields in the file: - unix_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed, + relative_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed, favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, execs_per_sec, edges_found */ -- cgit 1.4.1 From 50af4654e314df75ba8653340e5a58e9e42f1f19 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 10 May 2021 13:46:31 +0200 Subject: code-format --- src/afl-fuzz-mutators.c | 6 +++--- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 8 ++++---- src/afl-ld-lto.c | 11 +++++------ 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 3bb37a89..e27d6fae 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -312,7 +312,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, u32 trim_exec = 0; u32 orig_len = q->len; u32 out_len = 0; - u8* out_buf = NULL; + u8 *out_buf = NULL; u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; @@ -475,8 +475,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, close(fd); /* Update the queue's knowledge of length as soon as we write the file. - We do this here so that exit/error cases that *don't* update the file also - don't update q->len. */ + We do this here so that exit/error cases that *don't* update the file + also don't update q->len. */ q->len = out_len; memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 73ba7a52..c886cb28 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -193,7 +193,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl_environment_variable_len)) { afl->afl_env.afl_exit_on_time = - (u8 *) get_afl_env(afl_environment_variables[i]); + (u8 *)get_afl_env(afl_environment_variables[i]); } else if (!strncmp(env, "AFL_NO_AFFINITY", diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 2dea1bcb..313263f9 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -576,11 +576,11 @@ void show_stats(afl_state_t *afl) { } - /* AFL_EXIT_ON_TIME. */ + /* AFL_EXIT_ON_TIME. */ - if (unlikely(afl->last_path_time && !afl->non_instrumented_mode && - afl->afl_env.afl_exit_on_time && - (cur_ms - afl->last_path_time) > afl->exit_on_time)) { + if (unlikely(afl->last_path_time && !afl->non_instrumented_mode && + afl->afl_env.afl_exit_on_time && + (cur_ms - afl->last_path_time) > afl->exit_on_time)) { afl->stop_soon = 2; diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index d0113af9..1ce97649 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -298,13 +298,12 @@ int main(int argc, char **argv) { SAYF( "\n" - "This is a helper application for afl-clang-lto. It is a wrapper " - "around GNU " - "llvm's 'lld',\n" - "executed by the toolchain whenever using " - "afl-clang-lto/afl-clang-lto++.\n" + "This is a helper application for afl-clang-lto.\n" + "It is a wrapper around llvm's 'lld' in case afl-clang-lto cannot be " + "used.\n" + "Note that the target still has to be compiled with -flto=full!\n" "You probably don't want to run this program directly but rather pass " - "it as LD parameter to configure scripts\n\n" + "it as LD\nparameter to e.g. configure scripts.\n\n" "Environment variables:\n" " AFL_LD_PASSTHROUGH do not link+optimize == no instrumentation\n" -- cgit 1.4.1 From fd077e86bdfb73f1aa8432be547b1e8477883abb Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Mon, 10 May 2021 18:20:28 -0400 Subject: OSX-specific improvements (#912) * Fix afl-cc to work correctly by default on OSX using xcode - CLANG_ENV_VAR must be set for afl-as to work - Use clang mode by default if no specific compiler selected * Add OSX-specific documentation for configuring shared memory --- docs/INSTALL.md | 35 +++++++++++++++++++++++++++++++++++ src/afl-cc.c | 12 ++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/docs/INSTALL.md b/docs/INSTALL.md index e3c06c9d..80d452f7 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -103,6 +103,41 @@ The llvm instrumentation requires a fully-operational installation of clang. The comes with Xcode is missing some of the essential headers and helper tools. See README.llvm.md for advice on how to build the compiler from scratch. +MacOS X supports SYSV shared memory used by AFL's instrumentation, but the +default settings aren't usable with AFL++. The default settings on 10.14 seem +to be: + +```bash +$ ipcs -M +IPC status from as of XXX +shminfo: + shmmax: 4194304 (max shared memory segment size) + shmmin: 1 (min shared memory segment size) + shmmni: 32 (max number of shared memory identifiers) + shmseg: 8 (max shared memory segments per process) + shmall: 1024 (max amount of shared memory in pages) +``` + +To temporarily change your settings to something minimally usable with AFL++, +run these commands as root: + +```bash +sysctl kern.sysv.shmmax=8388608 +sysctl kern.sysv.shmall=4096 +``` + +If you're running more than one instance of AFL you likely want to make `shmall` +bigger and increase `shmseg` as well: + +```bash +sysctl kern.sysv.shmmax=8388608 +sysctl kern.sysv.shmseg=48 +sysctl kern.sysv.shmall=98304 +``` + +See http://www.spy-hill.com/help/apple/SharedMemory.html for documentation for +these settings and how to make them permanent. + ## 4. Linux or *BSD on non-x86 systems Standard build will fail on non-x86 systems, but you should be able to diff --git a/src/afl-cc.c b/src/afl-cc.c index 09009334..c1050355 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1574,7 +1574,12 @@ int main(int argc, char **argv, char **envp) { else if (have_gcc_plugin) compiler_mode = GCC_PLUGIN; else if (have_gcc) - compiler_mode = GCC; + #ifdef __APPLE__ + // on OSX clang masquerades as GCC + compiler_mode = CLANG; + #else + compiler_mode = GCC; + #endif else if (have_lto) compiler_mode = LTO; else @@ -1596,7 +1601,10 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode == CLANG) { instrument_mode = INSTRUMENT_CLANG; } + if (compiler_mode == CLANG) { + instrument_mode = INSTRUMENT_CLANG; + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + } if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { -- cgit 1.4.1 From 72ca9b4684981ce2b807e4efd218bd1924f3e6b1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 11 May 2021 22:06:37 +0200 Subject: fix a few cur_time uses --- docs/Changelog.md | 1 + src/afl-cc.c | 16 +++++++++------- src/afl-fuzz-one.c | 6 +++--- src/afl-fuzz-stats.c | 5 +++-- src/afl-fuzz.c | 6 ++++-- 5 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index ceb02bb9..e4c02921 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.13a (development) + - Note: plot_data switched to relative time from unix time in 3.10 - frida_mode - new mode that uses frida to fuzz binary-only targets, it currently supports persistent mode and cmplog. thanks to @WorksButNotTested! diff --git a/src/afl-cc.c b/src/afl-cc.c index c1050355..ff7b5219 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1574,12 +1574,12 @@ int main(int argc, char **argv, char **envp) { else if (have_gcc_plugin) compiler_mode = GCC_PLUGIN; else if (have_gcc) - #ifdef __APPLE__ - // on OSX clang masquerades as GCC - compiler_mode = CLANG; - #else - compiler_mode = GCC; - #endif +#ifdef __APPLE__ + // on OSX clang masquerades as GCC + compiler_mode = CLANG; +#else + compiler_mode = GCC; +#endif else if (have_lto) compiler_mode = LTO; else @@ -1602,8 +1602,10 @@ int main(int argc, char **argv, char **envp) { } if (compiler_mode == CLANG) { + instrument_mode = INSTRUMENT_CLANG; - setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + } if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 4eeb93de..4a3e7f33 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -562,7 +562,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->cmplog_lvl == 3 || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || !(afl->fsrv.total_execs % afl->queued_paths) || - get_cur_time() - afl->last_path_time > 300000) { + get_cur_time() - afl->last_path_time > 300000) { // 300 seconds if (input_to_state_stage(afl, in_buf, out_buf, len)) { @@ -2013,7 +2013,7 @@ havoc_stage: } - if (unlikely(get_cur_time() - afl->last_path_time > 5000 && + if (unlikely(get_cur_time() - afl->last_path_time > 5000 /* 5 seconds */ && afl->ready_for_splicing_count > 1)) { /* add expensive havoc cases here if there is no findings in the last 5s */ @@ -3060,7 +3060,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->cmplog_lvl == 3 || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || !(afl->fsrv.total_execs % afl->queued_paths) || - get_cur_time() - afl->last_path_time > 300000) { + get_cur_time() - afl->last_path_time > 300000) { // 300 seconds if (input_to_state_stage(afl, in_buf, out_buf, len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 313263f9..4884b942 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -368,7 +368,8 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, afl->plot_prev_uh == afl->unique_hangs && afl->plot_prev_md == afl->max_depth && afl->plot_prev_ed == afl->fsrv.total_execs) || - !afl->queue_cycle || get_cur_time() - afl->start_time <= 60))) { + !afl->queue_cycle || + get_cur_time() - afl->start_time <= 60000))) { return; @@ -393,7 +394,7 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fprintf(afl->fsrv.plot_file, "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, " "%u\n", - (afl->prev_run_time + get_cur_time() - afl->start_time), + ((afl->prev_run_time + get_cur_time() - afl->start_time) / 1000), afl->queue_cycle - 1, afl->current_entry, afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8de3ed6b..094fd161 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1940,8 +1940,10 @@ int main(int argc, char **argv_orig, char **envp) { /* If we had a full queue cycle with no new finds, try recombination strategies next. */ - if (unlikely(afl->queued_paths == prev_queued && - (get_cur_time() - afl->start_time) >= 3600)) { + if (unlikely(afl->queued_paths == prev_queued + /* FIXME TODO BUG: && (get_cur_time() - afl->start_time) >= + 3600 */ + )) { if (afl->use_splicing) { -- cgit 1.4.1 From 000c72909530274cb52015fee69e9700ec6a2c7e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 15 May 2021 17:33:05 +0200 Subject: added bounds check to pivot_inputs (fixes #921) --- src/afl-fuzz-init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index cb586111..7337bfbf 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1294,9 +1294,13 @@ void pivot_inputs(afl_state_t *afl) { if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { - struct queue_entry *s = afl->queue_buf[src_id]; + if (src_id < afl->queued_paths) { - if (s) { q->depth = s->depth + 1; } + struct queue_entry *s = afl->queue_buf[src_id]; + + if (s) { q->depth = s->depth + 1; } + + } if (afl->max_depth < q->depth) { afl->max_depth = q->depth; } -- cgit 1.4.1 From 3d28925c13b5fc171b239c0c0451686967ee3bda Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 15 May 2021 18:23:13 +0200 Subject: additional safety checks for restarts --- src/afl-fuzz.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 094fd161..a4599b4a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -332,7 +332,7 @@ static int stricmp(char const *a, char const *b) { int main(int argc, char **argv_orig, char **envp) { - s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/; + s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; u64 prev_queued = 0; u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = get_map_size(); @@ -1770,7 +1770,7 @@ int main(int argc, char **argv_orig, char **envp) { if (extras_dir_cnt) { - for (i = 0; i < extras_dir_cnt; i++) { + for (u8 i = 0; i < extras_dir_cnt; i++) { load_extras(afl, extras_dir[i]); @@ -1922,6 +1922,13 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(seek_to)) { + if (unlikely(seek_to >= afl->queued_paths)) { + + // This should never happen. + FATAL("BUG: seek_to location out of bounds!\n"); + + } + afl->current_entry = seek_to; afl->queue_cur = afl->queue_buf[seek_to]; seek_to = 0; @@ -2061,7 +2068,7 @@ int main(int argc, char **argv_orig, char **envp) { } // we must recalculate the scores of all queue entries - for (i = 0; i < (s32)afl->queued_paths; i++) { + for (u32 i = 0; i < afl->queued_paths; i++) { if (likely(!afl->queue_buf[i]->disabled)) { -- cgit 1.4.1 From 7b033367c2f49b47d0a5021a9ad9a82b514429de Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 May 2021 11:02:28 +0200 Subject: restrict afl-showmap in_file size --- src/afl-showmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 946b19cd..5994101e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -386,7 +386,7 @@ static u32 read_file(u8 *in_file) { } - in_len = st.st_size; + in_len = st.st_size > MAX_FILE ? MAX_FILE : st.st_size; in_data = ck_alloc_nozero(in_len); ck_read(fd, in_data, in_len, in_file); -- cgit 1.4.1 From 738246465d07770471ec34500909ebb4c3c5f1cf Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 May 2021 13:08:05 +0200 Subject: fix seed crash disable --- src/afl-fuzz-init.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7337bfbf..c43bcc2b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1044,18 +1044,16 @@ void perform_dry_run(afl_state_t *afl) { /* Remove from fuzzing queue but keep for splicing */ - struct queue_entry *p = afl->queue; + if (!q->was_fuzzed) { - if (!p->was_fuzzed) { - - p->was_fuzzed = 1; + q->was_fuzzed = 1; --afl->pending_not_fuzzed; --afl->active_paths; } - p->disabled = 1; - p->perf_score = 0; + q->disabled = 1; + q->perf_score = 0; u32 i = 0; while (unlikely(i < afl->queued_paths && afl->queue_buf[i] && -- cgit 1.4.1 From a3fffac90cb96736395aa9764f4cc5aa20e6cd71 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 May 2021 13:11:16 +0200 Subject: add warning for afl-showmap partial read --- src/afl-showmap.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 5994101e..41a62108 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -386,7 +386,18 @@ static u32 read_file(u8 *in_file) { } - in_len = st.st_size > MAX_FILE ? MAX_FILE : st.st_size; + if (st.st_size > MAX_FILE) { + + WARNF("Input file '%s' is too large, only reading %u bytes.", in_file, + MAX_FILE); + in_len = MAX_FILE; + + } else { + + in_len = st.st_size; + + } + in_data = ck_alloc_nozero(in_len); ck_read(fd, in_data, in_len, in_file); -- cgit 1.4.1 From 47e22e8d8d383078989906c6fe54a9ec4deff8c1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 May 2021 16:52:52 +0200 Subject: no core dumps --- docs/Changelog.md | 1 + src/afl-forkserver.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index e4c02921..4fa70bfd 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -29,6 +29,7 @@ sending a mail to . - ensure one fuzzer sync per cycle - fix afl_custom_queue_new_entry original file name when syncing from fuzzers + - on a crashing seed potentially the wrong input was disabled - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in -i dir crashes the target or results in a timeout. By default afl++ ignores these and uses them for splicing instead. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a07e78b4..0286ab47 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -451,8 +451,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered before the dump is complete. */ - // r.rlim_max = r.rlim_cur = 0; - // setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + if (!fsrv->debug) { + + r.rlim_max = r.rlim_cur = 0; + setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + + } /* Isolate the process and configure standard descriptors. If out_file is specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ -- cgit 1.4.1 From ccf739f8801c373fe2aa1bb709ffd697cfe2a3e6 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 17 May 2021 18:16:41 +0200 Subject: AFL_PRINT_FILENAMES added --- afl-cmin | 2 ++ docs/Changelog.md | 1 + docs/env_variables.md | 3 ++ src/afl-showmap.c | 82 ++++++++++++++++++++++++++++----------------------- 4 files changed, 51 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/afl-cmin b/afl-cmin index 3f3a7517..adcbb221 100755 --- a/afl-cmin +++ b/afl-cmin @@ -123,6 +123,8 @@ function usage() { "AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \ +"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \ + "printed to stdout\n" \ "AFL_SKIP_BIN_CHECK: skip check for target binary\n" exit 1 } diff --git a/docs/Changelog.md b/docs/Changelog.md index 4fa70bfd..67ab9d5e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -50,6 +50,7 @@ sending a mail to . MacOS shared memory - updated the grammar custom mutator to the newest version - add -d (add dead fuzzer stats) to afl-whatsup + - added AFL_PRINT_FILENAMES to afl-showmap/cmin to print the current filename ### Version ++3.12c (release) - afl-fuzz: diff --git a/docs/env_variables.md b/docs/env_variables.md index 8879db72..99568146 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -567,6 +567,9 @@ The corpus minimization script offers very little customization: a modest security risk on multi-user systems with rogue users, but should be safe on dedicated fuzzing boxes. + - `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed. + This can help when embedding `afl-cmin` or `afl-showmap` in other scripts scripting. + ## 7) Settings for afl-tmin Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 41a62108..336ac126 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -76,17 +76,18 @@ static u32 in_len; /* Input data length */ static u32 map_size = MAP_SIZE; -static u8 quiet_mode, /* Hide non-essential messages? */ +static bool quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ raw_instr_output, /* Do not apply AFL filters */ 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 = true, /* remove shmem? */ collect_coverage, /* collect coverage */ have_coverage, /* have coverage? */ no_classify, /* do not classify counts */ - debug; /* debug mode */ + debug, /* debug mode */ + print_filenames; /* print the current filename */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -320,11 +321,11 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, if (fsrv->trace_bits[0] == 1) { fsrv->trace_bits[0] = 0; - have_coverage = 1; + have_coverage = true; } else { - have_coverage = 0; + have_coverage = false; } @@ -335,11 +336,11 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(fsrv->child_status)) { - child_crashed = 1; + child_crashed = true; } else { - child_crashed = 0; + child_crashed = false; } @@ -375,6 +376,8 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, static u32 read_file(u8 *in_file) { + if (print_filenames) { SAYF("Processing %s\n", in_file); } + struct stat st; s32 fd = open(in_file, O_RDONLY); @@ -515,11 +518,11 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { if (fsrv->trace_bits[0] == 1) { fsrv->trace_bits[0] = 0; - have_coverage = 1; + have_coverage = true; } else { - have_coverage = 0; + have_coverage = false; } @@ -529,7 +532,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) { - child_crashed = 1; + child_crashed = true; } @@ -559,7 +562,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { static void handle_stop_sig(int sig) { (void)sig; - stop_soon = 1; + stop_soon = true; afl_fsrv_killall(); } @@ -742,6 +745,8 @@ static void usage(u8 *argv0) { "AFL_MAP_SIZE: the shared memory size for that target. must be >= the " "size the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" + "AFL_PRINT_FILENAMES: If set, the filename currently processed will be " + "printed to stdout\n" "AFL_QUIET: do not print extra informational output\n", argv0, MEM_LIMIT, doc_path); @@ -755,14 +760,17 @@ int main(int argc, char **argv_orig, char **envp) { // TODO: u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ - s32 opt, i; - u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; + s32 opt, i; + bool mem_limit_given = false, timeout_given = false, unicorn_mode = false, + use_wine = false; char **use_argv; char **argv = argv_cpy_dup(argc, argv_orig); afl_forkserver_t fsrv_var = {0}; - if (getenv("AFL_DEBUG")) { debug = 1; } + if (getenv("AFL_DEBUG")) { debug = true; } + if (getenv("AFL_PRINT_FILENAMES")) { print_filenames = true; } + fsrv = &fsrv_var; afl_fsrv_init(fsrv); map_size = get_map_size(); @@ -770,19 +778,19 @@ int main(int argc, char **argv_orig, char **envp) { doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; } + if (getenv("AFL_QUIET") != NULL) { be_quiet = true; } while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) { switch (opt) { case 's': - no_classify = 1; + no_classify = true; break; case 'C': - collect_coverage = 1; - quiet_mode = 1; + collect_coverage = true; + quiet_mode = true; break; case 'i': @@ -801,7 +809,7 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 'M'; if (mem_limit_given) { FATAL("Multiple -m options not supported"); } - mem_limit_given = 1; + mem_limit_given = true; if (!optarg) { FATAL("Wrong usage of -m"); } @@ -862,7 +870,7 @@ int main(int argc, char **argv_orig, char **envp) { case 't': if (timeout_given) { FATAL("Multiple -t options not supported"); } - timeout_given = 1; + timeout_given = true; if (!optarg) { FATAL("Wrong usage of -t"); } @@ -884,12 +892,12 @@ int main(int argc, char **argv_orig, char **envp) { if (edges_only) { FATAL("Multiple -e options not supported"); } if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); } - edges_only = 1; + edges_only = true; break; case 'q': - quiet_mode = 1; + quiet_mode = true; break; case 'Z': @@ -897,8 +905,8 @@ int main(int argc, char **argv_orig, char **envp) { /* This is an undocumented option to write data in the syntax expected by afl-cmin. Nobody else should have any use for this. */ - cmin_mode = 1; - quiet_mode = 1; + cmin_mode = true; + quiet_mode = true; break; case 'A': @@ -910,7 +918,7 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); } - fsrv->frida_mode = 1; + fsrv->frida_mode = true; break; @@ -918,21 +926,21 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } - fsrv->qemu_mode = 1; + fsrv->qemu_mode = true; break; case 'U': if (unicorn_mode) { FATAL("Multiple -U options not supported"); } - unicorn_mode = 1; + unicorn_mode = true; break; case 'W': /* Wine+QEMU mode */ if (use_wine) { FATAL("Multiple -W options not supported"); } - fsrv->qemu_mode = 1; - use_wine = 1; + fsrv->qemu_mode = true; + use_wine = true; break; @@ -941,20 +949,20 @@ int main(int argc, char **argv_orig, char **envp) { /* Secret undocumented mode. Writes output in raw binary format similar to that dumped by afl-fuzz in cmplog_mode = 0; u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1); - shm_fuzz->shmemfuzz_mode = 1; + shm_fuzz->shmemfuzz_mode = true; if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } #ifdef USEMMAP setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1); @@ -1073,7 +1081,7 @@ int main(int argc, char **argv_orig, char **envp) { setenv(SHM_FUZZ_ENV_VAR, shm_str, 1); ck_free(shm_str); #endif - fsrv->support_shmem_fuzz = 1; + fsrv->support_shmem_fuzz = true; fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz = map + sizeof(u32); @@ -1125,7 +1133,7 @@ int main(int argc, char **argv_orig, char **envp) { struct stat statbuf; #endif - if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = 1; + if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true; fsrv->dev_null_fd = open("/dev/null", O_RDWR); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } @@ -1164,8 +1172,8 @@ int main(int argc, char **argv_orig, char **envp) { if ((coverage_map = (u8 *)malloc(map_size)) == NULL) FATAL("coult not grab memory"); - edges_only = 0; - raw_instr_output = 1; + edges_only = false; + raw_instr_output = true; } -- cgit 1.4.1 From 9d50ae7468970412177c9e08edf7f32ff9fdf1ce Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 17 May 2021 18:54:24 +0200 Subject: Flushing for AFL_PRINT_FILENAMES --- src/afl-forkserver.c | 2 +- src/afl-showmap.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 0286ab47..3d472b36 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -454,7 +454,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!fsrv->debug) { r.rlim_max = r.rlim_cur = 0; - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 336ac126..10818905 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -376,7 +376,12 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, static u32 read_file(u8 *in_file) { - if (print_filenames) { SAYF("Processing %s\n", in_file); } + if (print_filenames) { + + SAYF("Processing %s\n", in_file); + fflush(stdout); + + } struct stat st; s32 fd = open(in_file, O_RDONLY); -- cgit 1.4.1 From e40c0c2da16f14dfddb5641f6f825903879534a9 Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Mon, 17 May 2021 19:02:45 +0100 Subject: FASAN Support (#918) * FASAN Support * Fix handling of Address Sanitizer DSO * Changes to identification of Address Sanitizer DSO Co-authored-by: Your Name --- frida_mode/include/asan.h | 13 +++ frida_mode/include/ctx.h | 11 +++ frida_mode/src/asan/asan.c | 24 +++++ frida_mode/src/asan/asan_arm.c | 22 +++++ frida_mode/src/asan/asan_arm64.c | 22 +++++ frida_mode/src/asan/asan_x64.c | 93 ++++++++++++++++++++ frida_mode/src/asan/asan_x86.c | 22 +++++ frida_mode/src/cmplog/cmplog_x64.c | 119 ++----------------------- frida_mode/src/ctx/ctx_x64.c | 114 ++++++++++++++++++++++++ frida_mode/src/instrument/instrument.c | 3 + frida_mode/test/fasan/GNUmakefile | 156 +++++++++++++++++++++++++++++++++ frida_mode/test/fasan/Makefile | 18 ++++ frida_mode/test/fasan/test.c | 85 ++++++++++++++++++ include/envs.h | 1 + include/forkserver.h | 2 + src/afl-fuzz.c | 81 ++++++++++++++--- 16 files changed, 664 insertions(+), 122 deletions(-) create mode 100644 frida_mode/include/asan.h create mode 100644 frida_mode/include/ctx.h create mode 100644 frida_mode/src/asan/asan.c create mode 100644 frida_mode/src/asan/asan_arm.c create mode 100644 frida_mode/src/asan/asan_arm64.c create mode 100644 frida_mode/src/asan/asan_x64.c create mode 100644 frida_mode/src/asan/asan_x86.c create mode 100644 frida_mode/src/ctx/ctx_x64.c create mode 100644 frida_mode/test/fasan/GNUmakefile create mode 100644 frida_mode/test/fasan/Makefile create mode 100644 frida_mode/test/fasan/test.c (limited to 'src') diff --git a/frida_mode/include/asan.h b/frida_mode/include/asan.h new file mode 100644 index 00000000..7a8726e0 --- /dev/null +++ b/frida_mode/include/asan.h @@ -0,0 +1,13 @@ +#ifndef _ASAN_H +#define _ASAN_H + +#include "frida-gum.h" + +extern gboolean asan_initialized; + +void asan_init(void); +void asan_arch_init(void); +void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator); + +#endif + diff --git a/frida_mode/include/ctx.h b/frida_mode/include/ctx.h new file mode 100644 index 00000000..030d124a --- /dev/null +++ b/frida_mode/include/ctx.h @@ -0,0 +1,11 @@ +#ifndef _CTX_H +#define _CTX_H + +#include "frida-gum.h" + +#if defined(__x86_64__) +guint64 ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg); +#endif + +#endif + diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c new file mode 100644 index 00000000..f78f690c --- /dev/null +++ b/frida_mode/src/asan/asan.c @@ -0,0 +1,24 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "asan.h" + +gboolean asan_initialized = FALSE; + +void asan_init(void) { + + if (getenv("AFL_USE_FASAN") != NULL) { + + OKF("Frida ASAN mode enabled"); + asan_arch_init(); + asan_initialized = TRUE; + + } else { + + OKF("Frida ASAN mode disabled"); + + } + +} + diff --git a/frida_mode/src/asan/asan_arm.c b/frida_mode/src/asan/asan_arm.c new file mode 100644 index 00000000..526017be --- /dev/null +++ b/frida_mode/src/asan/asan_arm.c @@ -0,0 +1,22 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "asan.h" +#include "util.h" + +#if defined(__arm__) +void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(iterator); + if (asan_initialized) { + + FATAL("ASAN mode not supported on this architecture"); + + } + +} + +#endif + diff --git a/frida_mode/src/asan/asan_arm64.c b/frida_mode/src/asan/asan_arm64.c new file mode 100644 index 00000000..4e3fbafd --- /dev/null +++ b/frida_mode/src/asan/asan_arm64.c @@ -0,0 +1,22 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "asan.h" +#include "util.h" + +#if defined(__aarch64__) +void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(iterator); + if (asan_initialized) { + + FATAL("ASAN mode not supported on this architecture"); + + } + +} + +#endif + diff --git a/frida_mode/src/asan/asan_x64.c b/frida_mode/src/asan/asan_x64.c new file mode 100644 index 00000000..bdf4ac30 --- /dev/null +++ b/frida_mode/src/asan/asan_x64.c @@ -0,0 +1,93 @@ +#include +#include "frida-gum.h" + +#include "debug.h" + +#include "asan.h" +#include "ctx.h" +#include "util.h" + +typedef void (*asan_loadN_t)(uint64_t address, uint8_t size); +typedef void (*asan_storeN_t)(uint64_t address, uint8_t size); + +asan_loadN_t asan_loadN = NULL; +asan_storeN_t asan_storeN = NULL; + +#if defined(__x86_64__) + +static void asan_callout(GumCpuContext *ctx, gpointer user_data) { + + UNUSED_PARAMETER(user_data); + + cs_x86_op * operand = (cs_x86_op *)user_data; + x86_op_mem *mem = &operand->mem; + uint64_t base = 0; + uint64_t index = 0; + uint64_t address; + uint8_t size; + + if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); } + + if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); } + + address = base + (mem->scale * index) + mem->disp; + size = operand->size; + + if (operand->access == CS_AC_READ) { + + asan_loadN(address, size); + + } else if (operand->access == CS_AC_WRITE) { + + asan_storeN(address, size); + + } + +} + +void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { + + UNUSED_PARAMETER(iterator); + + cs_x86 x86 = instr->detail->x86; + cs_x86_op * operand; + x86_op_mem *mem; + cs_x86_op * ctx; + + if (!asan_initialized) return; + + if (instr->id == X86_INS_LEA) return; + + if (instr->id == X86_INS_NOP) return; + + for (uint8_t i = 0; i < x86.op_count; i++) { + + operand = &x86.operands[i]; + + if (operand->type != X86_OP_MEM) { continue; } + + mem = &operand->mem; + if (mem->segment != X86_REG_INVALID) { continue; } + + ctx = g_malloc0(sizeof(cs_x86_op)); + memcpy(ctx, operand, sizeof(cs_x86_op)); + gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free); + + } + +} + +void asan_arch_init(void) { + + asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN"); + asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN"); + if (asan_loadN == NULL || asan_storeN == NULL) { + + FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'"); + + } + +} + +#endif + diff --git a/frida_mode/src/asan/asan_x86.c b/frida_mode/src/asan/asan_x86.c new file mode 100644 index 00000000..b946b3bf --- /dev/null +++ b/frida_mode/src/asan/asan_x86.c @@ -0,0 +1,22 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "asan.h" +#include "util.h" + +#if defined(__i386__) +void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(iterator); + if (asan_initialized) { + + FATAL("ASAN mode not supported on this architecture"); + + } + +} + +#endif + diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c index 4d8f243a..c3621a29 100644 --- a/frida_mode/src/cmplog/cmplog_x64.c +++ b/frida_mode/src/cmplog/cmplog_x64.c @@ -3,46 +3,12 @@ #include "debug.h" #include "cmplog.h" +#include "ctx.h" #include "frida_cmplog.h" #include "util.h" #if defined(__x86_64__) - #define X86_REG_8L(LABEL, REG) \ - case LABEL: { \ - \ - return REG & GUM_INT8_MASK; \ - \ - } - - #define X86_REG_8H(LABEL, REG) \ - case LABEL: { \ - \ - return (REG & GUM_INT16_MASK) >> 8; \ - \ - } - - #define X86_REG_16(LABEL, REG) \ - case LABEL: { \ - \ - return (REG & GUM_INT16_MASK); \ - \ - } - - #define X86_REG_32(LABEL, REG) \ - case LABEL: { \ - \ - return (REG & GUM_INT32_MASK); \ - \ - } - - #define X86_REG_64(LABEL, REG) \ - case LABEL: { \ - \ - return (REG); \ - \ - } - typedef struct { x86_op_type type; @@ -65,75 +31,6 @@ typedef struct { } cmplog_pair_ctx_t; -static guint64 cmplog_read_reg(GumX64CpuContext *ctx, x86_reg reg) { - - switch (reg) { - - X86_REG_8L(X86_REG_AL, ctx->rax) - X86_REG_8L(X86_REG_BL, ctx->rbx) - X86_REG_8L(X86_REG_CL, ctx->rcx) - X86_REG_8L(X86_REG_DL, ctx->rdx) - X86_REG_8L(X86_REG_BPL, ctx->rbp) - X86_REG_8L(X86_REG_SIL, ctx->rsi) - X86_REG_8L(X86_REG_DIL, ctx->rdi) - - X86_REG_8H(X86_REG_AH, ctx->rax) - X86_REG_8H(X86_REG_BH, ctx->rbx) - X86_REG_8H(X86_REG_CH, ctx->rcx) - X86_REG_8H(X86_REG_DH, ctx->rdx) - - X86_REG_16(X86_REG_AX, ctx->rax) - X86_REG_16(X86_REG_BX, ctx->rbx) - X86_REG_16(X86_REG_CX, ctx->rcx) - X86_REG_16(X86_REG_DX, ctx->rdx) - X86_REG_16(X86_REG_DI, ctx->rdi) - X86_REG_16(X86_REG_SI, ctx->rsi) - X86_REG_16(X86_REG_BP, ctx->rbp) - - X86_REG_32(X86_REG_EAX, ctx->rax) - X86_REG_32(X86_REG_ECX, ctx->rcx) - X86_REG_32(X86_REG_EDX, ctx->rdx) - X86_REG_32(X86_REG_EBX, ctx->rbx) - X86_REG_32(X86_REG_ESP, ctx->rsp) - X86_REG_32(X86_REG_EBP, ctx->rbp) - X86_REG_32(X86_REG_ESI, ctx->rsi) - X86_REG_32(X86_REG_EDI, ctx->rdi) - X86_REG_32(X86_REG_R8D, ctx->r8) - X86_REG_32(X86_REG_R9D, ctx->r9) - X86_REG_32(X86_REG_R10D, ctx->r10) - X86_REG_32(X86_REG_R11D, ctx->r11) - X86_REG_32(X86_REG_R12D, ctx->r12) - X86_REG_32(X86_REG_R13D, ctx->r13) - X86_REG_32(X86_REG_R14D, ctx->r14) - X86_REG_32(X86_REG_R15D, ctx->r15) - X86_REG_32(X86_REG_EIP, ctx->rip) - - X86_REG_64(X86_REG_RAX, ctx->rax) - X86_REG_64(X86_REG_RCX, ctx->rcx) - X86_REG_64(X86_REG_RDX, ctx->rdx) - X86_REG_64(X86_REG_RBX, ctx->rbx) - X86_REG_64(X86_REG_RSP, ctx->rsp) - X86_REG_64(X86_REG_RBP, ctx->rbp) - X86_REG_64(X86_REG_RSI, ctx->rsi) - X86_REG_64(X86_REG_RDI, ctx->rdi) - X86_REG_64(X86_REG_R8, ctx->r8) - X86_REG_64(X86_REG_R9, ctx->r9) - X86_REG_64(X86_REG_R10, ctx->r10) - X86_REG_64(X86_REG_R11, ctx->r11) - X86_REG_64(X86_REG_R12, ctx->r12) - X86_REG_64(X86_REG_R13, ctx->r13) - X86_REG_64(X86_REG_R14, ctx->r14) - X86_REG_64(X86_REG_R15, ctx->r15) - X86_REG_64(X86_REG_RIP, ctx->rip) - - default: - FATAL("Failed to read register: %d", reg); - return 0; - - } - -} - static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size, x86_op_mem *mem, guint64 *val) { @@ -141,9 +38,9 @@ static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size, guint64 index = 0; guint64 address; - if (mem->base != X86_REG_INVALID) base = cmplog_read_reg(ctx, mem->base); + if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base); - if (mem->index != X86_REG_INVALID) index = cmplog_read_reg(ctx, mem->index); + if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index); address = base + (index * mem->scale) + mem->disp; @@ -178,7 +75,7 @@ static gboolean cmplog_get_operand_value(GumCpuContext *context, switch (ctx->type) { case X86_OP_REG: - *val = cmplog_read_reg(context, ctx->reg); + *val = ctx_read_reg(context, ctx->reg); return TRUE; case X86_OP_IMM: *val = ctx->imm; @@ -198,9 +95,9 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) { UNUSED_PARAMETER(user_data); - guint64 address = cmplog_read_reg(context, X86_REG_RIP); - guint64 rdi = cmplog_read_reg(context, X86_REG_RDI); - guint64 rsi = cmplog_read_reg(context, X86_REG_RSI); + guint64 address = ctx_read_reg(context, X86_REG_RIP); + guint64 rdi = ctx_read_reg(context, X86_REG_RDI); + guint64 rsi = ctx_read_reg(context, X86_REG_RSI); if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return; @@ -275,7 +172,7 @@ static void cmplog_instrument_call(const cs_insn * instr, static void cmplog_handle_cmp_sub(GumCpuContext *context, guint64 operand1, guint64 operand2, uint8_t size) { - guint64 address = cmplog_read_reg(context, X86_REG_RIP); + guint64 address = ctx_read_reg(context, X86_REG_RIP); register uintptr_t k = (uintptr_t)address; diff --git a/frida_mode/src/ctx/ctx_x64.c b/frida_mode/src/ctx/ctx_x64.c new file mode 100644 index 00000000..dec759f4 --- /dev/null +++ b/frida_mode/src/ctx/ctx_x64.c @@ -0,0 +1,114 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "ctx.h" + +#if defined(__x86_64__) + + #define X86_REG_8L(LABEL, REG) \ + case LABEL: { \ + \ + return REG & GUM_INT8_MASK; \ + \ + } + + #define X86_REG_8H(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT16_MASK) >> 8; \ + \ + } + + #define X86_REG_16(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT16_MASK); \ + \ + } + + #define X86_REG_32(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT32_MASK); \ + \ + } + + #define X86_REG_64(LABEL, REG) \ + case LABEL: { \ + \ + return (REG); \ + \ + } + +guint64 ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) { + + switch (reg) { + + X86_REG_8L(X86_REG_AL, ctx->rax) + X86_REG_8L(X86_REG_BL, ctx->rbx) + X86_REG_8L(X86_REG_CL, ctx->rcx) + X86_REG_8L(X86_REG_DL, ctx->rdx) + X86_REG_8L(X86_REG_BPL, ctx->rbp) + X86_REG_8L(X86_REG_SIL, ctx->rsi) + X86_REG_8L(X86_REG_DIL, ctx->rdi) + + X86_REG_8H(X86_REG_AH, ctx->rax) + X86_REG_8H(X86_REG_BH, ctx->rbx) + X86_REG_8H(X86_REG_CH, ctx->rcx) + X86_REG_8H(X86_REG_DH, ctx->rdx) + + X86_REG_16(X86_REG_AX, ctx->rax) + X86_REG_16(X86_REG_BX, ctx->rbx) + X86_REG_16(X86_REG_CX, ctx->rcx) + X86_REG_16(X86_REG_DX, ctx->rdx) + X86_REG_16(X86_REG_DI, ctx->rdi) + X86_REG_16(X86_REG_SI, ctx->rsi) + X86_REG_16(X86_REG_BP, ctx->rbp) + + X86_REG_32(X86_REG_EAX, ctx->rax) + X86_REG_32(X86_REG_ECX, ctx->rcx) + X86_REG_32(X86_REG_EDX, ctx->rdx) + X86_REG_32(X86_REG_EBX, ctx->rbx) + X86_REG_32(X86_REG_ESP, ctx->rsp) + X86_REG_32(X86_REG_EBP, ctx->rbp) + X86_REG_32(X86_REG_ESI, ctx->rsi) + X86_REG_32(X86_REG_EDI, ctx->rdi) + X86_REG_32(X86_REG_R8D, ctx->r8) + X86_REG_32(X86_REG_R9D, ctx->r9) + X86_REG_32(X86_REG_R10D, ctx->r10) + X86_REG_32(X86_REG_R11D, ctx->r11) + X86_REG_32(X86_REG_R12D, ctx->r12) + X86_REG_32(X86_REG_R13D, ctx->r13) + X86_REG_32(X86_REG_R14D, ctx->r14) + X86_REG_32(X86_REG_R15D, ctx->r15) + X86_REG_32(X86_REG_EIP, ctx->rip) + + X86_REG_64(X86_REG_RAX, ctx->rax) + X86_REG_64(X86_REG_RCX, ctx->rcx) + X86_REG_64(X86_REG_RDX, ctx->rdx) + X86_REG_64(X86_REG_RBX, ctx->rbx) + X86_REG_64(X86_REG_RSP, ctx->rsp) + X86_REG_64(X86_REG_RBP, ctx->rbp) + X86_REG_64(X86_REG_RSI, ctx->rsi) + X86_REG_64(X86_REG_RDI, ctx->rdi) + X86_REG_64(X86_REG_R8, ctx->r8) + X86_REG_64(X86_REG_R9, ctx->r9) + X86_REG_64(X86_REG_R10, ctx->r10) + X86_REG_64(X86_REG_R11, ctx->r11) + X86_REG_64(X86_REG_R12, ctx->r12) + X86_REG_64(X86_REG_R13, ctx->r13) + X86_REG_64(X86_REG_R14, ctx->r14) + X86_REG_64(X86_REG_R15, ctx->r15) + X86_REG_64(X86_REG_RIP, ctx->rip) + + default: + FATAL("Failed to read register: %d", reg); + return 0; + + } + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 971f80c0..5c77ade6 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -5,6 +5,7 @@ #include "config.h" #include "debug.h" +#include "asan.h" #include "entry.h" #include "frida_cmplog.h" #include "instrument.h" @@ -107,6 +108,7 @@ static void instr_basic_block(GumStalkerIterator *iterator, if (!range_is_excluded((void *)instr->address)) { + asan_instrument(instr, iterator); cmplog_instrument(instr, iterator); } @@ -142,6 +144,7 @@ void instrument_init(void) { transformer = gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL); + asan_init(); cmplog_init(); } diff --git a/frida_mode/test/fasan/GNUmakefile b/frida_mode/test/fasan/GNUmakefile new file mode 100644 index 00000000..22689395 --- /dev/null +++ b/frida_mode/test/fasan/GNUmakefile @@ -0,0 +1,156 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +TEST_DATA_FILE:=$(TEST_DATA_DIR)in +FRIDA_OUT:=$(BUILD_DIR)frida-out + +TEST_SRC:=$(PWD)/test.c +TEST_BIN:=$(BUILD_DIR)test + +CFLAGS+=-fPIC \ + -D_GNU_SOURCE \ + -g \ + -fno-omit-frame-pointer \ + -Wno-stringop-overflow \ + +LDFLAGS+=-ldl \ + +ifdef DEBUG +CFLAGS+=-Werror \ + -Wall \ + -Wextra \ + -Wpointer-arith +else +CFLAGS+=-Wno-pointer-arith +endif + +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + +ifeq "$(ARCH)" "x86" +LIBASAN_FILE:=libclang_rt.asan-i386.so +endif + +ifeq "$(ARCH)" "x64" +LIBASAN_FILE:=libclang_rt.asan-x86_64.so +endif + +ifeq "$(ARCH)" "aarch64" +LIBASAN_FILE:=libclang_rt.asan-aarch64.so +endif + +# LIBASAN:=/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.so +# LIBASAN:=/usr/lib/x86_64-linux-gnu/libasan.so.6.0.0 + +LLVM_CONFIG ?= llvm-config +ifeq "$(shell test -e '$(shell which $(LLVM_CONFIG))' && echo 1)" "1" + $(info Found llvm-config: '$(shell which $(LLVM_CONFIG))') +else + $(warning Cannot find llvm-config) +endif + +LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)/ +$(info LLVM_BINDIR: $(LLVM_BINDIR)) + +CLANG ?= $(LLVM_BINDIR)clang +ifeq "$(shell test -e '$(CLANG)' && echo 1)" "1" + $(info Found clang: '$(CLANG)') +else + $(warning Cannot find clang) +endif + +CLANGVER = $(shell $(CLANG) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p') +$(info Clang version $(CLANGVER)) + +LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) +$(info LLVM_LIBDIR: $(LLVM_LIBDIR)) + +LIBASAN:=$(LLVM_LIBDIR)/clang/$(CLANGVER)/lib/linux/$(LIBASAN_FILE) + +ifeq "$(shell test -e '$(LIBASAN)' && echo 1)" "1" + $(info Found Address Sanitizer DSO: '$(LIBASAN)') +else + $(error Error cannot find Address Sanitizer DSO) +endif + + +.PHONY: all clean format frida-noasan frida debug run + +############################## ALL ############################################# + +all: $(TEST_BIN) + +$(TEST_BIN): $(TEST_SRC) GNUmakefile | $(BUILD_DIR) + $(CC) \ + $(CFLAGS) \ + $(LDFLAGS) \ + -o $@ \ + $< + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +############################# TESTS ############################################ + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo -n "TUODATM" > $@ + +frida-noasan: $(TEST_BIN) $(TEST_DATA_FILE) + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) + + +frida: $(TEST_BIN) $(TEST_DATA_FILE) + AFL_PRELOAD=/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.so \ + AFL_USE_FASAN=1 \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) + +debug: $(TEST_BIN) $(TEST_DATA_FILE) + gdb \ + --ex 'set environment LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so' \ + --ex 'set environment ASAN_OPTIONS=detect_leaks=false,halt_on_error=0' \ + --ex 'set environment AFL_USE_FASAN=1' \ + --ex 'set disassembly-flavor intel' \ + --ex 'r < $(TEST_DATA_FILE)' \ + --args $(TEST_BIN) \ + +run: $(TEST_BIN) $(TEST_DATA_FILE) + LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so \ + ASAN_OPTIONS=detect_leaks=false \ + AFL_USE_FASAN=1 \ + $(TEST_BIN) < $(TEST_DATA_FILE) + +############################# CLEAN ############################################ +clean: + rm -rf $(BUILD_DIR) + +############################# FORMAT ########################################### +format: + cd $(ROOT) && echo $(TEST_SRC) | xargs -L1 ./.custom-format.py -i + +############################# RUN ############################################# diff --git a/frida_mode/test/fasan/Makefile b/frida_mode/test/fasan/Makefile new file mode 100644 index 00000000..a7bf44c7 --- /dev/null +++ b/frida_mode/test/fasan/Makefile @@ -0,0 +1,18 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +clean: + @gmake clean + +frida-noasan: + @gmake frida-noasan + +frida: + @gmake frida + +debug: + @gmake debug + +run: + @gmake run \ No newline at end of file diff --git a/frida_mode/test/fasan/test.c b/frida_mode/test/fasan/test.c new file mode 100644 index 00000000..a7d03017 --- /dev/null +++ b/frida_mode/test/fasan/test.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include + +#define LOG(x) \ + do { \ + \ + char buf[] = x; \ + write(STDOUT_FILENO, buf, sizeof(buf)); \ + \ + } while (false); + +void test(char data) { + + char *buf = malloc(10); + + if (buf == NULL) return; + + switch (data) { + + /* Underflow */ + case 'U': + LOG("Underflow\n"); + buf[-1] = '\0'; + free(buf); + break; + /* Overflow */ + case 'O': + LOG("Overflow\n"); + buf[10] = '\0'; + free(buf); + break; + /* Double free */ + case 'D': + LOG("Double free\n"); + free(buf); + free(buf); + break; + /* Use after free */ + case 'A': + LOG("Use after free\n"); + free(buf); + buf[0] = '\0'; + break; + /* Test Limits (OK) */ + case 'T': + LOG("Test-Limits - No Error\n"); + buf[0] = 'A'; + buf[9] = 'I'; + free(buf); + break; + case 'M': + LOG("Memset too many\n"); + memset(buf, '\0', 11); + free(buf); + break; + default: + LOG("Nop - No Error\n"); + break; + + } + +} + +int main(int argc, char **argv) { + + char input = '\0'; + + if (read(STDIN_FILENO, &input, 1) < 0) { + + LOG("Failed to read stdin\n"); + return 1; + + } + + test(input); + + LOG("DONE\n"); + return 0; + +} + diff --git a/include/envs.h b/include/envs.h index 9175005e..4fff1e3a 100644 --- a/include/envs.h +++ b/include/envs.h @@ -191,6 +191,7 @@ static char *afl_environment_variables[] = { "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", + "AFL_USE_FASAN", "AFL_USE_QASAN", NULL diff --git a/include/forkserver.h b/include/forkserver.h index 48db94c7..2baa6f0a 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -79,6 +79,8 @@ typedef struct afl_forkserver { bool frida_mode; /* if running in frida mode or not */ + bool frida_asan; /* if running with asan in frida mode */ + bool use_stdin; /* use stdin for sending data */ bool no_unlink; /* do not unlink cur_input */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a4599b4a..903068b2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -328,6 +328,50 @@ static int stricmp(char const *a, char const *b) { } +static void fasan_check_afl_preload(char *afl_preload) { + + char first_preload[PATH_MAX + 1] = {0}; + char * separator = strchr(afl_preload, ':'); + size_t first_preload_len = PATH_MAX; + char * basename; + char clang_runtime_prefix[] = "libclang_rt.asan-"; + + if (separator != NULL && (separator - afl_preload) < PATH_MAX) { + + first_preload_len = separator - afl_preload; + + } + + strncpy(first_preload, afl_preload, first_preload_len); + + basename = strrchr(first_preload, '/'); + if (basename == NULL) { + + basename = first_preload; + + } else { + + basename = basename + 1; + + } + + if (strncmp(basename, clang_runtime_prefix, + sizeof(clang_runtime_prefix) - 1) != 0) { + + FATAL("Address Sanitizer DSO must be the first DSO in AFL_PRELOAD"); + + } + + if (access(first_preload, R_OK) != 0) { + + FATAL("Address Sanitizer DSO not found"); + + } + + OKF("Found ASAN DSO: %s", first_preload); + +} + /* Main entry point */ int main(int argc, char **argv_orig, char **envp) { @@ -785,6 +829,7 @@ int main(int argc, char **argv_orig, char **envp) { } afl->fsrv.frida_mode = 1; + if (get_afl_env("AFL_USE_FASAN")) { afl->fsrv.frida_asan = 1; } break; @@ -1365,18 +1410,21 @@ int main(int argc, char **argv_orig, char **envp) { } else if (afl->fsrv.frida_mode) { afl_preload = getenv("AFL_PRELOAD"); - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - OKF("Injecting %s ...", frida_binary); - if (afl_preload) { - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); + if (afl->fsrv.frida_asan) { - } else { + OKF("Using Frida Address Sanitizer Mode"); + + fasan_check_afl_preload(afl_preload); - frida_afl_preload = alloc_printf("%s", frida_binary); + setenv("ASAN_OPTIONS", "detect_leaks=false", 1); } + u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); + frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); + ck_free(frida_binary); setenv("LD_PRELOAD", frida_afl_preload, 1); @@ -1391,11 +1439,22 @@ int main(int argc, char **argv_orig, char **envp) { } else if (afl->fsrv.frida_mode) { - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - OKF("Injecting %s ...", frida_binary); - setenv("LD_PRELOAD", frida_binary, 1); - setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); - ck_free(frida_binary); + if (afl->fsrv.frida_asan) { + + OKF("Using Frida Address Sanitizer Mode"); + FATAL( + "Address Sanitizer DSO must be loaded using AFL_PRELOAD in Frida " + "Address Sanitizer Mode"); + + } else { + + u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); + setenv("LD_PRELOAD", frida_binary, 1); + setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); + ck_free(frida_binary); + + } } -- cgit 1.4.1 From d776d40669eb36cbfabeeeca55d4343413e2285b Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 19 May 2021 14:50:41 +0200 Subject: merge --- src/afl-fuzz.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 903068b2..1ac2e8ff 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1410,6 +1410,9 @@ int main(int argc, char **argv_orig, char **envp) { } else if (afl->fsrv.frida_mode) { afl_preload = getenv("AFL_PRELOAD"); + u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); + if (afl_preload) { if (afl->fsrv.frida_asan) { -- cgit 1.4.1 From dee64e74a8f5320e4fc86d6e6597c5f4b07d4ef7 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 19 May 2021 15:03:45 +0200 Subject: fix afl-fuzz.c frida preload --- src/afl-fuzz.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1ac2e8ff..eff25c91 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1414,24 +1414,26 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Injecting %s ...", frida_binary); if (afl_preload) { - if (afl->fsrv.frida_asan) { + if (afl->fsrv.frida_asan) { - OKF("Using Frida Address Sanitizer Mode"); + OKF("Using Frida Address Sanitizer Mode"); - fasan_check_afl_preload(afl_preload); + fasan_check_afl_preload(afl_preload); - setenv("ASAN_OPTIONS", "detect_leaks=false", 1); + setenv("ASAN_OPTIONS", "detect_leaks=false", 1); - } + } - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - OKF("Injecting %s ...", frida_binary); - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); + u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); + OKF("Injecting %s ...", frida_binary); + frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); - ck_free(frida_binary); + ck_free(frida_binary); - setenv("LD_PRELOAD", frida_afl_preload, 1); - setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); + setenv("LD_PRELOAD", frida_afl_preload, 1); + setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); + + } } else { -- cgit 1.4.1 From cdae3d3d038a28f1096ab6d34128896c19ef4733 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 19 May 2021 22:21:46 +0200 Subject: cleaned up AFL_PRINT_FILENAMES env --- include/envs.h | 1 + src/afl-fuzz.c | 2 +- src/afl-showmap.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/include/envs.h b/include/envs.h index 4fff1e3a..f1314bad 100644 --- a/include/envs.h +++ b/include/envs.h @@ -193,6 +193,7 @@ static char *afl_environment_variables[] = { "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN", + "AFL_PRINT_FILENAMES", NULL }; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index eff25c91..5f939115 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1432,7 +1432,7 @@ int main(int argc, char **argv_orig, char **envp) { setenv("LD_PRELOAD", frida_afl_preload, 1); setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); - + } } else { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 10818905..9b4d21a5 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -774,7 +774,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_forkserver_t fsrv_var = {0}; if (getenv("AFL_DEBUG")) { debug = true; } - if (getenv("AFL_PRINT_FILENAMES")) { print_filenames = true; } + if (get_afl_env("AFL_PRINT_FILENAMES")) { print_filenames = true; } fsrv = &fsrv_var; afl_fsrv_init(fsrv); -- cgit 1.4.1 From bceae827549beaa7721a847976d277f644ab93c6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 May 2021 12:24:58 +0200 Subject: improve error msg --- src/afl-fuzz-init.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index c43bcc2b..b277802b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2728,11 +2728,15 @@ void check_binary(afl_state_t *afl, u8 *fname) { " When source code is not available, you may be able to leverage " "QEMU\n" " mode support. Consult the README.md for tips on how to enable " - "this.\n" + "this.\n\n" + + " If your target is an instrumented binary (e.g. with zafl, " + "retrowrite,\n" + " etc.) then set 'AFL_SKIP_BIN_CHECK=1'\n\n" " (It is also possible to use afl-fuzz as a traditional, " - "non-instrumented fuzzer.\n" - " For that, you can use the -n option - but expect much worse " + "non-instrumented\n" + " fuzzer. For that use the -n option - but expect much worse " "results.)\n", doc_path); -- cgit 1.4.1 From 1edb89be0f7956f964d2d7c9c7a5813250108220 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 21 May 2021 22:40:36 +0200 Subject: showmap passes queue items in alphabetical order --- src/afl-showmap.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 9b4d21a5..9bf84956 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -52,6 +52,7 @@ #include #include +#include #include #include #ifndef USEMMAP @@ -1129,8 +1130,9 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir) { - DIR * dir_in, *dir_out = NULL; - struct dirent *dir_ent; + DIR * dir_in, *dir_out = NULL; + struct dirent **file_list; + // int done = 0; u8 infile[PATH_MAX], outfile[PATH_MAX]; u8 wait_for_gdb = 0; @@ -1155,12 +1157,6 @@ int main(int argc, char **argv_orig, char **envp) { 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 (!collect_coverage) { if (!(dir_out = opendir(out_file))) { @@ -1246,7 +1242,16 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - while ((dir_ent = readdir(dir_in))) { + int file_count = scandir(in_dir, &file_list, NULL, alphasort); + if (file_count < 0) { + + PFATAL("Failed to read from input dir at %s\n", in_dir); + + } + + for (int i = 0; i < file_count; i++) { + + struct dirent *dir_ent = file_list[i]; if (dir_ent->d_name[0] == '.') { @@ -1293,9 +1298,11 @@ int main(int argc, char **argv_orig, char **envp) { } + free(file_list); + file_list = NULL; + if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); } - closedir(dir_in); if (dir_out) { closedir(dir_out); } if (collect_coverage) { -- cgit 1.4.1 From d14a758f69407fe5c39cdcccc093efd5d15ed43c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 May 2021 23:16:37 +0200 Subject: lenient dict parsing, no map size enum for binary fuzzing --- src/afl-fuzz-extras.c | 14 ++++++++++++++ src/afl-fuzz.c | 11 +++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 6091db15..584241d4 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -130,6 +130,20 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, } + /* Skip [number] */ + + if (*lptr == '[') { + + do { + + ++lptr; + + } while (*lptr >= '0' && *lptr <= '9'); + + if (*lptr == ']') { ++lptr; } + + } + /* Skip whitespace and = signs. */ while (isspace(*lptr) || *lptr == '=') { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5f939115..37659831 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1717,10 +1717,11 @@ int main(int argc, char **argv_orig, char **envp) { afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->unicorn_mode) { + !afl->unicorn_mode && !afl->fsrv.frida_mode && + !((map_size == MAP_SIZE || map_size == 65536) && + afl->afl_env.afl_skip_bin_check)) { - if (map_size <= DEFAULT_SHMEM_SIZE && !afl->non_instrumented_mode && - !afl->fsrv.qemu_mode && !afl->unicorn_mode) { + if (map_size <= DEFAULT_SHMEM_SIZE) { afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value char vbuf[16]; @@ -1778,7 +1779,9 @@ int main(int argc, char **argv_orig, char **envp) { if ((map_size <= DEFAULT_SHMEM_SIZE || afl->cmplog_fsrv.map_size < map_size) && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->fsrv.frida_mode && !afl->unicorn_mode) { + !afl->fsrv.frida_mode && !afl->unicorn_mode && + !((map_size == MAP_SIZE || map_size == 65536) && + afl->afl_env.afl_skip_bin_check)) { afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); char vbuf[16]; -- cgit 1.4.1 From 58e39ecd8f601191a98d067d5567559de931c32c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 22 May 2021 12:15:09 +0200 Subject: turn off map size detection if skip_bin_check is set --- docs/env_variables.md | 1 + src/afl-common.c | 4 ++++ src/afl-fuzz.c | 8 +++----- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/docs/env_variables.md b/docs/env_variables.md index c3efa0c0..def1e297 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -355,6 +355,7 @@ checks or alter some of the more exotic semantics of the tool: and shell scripts; and `AFL_DUMB_FORKSRV` in conjunction with the `-n` setting to instruct afl-fuzz to still follow the fork server protocol without expecting any instrumentation data in return. + Note that this also turns off auto map size detection. - 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 diff --git a/src/afl-common.c b/src/afl-common.c index 0fb1462e..8826de70 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1110,6 +1110,10 @@ u32 get_map_size(void) { if (map_size % 64) { map_size = (((map_size >> 6) + 1) << 6); } + } else if (getenv("AFL_SKIP_BIN_CHECK")) { + + map_size = MAP_SIZE; + } return map_size; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 37659831..76c4ca37 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -238,7 +238,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" - "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" + "AFL_SKIP_BIN_CHECK: skip afl compatability checks, also disables auto map size\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" "AFL_STATSD: enables StatsD metrics collection\n" @@ -1718,8 +1718,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !afl->unicorn_mode && !afl->fsrv.frida_mode && - !((map_size == MAP_SIZE || map_size == 65536) && - afl->afl_env.afl_skip_bin_check)) { + !afl->afl_env.afl_skip_bin_check) { if (map_size <= DEFAULT_SHMEM_SIZE) { @@ -1780,8 +1779,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->cmplog_fsrv.map_size < map_size) && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode && - !((map_size == MAP_SIZE || map_size == 65536) && - afl->afl_env.afl_skip_bin_check)) { + !afl->afl_env.afl_skip_bin_check) { afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); char vbuf[16]; -- cgit 1.4.1 From 5864430d935fac57350726d0133b8926bc62d169 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Sat, 22 May 2021 15:49:47 +0200 Subject: Typo --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 76c4ca37..35fb2d04 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -238,7 +238,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" - "AFL_SKIP_BIN_CHECK: skip afl compatability checks, also disables auto map size\n" + "AFL_SKIP_BIN_CHECK: skip afl compatibility checks, also disables auto map size\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" "AFL_STATSD: enables StatsD metrics collection\n" -- cgit 1.4.1 From bc286035e94e43e1e7db1b2a8099210f0e71b88b Mon Sep 17 00:00:00 2001 From: buherator Date: Sun, 23 May 2021 18:26:15 +0200 Subject: Set kill signal before using it in afl-showmap (#935) --- src/afl-showmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 9bf84956..d7af668c 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1104,6 +1104,9 @@ int main(int argc, char **argv_orig, char **envp) { : 0); be_quiet = save_be_quiet; + fsrv->kill_signal = + parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); + if (new_map_size) { // only reinitialize when it makes sense @@ -1211,9 +1214,6 @@ int main(int argc, char **argv_orig, char **envp) { } - fsrv->kill_signal = - parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); - if (getenv("AFL_CRASH_EXITCODE")) { long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); -- cgit 1.4.1 From bb45398d0bbad0b86e311fa6effc286206ecc611 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 23 May 2021 18:47:39 +0200 Subject: fix afl-cc help output --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index ff7b5219..ebe11525 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1640,7 +1640,7 @@ int main(int argc, char **argv, char **envp) { " yes\n" " [LLVM] llvm: %s%s\n" " PCGUARD %s yes yes module yes yes " - "extern\n" + "yes\n" " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" -- cgit 1.4.1 From 109383f43830010c36b704c682ee537e6474d25a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 May 2021 09:08:31 +0200 Subject: less executions on variable paths --- docs/Changelog.md | 2 ++ include/config.h | 4 ++-- src/afl-fuzz-run.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index dfd5c393..33d37067 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,6 +35,8 @@ sending a mail to . afl++ ignores these and uses them for splicing instead. - added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing after no new paths have been found for n seconds + - when AFL_FAST_CAL is set a variable path will no be calibrated 8 times + instead of 40 - afl-cc: - We do not support llvm versions prior 6.0 anymore - Fix for -pie compiled binaries with default afl-clang-fast PCGUARD diff --git a/include/config.h b/include/config.h index aa24ea6c..80cdb684 100644 --- a/include/config.h +++ b/include/config.h @@ -154,7 +154,7 @@ cases that show variable behavior): */ #define CAL_CYCLES 8U -#define CAL_CYCLES_LONG 40U +#define CAL_CYCLES_LONG 20U /* Number of subsequent timeouts before abandoning an input file: */ @@ -163,7 +163,7 @@ /* Maximum number of unique hangs or crashes to record: */ #define KEEP_UNIQUE_HANG 500U -#define KEEP_UNIQUE_CRASH 5000U +#define KEEP_UNIQUE_CRASH 10000U /* Baseline number of random tweaks during a single 'havoc' stage: */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 6e5210b8..5a481639 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -410,7 +410,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } var_detected = 1; - afl->stage_max = CAL_CYCLES_LONG; + afl->stage_max = afl->fast_cal ? CAL_CYCLES : CAL_CYCLES_LONG; } else { -- cgit 1.4.1 From 8e75adfee5574d6d0dd7fd73e9c0899f3162c964 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 May 2021 09:22:50 +0200 Subject: AFL_SKIP_CRASHES is obsolete since 3.0 --- docs/env_variables.md | 5 ----- include/afl-fuzz.h | 2 +- src/afl-fuzz-init.c | 30 +++--------------------------- src/afl-fuzz-state.c | 3 +-- src/afl-fuzz.c | 2 +- 5 files changed, 6 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/docs/env_variables.md b/docs/env_variables.md index def1e297..442b0dd0 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -315,11 +315,6 @@ checks or alter some of the more exotic semantics of the tool: - Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary that is compiled into the target. - - `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input - queue. This can help with rare situations where a program crashes only - intermittently, but it's not really recommended under normal operating - conditions. - - Setting `AFL_HANG_TMOUT` allows you to specify a different timeout for deciding if a particular test case is a "hang". The default is 1 second or the value of the `-t` parameter, whichever is larger. Dialing the value diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 72f956b9..e9a72fc2 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -388,7 +388,7 @@ typedef struct afl_env_vars { afl_exit_on_seed_issues; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, - *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, + *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_kill_signal, *afl_target_env, diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index b277802b..f2d1fb9b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -823,7 +823,6 @@ void perform_dry_run(afl_state_t *afl) { struct queue_entry *q; u32 cal_failures = 0, idx; - u8 * skip_crashes = afl->afl_env.afl_skip_crashes; u8 * use_mem; for (idx = 0; idx < afl->queued_paths; idx++) { @@ -923,27 +922,6 @@ void perform_dry_run(afl_state_t *afl) { if (afl->crash_mode) { break; } - if (skip_crashes) { - - if (afl->fsrv.uses_crash_exitcode) { - - WARNF( - "Test case results in a crash or AFL_CRASH_EXITCODE %d " - "(skipping)", - (int)(s8)afl->fsrv.crash_exitcode); - - } else { - - WARNF("Test case results in a crash (skipping)"); - - } - - q->cal_failed = CAL_CHANCES; - ++cal_failures; - break; - - } - if (afl->fsrv.mem_limit) { u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; @@ -1117,14 +1095,12 @@ void perform_dry_run(afl_state_t *afl) { if (cal_failures == afl->queued_paths) { - FATAL("All test cases time out%s, giving up!", - skip_crashes ? " or crash" : ""); + FATAL("All test cases time out or crash, giving up!"); } - WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, - ((double)cal_failures) * 100 / afl->queued_paths, - skip_crashes ? " or crashes" : ""); + WARNF("Skipped %u test cases (%0.02f%%) due to timeouts or crashes.", + cal_failures, ((double)cal_failures) * 100 / afl->queued_paths); if (cal_failures * 5 > afl->queued_paths) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index c886cb28..046d17d6 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -206,8 +206,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl_environment_variable_len)) { - afl->afl_env.afl_skip_crashes = - (u8 *)get_afl_env(afl_environment_variables[i]); + // we should mark this obsolete in a few versions } else if (!strncmp(env, "AFL_HANG_TMOUT", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 35fb2d04..3b6ac5e2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -240,7 +240,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" "AFL_SKIP_BIN_CHECK: skip afl compatibility checks, also disables auto map size\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" - "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" + //"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" "AFL_STATSD: enables StatsD metrics collection\n" "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n" "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" -- cgit 1.4.1 From 87b16c4460d34eb775660991732ca0ef0c2f8e78 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 May 2021 10:45:24 +0200 Subject: add AFL_TRY_AFFINITY --- Dockerfile | 1 + README.md | 4 ++-- docs/Changelog.md | 10 ++++++---- docs/env_variables.md | 3 +++ include/afl-fuzz.h | 2 +- include/envs.h | 1 + src/afl-fuzz-init.c | 34 ++++++++++++++++++++++++---------- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 1 + 9 files changed, 46 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/Dockerfile b/Dockerfile index 8f89b9aa..9662ca7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,6 +50,7 @@ RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0 ENV LLVM_CONFIG=llvm-config-12 ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_TRY_AFFINITY=1 ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov /afl-cov diff --git a/README.md b/README.md index cedf706c..69e2d14a 100644 --- a/README.md +++ b/README.md @@ -679,8 +679,8 @@ If you see that an important area or a feature has not been covered so far then try to find an input that is able to reach that and start a new secondary in that fuzzing campaign with that seed as input, let it run for a few minutes, then terminate it. The main node will pick it up and make it available to the -other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` if you have no -free core. +other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` or +`export AFL_TRY_AFFINITY=1` if you have no free core. Note that you in nearly all cases can never reach full coverage. A lot of functionality is usually behind options that were not activated or fuzz e.g. diff --git a/docs/Changelog.md b/docs/Changelog.md index 33d37067..bbe55e3e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -33,10 +33,12 @@ sending a mail to . - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in -i dir crashes the target or results in a timeout. By default afl++ ignores these and uses them for splicing instead. - - added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing after - no new paths have been found for n seconds - - when AFL_FAST_CAL is set a variable path will no be calibrated 8 times - instead of 40 + - added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing + after no new paths have been found for n seconds + - when AFL_FAST_CAL is set a variable path will no be calibrated + 8 times instead of 40 + - added AFL_TRY_AFFINITY to try to bind to CPUs but don't error if + it fails - afl-cc: - We do not support llvm versions prior 6.0 anymore - Fix for -pie compiled binaries with default afl-clang-fast PCGUARD diff --git a/docs/env_variables.md b/docs/env_variables.md index 442b0dd0..a3267523 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -312,6 +312,9 @@ checks or alter some of the more exotic semantics of the tool: on Linux systems. This slows things down, but lets you run more instances of afl-fuzz than would be prudent (if you really want to). + - Setting `AFL_TRY_AFFINITY` tries to attempts to bind to a specific CPU core + on Linux systems, but will not terminate if it fails. + - Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary that is compiled into the target. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e9a72fc2..4aba3bdf 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -385,7 +385,7 @@ typedef struct afl_env_vars { afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, - afl_exit_on_seed_issues; + afl_exit_on_seed_issues, afl_try_affinity; 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 f1314bad..e7162c0f 100644 --- a/include/envs.h +++ b/include/envs.h @@ -120,6 +120,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", + "AFL_TRY_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index f2d1fb9b..88b5bc02 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -113,7 +113,7 @@ void bind_to_free_cpu(afl_state_t *afl) { u8 lockfile[PATH_MAX] = ""; s32 i; - if (afl->afl_env.afl_no_affinity) { + if (afl->afl_env.afl_no_affinity && !afl->afl_env.afl_try_affinity) { if (afl->cpu_to_bind != -1) { @@ -130,10 +130,21 @@ void bind_to_free_cpu(afl_state_t *afl) { if (!bind_cpu(afl, afl->cpu_to_bind)) { - FATAL( - "Could not bind to requested CPU %d! Make sure you passed a valid " - "-b.", - afl->cpu_to_bind); + if (afl->afl_env.afl_try_affinity) { + + WARNF( + "Could not bind to requested CPU %d! Make sure you passed a valid " + "-b.", + afl->cpu_to_bind); + + } else { + + FATAL( + "Could not bind to requested CPU %d! Make sure you passed a valid " + "-b.", + afl->cpu_to_bind); + + } } @@ -420,11 +431,14 @@ void bind_to_free_cpu(afl_state_t *afl) { "Uh-oh, looks like all %d CPU cores on your system are allocated to\n" " other instances of afl-fuzz (or similar CPU-locked tasks). " "Starting\n" - " another fuzzer on this machine is probably a bad plan, but if " - "you are\n" - " absolutely sure, you can set AFL_NO_AFFINITY and try again.\n", - afl->cpu_core_count); - FATAL("No more free CPU cores"); + " another fuzzer on this machine is probably a bad plan.\n" + "%s", + afl->cpu_core_count, + afl->afl_env.afl_try_affinity ? "" + : " If you are sure, you can set " + "AFL_NO_AFFINITY and try again.\n"); + + if (!afl->afl_env.afl_try_affinity) { FATAL("No more free CPU cores"); } } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 046d17d6..0658070e 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -202,6 +202,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_no_affinity = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_TRY_AFFINITY", + + afl_environment_variable_len)) { + + afl->afl_env.afl_try_affinity = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_SKIP_CRASHES", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3b6ac5e2..bb970e5f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -220,6 +220,7 @@ static void usage(u8 *argv0, int more_help) { " then they are randomly selected instead all of them being\n" " used. Defaults to 200.\n" "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n" + "AFL_TRY_AFFINITY: try to bind to an unused core, but don't fail if unsuccessful\n" "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n" "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n" "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n" -- cgit 1.4.1 From 3b93729213de46a3008709bd8170d5593394d8cb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 May 2021 22:04:25 +0200 Subject: tweaks --- docs/Changelog.md | 4 ++-- docs/custom_mutators.md | 3 +++ src/afl-fuzz-python.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index f8831ff1..175c6c43 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,8 +35,8 @@ sending a mail to . afl++ ignores these and uses them for splicing instead. - added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing after no new paths have been found for n seconds - - when AFL_FAST_CAL is set a variable path will now be calibrated - 8 times instead of 40 + - when AFL_FAST_CAL is set a variable path will no be calibrated + 8 times instead of originally 40. Long calibration is now 20. - added AFL_TRY_AFFINITY to try to bind to CPUs but don't error if it fails - afl-cc: diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 9d5381e8..3e3ae01d 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -92,6 +92,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue): def introspection(): return string + +def deinit(): # optional for Python + pass ``` ### Custom Mutation diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 8760194c..3aa97635 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -212,7 +212,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "introspection"); py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit"); if (!py_functions[PY_FUNC_DEINIT]) - FATAL("deinit function not found in python module"); + WARNF("deinit function not found in python module"); for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) { -- cgit 1.4.1 From 64d9b7dd21aec84658f6ab89eee0455e98bdbc98 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 26 May 2021 22:42:14 +0200 Subject: fix for MacOS --- src/afl-fuzz.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bb970e5f..4cd38d78 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -35,6 +35,10 @@ #include #endif +#ifdef __APPLE__ + #include +#endif + #ifdef PROFILING extern u64 time_spent_working; #endif -- cgit 1.4.1 From 0aeb871ac95b35d741628069a487e843369c1ab0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 26 May 2021 22:55:21 +0200 Subject: fix tmpfile removal --- src/afl-fuzz.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 4cd38d78..a3a623d9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2301,26 +2301,9 @@ stop_fuzzing: afl_fsrv_deinit(&afl->fsrv); /* remove tmpfile */ - if (afl->tmp_dir != NULL && !afl->in_place_resume) { + if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) { - char tmpfile[PATH_MAX]; - - if (afl->file_extension) { - - snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, - afl->file_extension); - - } else { - - snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); - - } - - if (unlink(tmpfile) != 0) { - - FATAL("Could not unlink current input file: %s.", tmpfile); - - } + (void)unlink(afl->fsrv.out_file); } -- cgit 1.4.1 From 8e86f7ad803e571bcd275d2aca597997ab0e4d2c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 May 2021 13:35:05 +0200 Subject: add --afl-noopt to afl-cc --- docs/Changelog.md | 1 + src/afl-cc.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 594637fb..298a3998 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -46,6 +46,7 @@ sending a mail to . - Removed InsTrim instrumentation as it is not as good as PCGUARD - Removed automatic linking with -lc++ for LTO mode - Fixed a crash in llvm dict2file when a strncmp length was -1 + - added --afl-noopt support - utils/aflpp_driver: - aflpp_qemu_driver_hook fixed to work with qemu_mode - aflpp_driver now compiled with -fPIC diff --git a/src/afl-cc.c b/src/afl-cc.c index ebe11525..8af8e7b0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1224,6 +1224,14 @@ int main(int argc, char **argv, char **envp) { if (strncmp(argv[i], "--afl", 5) == 0) { + if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { + + passthrough = 1; + argv[i] = "-g"; // we have to overwrite it, -g is always good + continue; + + } + if (compiler_mode) WARNF( "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " @@ -1821,6 +1829,12 @@ int main(int argc, char **argv, char **envp) { "If anything fails - be sure to read README.lto.md!\n"); #endif + SAYF( + "\nYou can supply --afl-noopt to not instrument, like AFL_NOOPT. " + "(this is helpful\n" + "in some build systems if you do not want to instrument " + "everything.\n"); + } SAYF( -- cgit 1.4.1 From c78762e690ff936c2e5394aff87deeb7b6b67a6c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 30 May 2021 02:04:37 +0200 Subject: fix for afl-showmap --- src/afl-showmap.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index d7af668c..96b72dd9 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -235,6 +235,9 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (cmin_mode && (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) { + // create empty file to prevent error messages in afl-cmin + fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + close(fd); return ret; } -- cgit 1.4.1 From eb74a7a8004e8281cda62525bbc1f3bbe7f5d9da Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sun, 30 May 2021 12:43:30 +0200 Subject: add documentation for AFL_LLVM_THREADSAFE_INST --- docs/Changelog.md | 1 + docs/env_variables.md | 5 +++++ instrumentation/README.llvm.md | 4 ++++ instrumentation/README.neverzero.md | 5 +++++ src/afl-cc.c | 1 + 5 files changed, 16 insertions(+) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 9c9a3976..d8e96bf3 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,6 +35,7 @@ sending a mail to . - Removed automatic linking with -lc++ for LTO mode - utils/aflpp_driver/aflpp_qemu_driver_hook fixed to work with qemu mode - add -d (add dead fuzzer stats) to afl-whatsup + - add thread safe counters for LLVM CLASSIC (set AFL_LLVM_THREADSAFE_INST) ### Version ++3.12c (release) - afl-fuzz: diff --git a/docs/env_variables.md b/docs/env_variables.md index 0100ffac..d9a774aa 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -231,6 +231,11 @@ Then there are a few specific features that are only available in instrumentatio See [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) for more information. +### Thread safe instrumentation counters (in mode LLVM CLASSIC) + - Setting `AFL_LLVM_THREADSAFE_INST` will inject code that implements thread safe counters. + The overhead is a bit higher compared to the older non-thread safe case. + `AFL_LLVM_NOT_ZERO` and `AFL_LLVM_SKIP_NEVERZERO` are supported (see below). + ### NOT_ZERO - Setting `AFL_LLVM_NOT_ZERO=1` during compilation will use counters diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index adce6c1d..a9d51829 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -144,6 +144,10 @@ is not optimal and was only fixed in llvm 9. You can set this with AFL_LLVM_NOT_ZERO=1 See [README.neverzero.md](README.neverzero.md) +Support for thread safe counters has been added for mode LLVM CLASSIC. +Activate it with `AFL_LLVM_THREADSAFE_INST=1`. The tradeoff is better precision in +multi threaded apps for a slightly higher instrumentation overhead. + ## 4) Snapshot feature To speed up fuzzing you can use a linux loadable kernel module which enables diff --git a/instrumentation/README.neverzero.md b/instrumentation/README.neverzero.md index 49104e00..06334eab 100644 --- a/instrumentation/README.neverzero.md +++ b/instrumentation/README.neverzero.md @@ -33,3 +33,8 @@ AFL_LLVM_SKIP_NEVERZERO=1 ``` If the target does not have extensive loops or functions that are called a lot then this can give a small performance boost. + +Please note that the default counter implementations are not thread safe! + +Support for thread safe counters in mode LLVM CLASSIC can be activated with setting +`AFL_LLVM_THREADSAFE_INST=1`. \ No newline at end of file diff --git a/src/afl-cc.c b/src/afl-cc.c index 1f89bac5..132f5f83 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1757,6 +1757,7 @@ int main(int argc, char **argv, char **envp) { SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" + " AFL_LLVM_THREADSAFE_INST: instrument with thread safe counters\n" COUNTER_BEHAVIOUR -- cgit 1.4.1 From 76653544056ce2334b6523252e91a8f8a6ac9dcb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Jun 2021 10:13:16 +0200 Subject: threadsafe doc fixes, code format --- README.md | 3 +- docs/Changelog.md | 3 +- docs/env_variables.md | 9 +- frida_mode/src/instrument/instrument_debug.c | 2 +- frida_mode/src/stats/stats.c | 4 +- instrumentation/README.llvm.md | 7 +- instrumentation/SanitizerCoverageLTO.so.cc | 7 +- instrumentation/SanitizerCoveragePCGUARD.so.cc | 6 +- instrumentation/afl-llvm-lto-instrumentation.so.cc | 11 +- instrumentation/afl-llvm-pass.so.cc | 116 +++++++++++++-------- qemu_mode/libqasan/libqasan.c | 5 +- src/afl-cc.c | 3 +- src/afl-fuzz-one.c | 1 + src/afl-fuzz.c | 7 +- 14 files changed, 106 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 69e2d14a..c04dba98 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ behaviours and defaults: | Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode | | -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:| + | Threadsafe counters | | x(3) | | | | | | NeverZero | x86[_64]| x(1) | x | x | x | x | | Persistent Mode | | x | x | x86[_64] | x86[_64]/arm[64] | x | | LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm | @@ -104,7 +105,7 @@ behaviours and defaults: 1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions 2. GCC creates non-performant code, hence it is disabled in gcc_plugin - 3. (currently unassigned) + 3. with `AFL_LLVM_THREADSAFE_INST`, disables NeverZero 4. with pcguard mode and LTO mode for LLVM 11 and newer 5. upcoming, development in the branch 6. not compatible with LTO instrumentation and needs at least LLVM v4.1 diff --git a/docs/Changelog.md b/docs/Changelog.md index d8ffe498..29ea918b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -41,6 +41,8 @@ sending a mail to . it fails - afl-cc: - We do not support llvm versions prior 6.0 anymore + - added thread safe counters to all modes (`AFL_LLVM_THREADSAFE_INST`), + note that this disables never zero counters. - Fix for -pie compiled binaries with default afl-clang-fast PCGUARD - Leak Sanitizer (AFL_USE_LSAN) added by Joshua Rogers, thanks! - Removed InsTrim instrumentation as it is not as good as PCGUARD @@ -58,7 +60,6 @@ sending a mail to . MacOS shared memory - updated the grammar custom mutator to the newest version - add -d (add dead fuzzer stats) to afl-whatsup - - add thread safe counters for LLVM CLASSIC (set AFL_LLVM_THREADSAFE_INST) - added AFL_PRINT_FILENAMES to afl-showmap/cmin to print the current filename - afl-showmap/cmin will now process queue items in alphabetical order diff --git a/docs/env_variables.md b/docs/env_variables.md index b4b866ab..38a67bc7 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -231,10 +231,11 @@ Then there are a few specific features that are only available in instrumentatio See [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) for more information. -### Thread safe instrumentation counters (in mode LLVM CLASSIC) - - Setting `AFL_LLVM_THREADSAFE_INST` will inject code that implements thread safe counters. - The overhead is a bit higher compared to the older non-thread safe case. - `AFL_LLVM_NOT_ZERO` and `AFL_LLVM_SKIP_NEVERZERO` are supported (see below). +### Thread safe instrumentation counters (in all modes) + + - Setting `AFL_LLVM_THREADSAFE_INST` will inject code that implements thread + safe counters. The overhead is a little bit higher compared to the older + non-thread safe case. Note that this disables neverzero (see below). ### NOT_ZERO diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c index be72ef89..f8c1df77 100644 --- a/frida_mode/src/instrument/instrument_debug.c +++ b/frida_mode/src/instrument/instrument_debug.c @@ -17,7 +17,7 @@ static void instrument_debug(char *format, ...) { va_list ap; char buffer[4096] = {0}; int ret; - int len; + int len; va_start(ap, format); ret = vsnprintf(buffer, sizeof(buffer) - 1, format, ap); diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c index 890a8d6b..662fb6d5 100644 --- a/frida_mode/src/stats/stats.c +++ b/frida_mode/src/stats/stats.c @@ -96,10 +96,10 @@ void stats_init(void) { void stats_vprint(int fd, char *format, va_list ap) { char buffer[4096] = {0}; - int ret; + int ret; int len; - if(vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; } + if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; } len = strnlen(buffer, sizeof(buffer)); IGNORED_RETURN(write(fd, buffer, len)); diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index 02722588..8ce5afb9 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -144,9 +144,10 @@ is not optimal and was only fixed in llvm 9. You can set this with AFL_LLVM_NOT_ZERO=1 See [README.neverzero.md](README.neverzero.md) -Support for thread safe counters has been added for mode LLVM CLASSIC. -Activate it with `AFL_LLVM_THREADSAFE_INST=1`. The tradeoff is better precision in -multi threaded apps for a slightly higher instrumentation overhead. +Support for thread safe counters has been added for all modes. +Activate it with `AFL_LLVM_THREADSAFE_INST=1`. The tradeoff is better precision +in multi threaded apps for a slightly higher instrumentation overhead. +This also disables the nozero counter default for performance reasons. ## 4) Snapshot feature diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 58969e18..20f1856e 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1497,14 +1497,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } /* Update bitmap */ - if (use_threadsafe_counters) { /* Atomic */ + if (use_threadsafe_counters) { /* Atomic */ IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, llvm::AtomicOrdering::Monotonic); - } - else - { + } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(Mo->getMDKindID("nosanitize"), @@ -1524,6 +1522,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, ->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None)); } + // done :) inst++; diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index dbddad0a..4a8c9e28 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1069,16 +1069,14 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, /* Load counter for CurLoc */ - Value * MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); if (use_threadsafe_counters) { IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, llvm::AtomicOrdering::Monotonic); - } - else - { + } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); /* Update bitmap */ diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index b5fdb3d6..fe43fbe5 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -93,8 +93,8 @@ class AFLLTOPass : public ModulePass { uint32_t function_minimum_size = 1; uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0; unsigned long long int map_addr = 0x10000; - const char *skip_nozero = NULL; - const char *use_threadsafe_counters = nullptr; + const char * skip_nozero = NULL; + const char * use_threadsafe_counters = nullptr; }; @@ -843,9 +843,12 @@ bool AFLLTOPass::runOnModule(Module &M) { /* Update bitmap */ if (use_threadsafe_counters) { + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, llvm::AtomicOrdering::Monotonic); + } else { + LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); @@ -861,7 +864,9 @@ bool AFLLTOPass::runOnModule(Module &M) { } IRB.CreateStore(Incr, MapPtrIdx) - ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + ->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + } // done :) diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index fe9e2e40..62f8b2ed 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -81,12 +81,12 @@ class AFLCoverage : public ModulePass { bool runOnModule(Module &M) override; protected: - uint32_t ngram_size = 0; - uint32_t ctx_k = 0; - uint32_t map_size = MAP_SIZE; - uint32_t function_minimum_size = 1; - const char * ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL; - const char * use_threadsafe_counters = nullptr; + uint32_t ngram_size = 0; + uint32_t ctx_k = 0; + uint32_t map_size = MAP_SIZE; + uint32_t function_minimum_size = 1; + const char *ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL; + const char *use_threadsafe_counters = nullptr; }; @@ -188,18 +188,30 @@ bool AFLCoverage::runOnModule(Module &M) { if ((isatty(2) && !getenv("AFL_QUIET")) || !!getenv("AFL_DEBUG")) { if (use_threadsafe_counters) { - if (!getenv("AFL_LLVM_NOT_ZERO")) { - skip_nozero = "1"; - SAYF(cCYA "afl-llvm-pass" VERSION cRST " using thread safe counters\n"); - } - else { - SAYF(cCYA "afl-llvm-pass" VERSION cRST - " using thread safe not-zero-counters\n"); - } - } - else - { - SAYF(cCYA "afl-llvm-pass" VERSION cRST " using non-thread safe instrumentation\n"); + + // disabled unless there is support for other modules as well + // (increases documentation complexity) + /* if (!getenv("AFL_LLVM_NOT_ZERO")) { */ + + skip_nozero = "1"; + SAYF(cCYA "afl-llvm-pass" VERSION cRST " using thread safe counters\n"); + + /* + + } else { + + SAYF(cCYA "afl-llvm-pass" VERSION cRST + " using thread safe not-zero-counters\n"); + + } + + */ + + } else { + + SAYF(cCYA "afl-llvm-pass" VERSION cRST + " using non-thread safe instrumentation\n"); + } } @@ -649,44 +661,44 @@ bool AFLCoverage::runOnModule(Module &M) { /* Update bitmap */ + if (use_threadsafe_counters) { /* Atomic */ - if (use_threadsafe_counters) {/* Atomic */ - - #if LLVM_VERSION_MAJOR < 9 +#if LLVM_VERSION_MAJOR < 9 if (neverZero_counters_str != - NULL) { // with llvm 9 we make this the default as the bug in llvm is then fixed - #else + NULL) { // with llvm 9 we make this the default as the bug in llvm + // is then fixed +#else if (!skip_nozero) { - #endif +#endif // register MapPtrIdx in a todo list todo.push_back(MapPtrIdx); - } - else - { + } else { + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, llvm::AtomicOrdering::Monotonic); + } - } - else - { + + } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *Incr = IRB.CreateAdd(Counter, One); - #if LLVM_VERSION_MAJOR < 9 +#if LLVM_VERSION_MAJOR < 9 if (neverZero_counters_str != - NULL) { // with llvm 9 we make this the default as the bug in llvm is - // then fixed - #else + NULL) { // with llvm 9 we make this the default as the bug in llvm + // is then fixed +#else if (!skip_nozero) { - #endif +#endif /* hexcoder: Realize a counter that skips zero during overflow. - * Once this counter reaches its maximum value, it next increments to 1 + * Once this counter reaches its maximum value, it next increments to + * 1 * * Instead of * Counter + 1 -> Counter @@ -705,7 +717,7 @@ bool AFLCoverage::runOnModule(Module &M) { IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } /* non atomic case */ + } /* non atomic case */ /* Update prev_loc history vector (by placing cur_loc at the head of the vector and shuffle the other elements back by one) */ @@ -762,16 +774,19 @@ bool AFLCoverage::runOnModule(Module &M) { } - if (use_threadsafe_counters) { /*Atomic NeverZero */ + if (use_threadsafe_counters) { /*Atomic NeverZero */ // handle the list of registered blocks to instrument for (auto val : todo) { - /* hexcoder: Realize a thread-safe counter that skips zero during overflow. Once this counter reaches its maximum value, it next increments to 1 - * - * Instead of - * Counter + 1 -> Counter - * we inject now this - * Counter + 1 -> {Counter, OverflowFlag} - * Counter + OverflowFlag -> Counter + + /* hexcoder: Realize a thread-safe counter that skips zero during + * overflow. Once this counter reaches its maximum value, it next + * increments to 1 + * + * Instead of + * Counter + 1 -> Counter + * we inject now this + * Counter + 1 -> {Counter, OverflowFlag} + * Counter + OverflowFlag -> Counter */ /* equivalent c code looks like this @@ -781,12 +796,19 @@ bool AFLCoverage::runOnModule(Module &M) { int old = atomic_load_explicit(&Counter, memory_order_relaxed); int new; do { + if (old == 255) { + new = 1; + } else { + new = old + 1; + } + } while (!atomic_compare_exchange_weak_explicit(&Counter, &old, new, + memory_order_relaxed, memory_order_relaxed)); */ @@ -805,7 +827,8 @@ bool AFLCoverage::runOnModule(Module &M) { BasicBlock *BB = IRB.GetInsertBlock(); // insert a basic block with the corpus of a do while loop - // the calculation may need to repeat, if atomic compare_exchange is not successful + // the calculation may need to repeat, if atomic compare_exchange is not + // successful BasicBlock::iterator it(*Counter); it++; // split after load counter @@ -857,6 +880,7 @@ bool AFLCoverage::runOnModule(Module &M) { // if the cmpXchg was not successful, retry IRB.CreateCondBr(Success, end_bb, do_while_bb); + } } diff --git a/qemu_mode/libqasan/libqasan.c b/qemu_mode/libqasan/libqasan.c index d4742e3e..6ea24f08 100644 --- a/qemu_mode/libqasan/libqasan.c +++ b/qemu_mode/libqasan/libqasan.c @@ -69,9 +69,8 @@ __attribute__((constructor)) void __libqasan_init() { __libqasan_is_initialized = 1; __libqasan_init_hooks(); - - if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) - __libqasan_hotpatch(); + + if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) __libqasan_hotpatch(); if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) __libqasan_hotpatch(); diff --git a/src/afl-cc.c b/src/afl-cc.c index 6be6e165..486f7468 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1777,7 +1777,8 @@ int main(int argc, char **argv, char **envp) { SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" - " AFL_LLVM_THREADSAFE_INST: instrument with thread safe counters\n" + " AFL_LLVM_THREADSAFE_INST: instrument with thread safe counters, " + "disables neverzero\n" COUNTER_BEHAVIOUR diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 4a3e7f33..c3ce2edd 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -561,6 +561,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->cmplog_lvl == 3 || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || + afl->queue_cur->favored || !(afl->fsrv.total_execs % afl->queued_paths) || get_cur_time() - afl->last_path_time > 300000) { // 300 seconds diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a3a623d9..5bdb4c8d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2066,13 +2066,10 @@ int main(int argc, char **argv_orig, char **envp) { break; case 4: afl->expand_havoc = 5; - if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl = 3; + // if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl = + // 3; break; case 5: - // if not in sync mode, enable deterministic mode? - // if (!afl->sync_id) afl->skip_deterministic = 0; - afl->expand_havoc = 6; - case 6: // nothing else currently break; -- cgit 1.4.1 From 17e904eedf025e870c79cd0dcc037282e1cce1d7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Jun 2021 10:40:25 +0200 Subject: fix afl_custom_post_process with multiple custom mutators --- docs/Changelog.md | 9 +++++---- src/afl-fuzz-run.c | 30 ++++++++++++------------------ 2 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index e7344761..09e46fb6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -22,13 +22,14 @@ sending a mail to . to allow replay of non-reproducable crashes, see AFL_PERSISTENT_RECORD in config.h and docs/envs.h - fixed a bug when trimming for stdin targets - - default cmplog level (-l) is now 2, better efficiency. - - cmplog level 3 (-l 3) now performs redqueen on everything. - use with care. - - better fuzzing strategy yields for enabled options + - cmplog -l: default cmplog level is now 2, better efficiency. + level 3 now performs redqueen on everything. use with care. + - better fuzzing strategy yield display for enabled options - ensure one fuzzer sync per cycle - fix afl_custom_queue_new_entry original file name when syncing from fuzzers + - fixed a crash when more than one custom mutator was used together + with afl_custom_post_process - on a crashing seed potentially the wrong input was disabled - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in -i dir crashes the target or results in a timeout. By default diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 5a481639..7df4c625 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -107,27 +107,21 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { new_size = el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf); - } - - new_mem = new_buf; - - }); + if (unlikely(!new_buf && new_size <= 0)) { - if (unlikely(!new_buf && (new_size <= 0))) { - - FATAL("Custom_post_process failed (ret: %lu)", (long unsigned)new_size); + FATAL("Custom_post_process failed (ret: %lu)", + (long unsigned)new_size); - } else if (likely(new_buf)) { + } - /* everything as planned. use the new data. */ - afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); + new_mem = new_buf; - } else { + } - /* custom mutators do not has a custom_post_process function */ - afl_fsrv_write_to_testcase(&afl->fsrv, mem, len); + }); - } + /* everything as planned. use the potentially new data. */ + afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); } else { @@ -188,16 +182,16 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, new_size = el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf); - if (unlikely(!new_buf || (new_size <= 0))) { + if (unlikely(!new_buf || new_size <= 0)) { FATAL("Custom_post_process failed (ret: %lu)", (long unsigned)new_size); } - } + new_mem = new_buf; - new_mem = new_buf; + } }); -- cgit 1.4.1 From 7e54c8d7f6ad7e07c5c442d2e92eed3da7c4add0 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Jun 2021 11:06:42 +0200 Subject: fixed potential diff by 0 --- src/afl-fuzz-redqueen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index cf1e5ea5..22fd0621 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -438,7 +438,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, if (taint) { if (afl->colorize_success && afl->cmplog_lvl < 3 && - (len / positions == 1 && positions > CMPLOG_POSITIONS_MAX && + (positions > CMPLOG_POSITIONS_MAX && len / positions == 1 && afl->active_paths / afl->colorize_success > CMPLOG_CORPUS_PERCENT)) { #ifdef _DEBUG -- cgit 1.4.1 From 07c3e47e6beae3e99637f501095bffb95be9f5da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Jun 2021 11:19:49 +0200 Subject: fixes --- src/afl-common.c | 12 ++++++++++-- src/afl-fuzz-run.c | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 8826de70..c61ce3d8 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -479,9 +479,17 @@ void print_suggested_envs(char *mispelled_env) { size_t end = start + strcspn(afl_env + start, "_") + 1; memcpy(reduced, afl_env, start); - if (end < afl_env_len) + if (end < afl_env_len) { + memcpy(reduced + start, afl_env + end, afl_env_len - end); - reduced[afl_env_len - end + start] = 0; + + } + + if (afl_env_len + start >= end) { + + reduced[afl_env_len - end + start] = 0; + + } int distance = string_distance_levenshtein(reduced, env_name); if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 7df4c625..2c3e8a1b 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -121,7 +121,7 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { }); /* everything as planned. use the potentially new data. */ - afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); + afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); } else { -- cgit 1.4.1 From 753d5d74ffc0a75ee437be0e87ca0b93c2e61b1b Mon Sep 17 00:00:00 2001 From: terrynini Date: Tue, 1 Jun 2021 18:39:39 +0800 Subject: remove redundant unsetenv (#947) --- src/afl-fuzz-run.c | 1 - src/afl-fuzz.c | 3 --- 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2c3e8a1b..493735ff 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -333,7 +333,6 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) { - unsetenv(SHM_FUZZ_ENV_VAR); afl_shm_deinit(afl->shm_fuzz); ck_free(afl->shm_fuzz); afl->shm_fuzz = NULL; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5bdb4c8d..196547f4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2283,13 +2283,10 @@ stop_fuzzing: destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); - unsetenv(SHM_ENV_VAR); - unsetenv(CMPLOG_SHM_ENV_VAR); afl_shm_deinit(&afl->shm); if (afl->shm_fuzz) { - unsetenv(SHM_FUZZ_ENV_VAR); afl_shm_deinit(afl->shm_fuzz); ck_free(afl->shm_fuzz); -- cgit 1.4.1 From e3a0ede91c9319ac6991c3f739b24e6af08749d9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Jun 2021 18:35:42 +0200 Subject: ensure memory is there before free --- src/afl-fuzz-redqueen.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 22fd0621..b41ffa88 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2663,7 +2663,12 @@ exit_its: afl->queue_cur->colorized = CMPLOG_LVL_MAX; - ck_free(afl->queue_cur->cmplog_colorinput); + if (afl->queue_cur->cmplog_colorinput) { + + ck_free(afl->queue_cur->cmplog_colorinput); + + } + while (taint) { t = taint->next; -- cgit 1.4.1 From a38aafc5d0cb9ccf75f99613f52fd0938f5f86c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 2 Jun 2021 10:50:04 +0200 Subject: fix -F with slash option --- docs/Changelog.md | 3 +++ src/afl-fuzz-init.c | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index a49c0672..a4c6ac10 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,9 @@ sending a mail to . ### Version ++3.14a (release) - Fix for llvm 13 + - afl-fuzz: + - fix -F when a '/' was part of the parameter + - ensure afl-compiler-rt is built for gcc_module ### Version ++3.13c (release) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 88b5bc02..872e3a32 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -480,13 +480,22 @@ void read_foreign_testcases(afl_state_t *afl, int first) { for (iter = 0; iter < afl->foreign_sync_cnt; iter++) { - if (afl->foreign_syncs[iter].dir != NULL && - afl->foreign_syncs[iter].dir[0] != 0) { + if (afl->foreign_syncs[iter].dir && afl->foreign_syncs[iter].dir[0]) { if (first) ACTF("Scanning '%s'...", afl->foreign_syncs[iter].dir); time_t mtime_max = 0; - u8 * name = strrchr(afl->foreign_syncs[iter].dir, '/'); - if (!name) { name = afl->foreign_syncs[iter].dir; } + + u8 *name = strrchr(afl->foreign_syncs[iter].dir, '/'); + if (!name) { + + name = afl->foreign_syncs[iter].dir; + + } else { + + ++name; + + } + if (!strcmp(name, "queue") || !strcmp(name, "out") || !strcmp(name, "default")) { -- cgit 1.4.1 From 0fbe5fb436b2ee939959230da7b0b660d81b41d7 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 3 Jun 2021 16:26:53 +0200 Subject: detect partial linking in afl-cc --- src/afl-cc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 486f7468..db31461d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -315,7 +315,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0, preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0, - have_c = 0; + have_c = 0, partial_linking = 0; cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); @@ -767,6 +767,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!strcmp(cur, "-x")) x_set = 1; if (!strcmp(cur, "-E")) preprocessor_only = 1; if (!strcmp(cur, "-shared")) shared_linking = 1; + if (!strcmp(cur, "-r")) partial_linking = 1; if (!strcmp(cur, "-c")) have_c = 1; if (!strncmp(cur, "-O", 2)) have_o = 1; @@ -996,7 +997,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { switch (bit_mode) { case 0: - if (!shared_linking) + if (!shared_linking && !partial_linking) cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt.o", obj_path); if (lto_mode) @@ -1005,7 +1006,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { break; case 32: - if (!shared_linking) { + if (!shared_linking && !partial_linking) { cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-32.o", obj_path); @@ -1026,7 +1027,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { break; case 64: - if (!shared_linking) { + if (!shared_linking && !partial_linking) { cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-64.o", obj_path); @@ -1049,7 +1050,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking) + if (!shared_linking && !partial_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif -- cgit 1.4.1 From 55da5e3e022fe5556668224bc8546225dd59dfc6 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 3 Jun 2021 16:44:15 +0200 Subject: partial linking with -Wl --- src/afl-cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index db31461d..980e5d86 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -767,7 +767,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!strcmp(cur, "-x")) x_set = 1; if (!strcmp(cur, "-E")) preprocessor_only = 1; if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; + if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; + if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; if (!strcmp(cur, "-c")) have_c = 1; if (!strncmp(cur, "-O", 2)) have_o = 1; -- cgit 1.4.1 From 36671ce79987859b1f0dfec88cb06c6eb7f5d12b Mon Sep 17 00:00:00 2001 From: yuan Date: Fri, 4 Jun 2021 15:49:34 +0800 Subject: fix ui fuzzing stage index (#960) --- src/afl-fuzz-stats.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4884b942..a9c44cc0 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1017,9 +1017,10 @@ void show_stats(afl_state_t *afl) { if (unlikely(afl->afl_env.afl_custom_mutator_library)) { strcat(tmp, " "); - strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_PYTHON])); + strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR])); strcat(tmp, "/"); - strcat(tmp, u_stringify_int(IB(3), afl->stage_cycles[STAGE_PYTHON])); + strcat(tmp, + u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); strcat(tmp, ","); } else { -- cgit 1.4.1 From 43eca8203a278183120d93fbf0cd3df2b7fd2392 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Fri, 4 Jun 2021 21:41:12 +0200 Subject: fix overflowing UI fields 'now processing' --- src/afl-fuzz-stats.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index a9c44cc0..89d2c37d 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -766,9 +766,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA - " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + SAYF(bVR bH bSTOP cCYA + " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA + " map coverage" bSTG bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -778,13 +778,13 @@ void show_stats(afl_state_t *afl) { afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level, ((double)afl->current_entry * 100) / afl->queued_paths); - SAYF(bV bSTOP " now processing : " cRST "%-16s " bSTG bV bSTOP, tmp); + SAYF(bV bSTOP " now processing : " cRST "%-18s " bSTG bV bSTOP, tmp); sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.map_size, t_byte_ratio); - SAYF(" map density : %s%-21s" bSTG bV "\n", + SAYF(" map density : %s%-19s" bSTG bV "\n", t_byte_ratio > 70 ? cLRD : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), @@ -793,23 +793,23 @@ void show_stats(afl_state_t *afl) { sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths), ((double)afl->cur_skipped_paths * 100) / afl->queued_paths); - SAYF(bV bSTOP " paths timed out : " cRST "%-16s " bSTG bV, tmp); + SAYF(bV bSTOP " paths timed out : " cRST "%-18s " bSTG bV, tmp); sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0); - SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); + SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA - " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + SAYF(bVR bH bSTOP cCYA + " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA + " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); /* Yeah... it's still going on... halp? */ - SAYF(bV bSTOP " now trying : " cRST "%-20s " bSTG bV bSTOP - " favored paths : " cRST "%-22s" bSTG bV "\n", + SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP + " favored paths : " cRST "%-20s" bSTG bV "\n", afl->stage_name, tmp); if (!afl->stage_max) { @@ -824,12 +824,12 @@ void show_stats(afl_state_t *afl) { } - SAYF(bV bSTOP " stage execs : " cRST "%-21s" bSTG bV bSTOP, tmp); + SAYF(bV bSTOP " stage execs : " cRST "%-23s" bSTG bV bSTOP, tmp); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov), ((double)afl->queued_with_cov) * 100 / afl->queued_paths); - SAYF(" new edges on : " cRST "%-22s" bSTG bV "\n", tmp); + SAYF(" new edges on : " cRST "%-20s" bSTG bV "\n", tmp); sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_crashes), u_stringify_int(IB(1), afl->unique_crashes), @@ -837,14 +837,14 @@ void show_stats(afl_state_t *afl) { if (afl->crash_mode) { - SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP - " new crashes : %s%-22s" bSTG bV "\n", + SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP + " new crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } else { - SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP - " total crashes : %s%-22s" bSTG bV "\n", + SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP + " total crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } @@ -856,12 +856,12 @@ void show_stats(afl_state_t *afl) { sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec), afl->stats_avg_exec < 20 ? "zzzz..." : "slow!"); - SAYF(bV bSTOP " exec speed : " cLRD "%-20s ", tmp); + SAYF(bV bSTOP " exec speed : " cLRD "%-22s ", tmp); } else { sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec)); - SAYF(bV bSTOP " exec speed : " cRST "%-20s ", tmp); + SAYF(bV bSTOP " exec speed : " cRST "%-22s ", tmp); } @@ -869,12 +869,12 @@ void show_stats(afl_state_t *afl) { u_stringify_int(IB(1), afl->unique_tmouts), (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-22s" bSTG bV "\n", tmp); + SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp); /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP - " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA + SAYF(bVR bH cCYA bSTOP + " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2 bH bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); if (unlikely(afl->custom_only)) { -- cgit 1.4.1 From 0d50ee494751e8dd83e24fd138e396fe940a15c7 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 5 Jun 2021 11:51:03 +0200 Subject: restored timeout handling (with SIGALRM for now) --- src/afl-analyze.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src') diff --git a/src/afl-analyze.c b/src/afl-analyze.c index aabdbf1a..5d5c4b8c 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -225,6 +225,20 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { } + +/* Handle timeout signal. */ + +static void handle_timeout(int sig) { + + (void)sig; + + child_timed_out = 1; + + if (child_pid > 0) kill(child_pid, SIGKILL); + +} + + /* Execute target application. Returns exec checksum, or 0 if program times out. */ @@ -904,6 +918,11 @@ static void setup_signal_handlers(void) { sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); + /* Exec timeout notifications. */ + + sa.sa_handler = handle_timeout; + sigaction(SIGALRM, &sa, NULL); + } /* Display usage hints. */ -- cgit 1.4.1 From a5ff9f1bebfc974a774bba896e51e18288f66c68 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Jun 2021 09:02:33 +0200 Subject: remove -D from -M --- docs/Changelog.md | 1 + src/afl-fuzz.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index a4c6ac10..b70ba022 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,6 +12,7 @@ sending a mail to . - Fix for llvm 13 - afl-fuzz: - fix -F when a '/' was part of the parameter + - removed implied -D determinstic from -M main - ensure afl-compiler-rt is built for gcc_module diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 196547f4..dc594b30 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -575,7 +575,6 @@ int main(int argc, char **argv_orig, char **envp) { } afl->sync_id = ck_strdup(optarg); - afl->skip_deterministic = 0; // force deterministic fuzzing afl->old_seed_selection = 1; // force old queue walking seed selection afl->disable_trim = 1; // disable trimming -- cgit 1.4.1 From 92fcef4520fe65fc641fd2e8d86a7c17845031c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Jun 2021 09:26:53 +0200 Subject: write target errors to out_dir/error.txt --- instrumentation/afl-compiler-rt.o.c | 134 +++++++++++++++++++++++++++++------- src/afl-analyze.c | 2 - src/afl-fuzz-stats.c | 7 +- src/afl-fuzz.c | 2 + 4 files changed, 116 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 5dacf961..a4760153 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -83,15 +83,15 @@ extern ssize_t _kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize); #endif // HAIKU -static u8 __afl_area_initial[MAP_INITIAL_SIZE]; -static u8 * __afl_area_ptr_dummy = __afl_area_initial; -static u8 * __afl_area_ptr_backup = __afl_area_initial; +static u8 __afl_area_initial[MAP_INITIAL_SIZE]; +static u8 *__afl_area_ptr_dummy = __afl_area_initial; +static u8 *__afl_area_ptr_backup = __afl_area_initial; -u8 * __afl_area_ptr = __afl_area_initial; -u8 * __afl_dictionary; -u8 * __afl_fuzz_ptr; -static u32 __afl_fuzz_len_dummy; -u32 *__afl_fuzz_len = &__afl_fuzz_len_dummy; +u8 * __afl_area_ptr = __afl_area_initial; +u8 * __afl_dictionary; +u8 * __afl_fuzz_ptr; +static u32 __afl_fuzz_len_dummy; +u32 * __afl_fuzz_len = &__afl_fuzz_len_dummy; u32 __afl_final_loc; u32 __afl_map_size = MAP_SIZE; @@ -99,8 +99,8 @@ u32 __afl_dictionary_len; u64 __afl_map_addr; // for the __AFL_COVERAGE_ON/__AFL_COVERAGE_OFF features to work: -int __afl_selective_coverage __attribute__((weak)); -int __afl_selective_coverage_start_off __attribute__((weak)); +int __afl_selective_coverage __attribute__((weak)); +int __afl_selective_coverage_start_off __attribute__((weak)); static int __afl_selective_coverage_temp = 1; #if defined(__ANDROID__) || defined(__HAIKU__) @@ -630,6 +630,30 @@ static void __afl_unmap_shm(void) { } +void write_error(char *text) { + + u8 * o = getenv("__AFL_OUT_DIR"); + char *e = strerror(errno); + + if (o) { + + char buf[4096]; + snprintf(buf, sizeof(buf), "%s/error.txt", o); + FILE *f = fopen(buf, "a"); + + if (f) { + + fprintf(f, "Error(%s): %s\n", text, e); + fclose(f); + + } + + } + + fprintf(stderr, "Error(%s): %s\n", text, e); + +} + #ifdef __linux__ static void __afl_start_snapshots(void) { @@ -656,7 +680,12 @@ static void __afl_start_snapshots(void) { if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) { - if (read(FORKSRV_FD, &was_killed, 4) != 4) { _exit(1); } + if (read(FORKSRV_FD, &was_killed, 4) != 4) { + + write_error("read to afl-fuzz"); + _exit(1); + + } if (__afl_debug) { @@ -725,7 +754,12 @@ static void __afl_start_snapshots(void) { } else { /* Wait for parent by reading from the pipe. Abort if read fails. */ - if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + if (read(FORKSRV_FD, &was_killed, 4) != 4) { + + write_error("reading from afl-fuzz"); + _exit(1); + + } } @@ -762,7 +796,12 @@ static void __afl_start_snapshots(void) { if (child_stopped && was_killed) { child_stopped = 0; - if (waitpid(child_pid, &status, 0) < 0) _exit(1); + if (waitpid(child_pid, &status, 0) < 0) { + + write_error("child_stopped && was_killed"); + _exit(1); // TODO why exit? + + } } @@ -771,7 +810,12 @@ static void __afl_start_snapshots(void) { /* Once woken up, create a clone of our process. */ child_pid = fork(); - if (child_pid < 0) _exit(1); + if (child_pid < 0) { + + write_error("fork"); + _exit(1); + + } /* In child process: close fds, resume execution. */ @@ -811,9 +855,19 @@ static void __afl_start_snapshots(void) { /* In parent process: write PID to pipe, then wait for child. */ - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1); + if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { + + write_error("write to afl-fuzz"); + _exit(1); + + } - if (waitpid(child_pid, &status, WUNTRACED) < 0) _exit(1); + if (waitpid(child_pid, &status, WUNTRACED) < 0) { + + write_error("waitpid"); + _exit(1); + + } /* In persistent mode, the child stops itself with SIGSTOP to indicate a successful run. In this case, we want to wake it up without forking @@ -823,7 +877,12 @@ static void __afl_start_snapshots(void) { /* Relay wait status to pipe, then loop back. */ - if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1); + if (write(FORKSRV_FD + 1, &status, 4) != 4) { + + write_error("writing to afl-fuzz"); + _exit(1); + + } } @@ -956,7 +1015,12 @@ static void __afl_start_forkserver(void) { } else { - if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + if (read(FORKSRV_FD, &was_killed, 4) != 4) { + + write_error("read from afl-fuzz"); + _exit(1); + + } } @@ -993,7 +1057,12 @@ static void __afl_start_forkserver(void) { if (child_stopped && was_killed) { child_stopped = 0; - if (waitpid(child_pid, &status, 0) < 0) _exit(1); + if (waitpid(child_pid, &status, 0) < 0) { + + write_error("child_stopped && was_killed"); + _exit(1); + + } } @@ -1002,7 +1071,12 @@ static void __afl_start_forkserver(void) { /* Once woken up, create a clone of our process. */ child_pid = fork(); - if (child_pid < 0) _exit(1); + if (child_pid < 0) { + + write_error("fork"); + _exit(1); + + } /* In child process: close fds, resume execution. */ @@ -1031,11 +1105,20 @@ static void __afl_start_forkserver(void) { /* In parent process: write PID to pipe, then wait for child. */ - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1); + if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { - if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) + write_error("write to afl-fuzz"); _exit(1); + } + + if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) { + + write_error("waitpid"); + _exit(1); + + } + /* In persistent mode, the child stops itself with SIGSTOP to indicate a successful run. In this case, we want to wake it up without forking again. */ @@ -1044,7 +1127,12 @@ static void __afl_start_forkserver(void) { /* Relay wait status to pipe, then loop back. */ - if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1); + if (write(FORKSRV_FD + 1, &status, 4) != 4) { + + write_error("writing to afl-fuzz"); + _exit(1); + + } } diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 5d5c4b8c..d43278b9 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -225,7 +225,6 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { } - /* Handle timeout signal. */ static void handle_timeout(int sig) { @@ -238,7 +237,6 @@ static void handle_timeout(int sig) { } - /* Execute target application. Returns exec checksum, or 0 if program times out. */ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 89d2c37d..9648d795 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -768,7 +768,7 @@ void show_stats(afl_state_t *afl) { SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA - " map coverage" bSTG bHT bH20 bH2 bVL "\n"); + " map coverage" bSTG bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -873,9 +873,8 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP - " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2 bH bHB bH bSTOP cCYA - " path geometry " bSTG bH5 bH2 bVL "\n"); + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2 + bH bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); if (unlikely(afl->custom_only)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index dc594b30..9a3780fb 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1205,6 +1205,8 @@ int main(int argc, char **argv_orig, char **envp) { } + setenv("__AFL_OUT_DIR", afl->out_dir, 1); + if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; } if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) { -- cgit 1.4.1 From 63ee9df54f3c9db8ecbb0fb6186ea912200d9126 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 7 Jun 2021 20:49:23 +0200 Subject: Forkserver for afl-analyze (#963) * afl-analyze forkserver * added missing vars to forkserver * synchronized a bit more with afl-tmin * more debugging, runs now, but need to suppress target output * fix dev/null setting * afl-analyze info: Co-authored-by: hexcoder- --- GNUmakefile | 4 +- docs/Changelog.md | 3 +- src/afl-analyze.c | 235 +++++++++++++++++++----------------------------------- 3 files changed, 84 insertions(+), 158 deletions(-) (limited to 'src') diff --git a/GNUmakefile b/GNUmakefile index 6df7ea1d..bd206af0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -436,8 +436,8 @@ afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-fork afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS) -afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS) +afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS) afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) diff --git a/docs/Changelog.md b/docs/Changelog.md index a2c523b0..a8ed4d72 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -18,8 +18,7 @@ sending a mail to . - afl-cc - support partial linking - ensure afl-compiler-rt is built for gcc_module - - + - afl-analyze now uses the forkserver for increased performance ### Version ++3.13c (release) - Note: plot_data switched to relative time from unix time in 3.10 - frida_mode - new mode that uses frida to fuzz binary-only targets, diff --git a/src/afl-analyze.c b/src/afl-analyze.c index d43278b9..606254d9 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -55,12 +55,7 @@ #include #include -static s32 child_pid; /* PID of the tested program */ - -static u8 *trace_bits; /* SHM with instrumentation bitmap */ - -static u8 *in_file, /* Analyzer input test case */ - *prog_in; /* Targeted program input file */ +static u8 *in_file; /* Analyzer input test case */ static u8 *in_data; /* Input data for analysis */ @@ -73,20 +68,19 @@ static u64 orig_cksum; /* Original checksum */ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ -static s32 dev_null_fd = -1; /* FD to /dev/null */ - static bool edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ use_stdin = true; /* Use stdin for program input? */ -static volatile u8 stop_soon, /* Ctrl-C pressed? */ - child_timed_out; /* Child timed out? */ +static volatile u8 stop_soon; /* Ctrl-C pressed? */ static u8 *target_path; static u8 frida_mode; static u8 qemu_mode; static u32 map_size = MAP_SIZE; +static afl_forkserver_t fsrv = {0}; /* The forkserver */ + /* Constants used for describing byte behavior. */ #define RESP_NONE 0x00 /* Changing byte is a no-op. */ @@ -156,7 +150,7 @@ static void classify_counts(u8 *mem) { static inline u8 anything_set(void) { - u32 *ptr = (u32 *)trace_bits; + u32 *ptr = (u32 *)fsrv.trace_bits; u32 i = (map_size >> 2); while (i--) { @@ -173,7 +167,7 @@ static inline u8 anything_set(void) { static void at_exit_handler(void) { - unlink(prog_in); /* Ignore errors */ + unlink(fsrv.out_file); /* Ignore errors */ } @@ -205,128 +199,29 @@ static void read_initial_file(void) { } -/* Write output file. */ - -static s32 write_to_file(u8 *path, u8 *mem, u32 len) { - - s32 ret; - - unlink(path); /* Ignore errors */ - - ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - - if (ret < 0) { PFATAL("Unable to create '%s'", path); } - - ck_write(ret, mem, len, path); - - lseek(ret, 0, SEEK_SET); - - return ret; - -} - -/* Handle timeout signal. */ - -static void handle_timeout(int sig) { - - (void)sig; - - child_timed_out = 1; - - if (child_pid > 0) kill(child_pid, SIGKILL); - -} - /* Execute target application. Returns exec checksum, or 0 if program times out. */ -static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { - - static struct itimerval it; - int status = 0; - - s32 prog_in_fd; - u64 cksum; - - memset(trace_bits, 0, map_size); - MEM_BARRIER(); - - prog_in_fd = write_to_file(prog_in, mem, len); - - child_pid = fork(); - - if (child_pid < 0) { PFATAL("fork() failed"); } - - if (!child_pid) { - - struct rlimit r; - - if (dup2(use_stdin ? prog_in_fd : dev_null_fd, 0) < 0 || - dup2(dev_null_fd, 1) < 0 || dup2(dev_null_fd, 2) < 0) { - - *(u32 *)trace_bits = EXEC_FAIL_SIG; - PFATAL("dup2() failed"); - - } - - close(dev_null_fd); - close(prog_in_fd); - - if (mem_limit) { +static u32 analyze_run_target(u8 *mem, u32 len, u8 first_run) { - r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; + afl_fsrv_write_to_testcase(&fsrv, mem, len); + fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon); -#ifdef RLIMIT_AS + if (ret == FSRV_RUN_ERROR) { - setrlimit(RLIMIT_AS, &r); /* Ignore errors */ + FATAL("Error in forkserver"); -#else - - setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ - -#endif /* ^RLIMIT_AS */ - - } + } else if (ret == FSRV_RUN_NOINST) { - r.rlim_max = r.rlim_cur = 0; - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + FATAL("Target not instrumented"); - execv(target_path, argv); + } else if (ret == FSRV_RUN_NOBITS) { - *(u32 *)trace_bits = EXEC_FAIL_SIG; - exit(0); + FATAL("Failed to run target"); } - close(prog_in_fd); - - /* Configure timeout, wait for child, cancel timeout. */ - - child_timed_out = 0; - it.it_value.tv_sec = (exec_tmout / 1000); - it.it_value.tv_usec = (exec_tmout % 1000) * 1000; - - setitimer(ITIMER_REAL, &it, NULL); - - if (waitpid(child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); } - - child_pid = 0; - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - MEM_BARRIER(); - - /* Clean up bitmap, analyze exit condition, etc. */ - - if (*(u32 *)trace_bits == EXEC_FAIL_SIG) { - - FATAL("Unable to execute '%s'", argv[0]); - - } - - classify_counts(trace_bits); + classify_counts(fsrv.trace_bits); total_execs++; if (stop_soon) { @@ -338,21 +233,19 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { /* Always discard inputs that time out. */ - if (child_timed_out) { + if (fsrv.last_run_timed_out) { exec_hangs++; return 0; } - cksum = hash64(trace_bits, map_size, HASH_CONST); + u64 cksum = hash64(fsrv.trace_bits, fsrv.map_size, HASH_CONST); - /* We don't actually care if the target is crashing or not, - except that when it does, the checksum should be different. */ + if (ret == FSRV_RUN_CRASH) { - if (WIFSIGNALED(status) || - (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) || - (WIFEXITED(status) && WEXITSTATUS(status))) { + /* We don't actually care if the target is crashing or not, + except that when it does, the checksum should be different. */ cksum ^= 0xffffffff; @@ -616,7 +509,7 @@ static void dump_hex(u32 len, u8 *b_data) { /* Actually analyze! */ -static void analyze(char **argv) { +static void analyze() { u32 i; u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0; @@ -642,16 +535,16 @@ static void analyze(char **argv) { code. */ in_data[i] ^= 0xff; - xor_ff = analyze_run_target(argv, in_data, in_len, 0); + xor_ff = analyze_run_target(in_data, in_len, 0); in_data[i] ^= 0xfe; - xor_01 = analyze_run_target(argv, in_data, in_len, 0); + xor_01 = analyze_run_target(in_data, in_len, 0); in_data[i] = (in_data[i] ^ 0x01) - 0x10; - sub_10 = analyze_run_target(argv, in_data, in_len, 0); + sub_10 = analyze_run_target(in_data, in_len, 0); in_data[i] += 0x20; - add_10 = analyze_run_target(argv, in_data, in_len, 0); + add_10 = analyze_run_target(in_data, in_len, 0); in_data[i] -= 0x10; /* Classify current behavior. */ @@ -724,7 +617,7 @@ static void handle_stop_sig(int sig) { (void)sig; stop_soon = 1; - if (child_pid > 0) { kill(child_pid, SIGKILL); } + afl_fsrv_killall(); } @@ -736,10 +629,10 @@ static void set_up_environment(char **argv) { char *afl_preload; char *frida_afl_preload = NULL; - dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } + fsrv.dev_null_fd = open("/dev/null", O_RDWR); + if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } - if (!prog_in) { + if (!fsrv.out_file) { u8 *use_dir = "."; @@ -750,10 +643,15 @@ static void set_up_environment(char **argv) { } - prog_in = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid()); + fsrv.out_file = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid()); } + unlink(fsrv.out_file); + fsrv.out_fd = open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + + if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); } + /* Set sane defaults... */ x = get_afl_env("ASAN_OPTIONS"); @@ -916,11 +814,6 @@ static void setup_signal_handlers(void) { sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); - /* Exec timeout notifications. */ - - sa.sa_handler = handle_timeout; - sigaction(SIGALRM, &sa, NULL); - } /* Display usage hints. */ @@ -982,6 +875,8 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n"); + afl_fsrv_init(&fsrv); + while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) { switch (opt) { @@ -994,9 +889,9 @@ int main(int argc, char **argv_orig, char **envp) { case 'f': - if (prog_in) { FATAL("Multiple -f options not supported"); } - use_stdin = 0; - prog_in = optarg; + if (fsrv.out_file) { FATAL("Multiple -f options not supported"); } + fsrv.use_stdin = 0; + fsrv.out_file = ck_strdup(optarg); break; case 'e': @@ -1017,6 +912,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!strcmp(optarg, "none")) { mem_limit = 0; + fsrv.mem_limit = 0; break; } @@ -1055,6 +951,8 @@ int main(int argc, char **argv_orig, char **envp) { } + fsrv.mem_limit = mem_limit; + } break; @@ -1074,6 +972,8 @@ int main(int argc, char **argv_orig, char **envp) { } + fsrv.exec_tmout = exec_tmout; + break; case 'O': /* FRIDA mode */ @@ -1081,6 +981,7 @@ int main(int argc, char **argv_orig, char **envp) { if (frida_mode) { FATAL("Multiple -O options not supported"); } frida_mode = 1; + fsrv.frida_mode = frida_mode; break; @@ -1090,6 +991,8 @@ int main(int argc, char **argv_orig, char **envp) { if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; } qemu_mode = 1; + fsrv.mem_limit = mem_limit; + fsrv.qemu_mode = qemu_mode; break; case 'U': @@ -1098,6 +1001,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; } unicorn_mode = 1; + fsrv.mem_limit = mem_limit; break; case 'W': /* Wine+QEMU mode */ @@ -1107,6 +1011,8 @@ int main(int argc, char **argv_orig, char **envp) { use_wine = 1; if (!mem_limit_given) { mem_limit = 0; } + fsrv.qemu_mode = qemu_mode; + fsrv.mem_limit = mem_limit; break; @@ -1125,6 +1031,7 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file) { usage(argv[0]); } map_size = get_map_size(); + fsrv.map_size = map_size; use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); @@ -1134,14 +1041,15 @@ int main(int argc, char **argv_orig, char **envp) { /* initialize cmplog_mode */ shm.cmplog_mode = 0; - trace_bits = afl_shm_init(&shm, map_size, 0); + atexit(at_exit_handler); setup_signal_handlers(); set_up_environment(argv); - target_path = find_binary(argv[optind]); - detect_file_args(argv + optind, prog_in, &use_stdin); + fsrv.target_path = find_binary(argv[optind]); + fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); + detect_file_args(argv + optind, fsrv.out_file, &use_stdin); if (qemu_mode) { @@ -1165,14 +1073,31 @@ int main(int argc, char **argv_orig, char **envp) { SAYF("\n"); + if (getenv("AFL_FORKSRV_INIT_TMOUT")) { + + s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT")); + if (forksrv_init_tmout < 1) { + + FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT"); + + } + + fsrv.init_tmout = (u32)forksrv_init_tmout; + + } + + fsrv.kill_signal = + parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); + read_initial_file(); ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); - analyze_run_target(use_argv, in_data, in_len, 1); + afl_fsrv_start(&fsrv, use_argv, &stop_soon, false); + analyze_run_target(in_data, in_len, 1); - if (child_timed_out) { + if (fsrv.last_run_timed_out) { FATAL("Target binary times out (adjusting -t may help)."); @@ -1184,13 +1109,15 @@ int main(int argc, char **argv_orig, char **envp) { } - analyze(use_argv); + analyze(); OKF("We're done here. Have a nice day!\n"); - if (target_path) { ck_free(target_path); } - afl_shm_deinit(&shm); + afl_fsrv_deinit(&fsrv); + if (fsrv.target_path) { ck_free(fsrv.target_path); } + if (in_data) { ck_free(in_data); } + exit(0); -- cgit 1.4.1 From a7340a1ac6c6165c8eb390a503758104c0d85bcb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 10 Jun 2021 10:25:37 +0200 Subject: fix AFL_CAL_FAST --- docs/Changelog.md | 1 + docs/env_variables.md | 4 +--- include/afl-fuzz.h | 4 +--- src/afl-analyze.c | 9 +++++---- src/afl-fuzz-run.c | 5 +++-- src/afl-fuzz-state.c | 9 +++++++-- src/afl-fuzz.c | 9 --------- 7 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 6c851460..29ef69f9 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,6 +15,7 @@ sending a mail to . - removed implied -D determinstic from -M main - if the target becomes unavailable check out out/default/error.txt for an indicator why + - AFL_CAL_FAST was a dead env, now does the same as AFL_FAST_CAL - afl-cc - support partial linking - We do support llvm versions from 3.8 again diff --git a/docs/env_variables.md b/docs/env_variables.md index 38a67bc7..e058f377 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -108,9 +108,6 @@ make fairly broad use of environmental variables instead: - Setting `AFL_QUIET` will prevent afl-cc and afl-as banners from being displayed during compilation, in case you find them distracting. - - Setting `AFL_CAL_FAST` will speed up the initial calibration, if the - application is very slow. - ## 2) Settings for LLVM and LTO: afl-clang-fast / afl-clang-fast++ / afl-clang-lto / afl-clang-lto++ The native instrumentation helpers (instrumentation and gcc_plugin) accept a subset @@ -386,6 +383,7 @@ checks or alter some of the more exotic semantics of the tool: - `AFL_FAST_CAL` keeps the calibration stage about 2.5x faster (albeit less precise), which can help when starting a session against a slow target. + `AFL_CAL_FAST` works too. - The CPU widget shown at the bottom of the screen is fairly simplistic and may complain of high load prematurely, especially on systems with low core diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 4aba3bdf..2920f905 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -478,9 +478,7 @@ typedef struct afl_state { u32 hang_tmout; /* Timeout used for hang det (ms) */ - u8 cal_cycles, /* Calibration cycles defaults */ - cal_cycles_long, /* Calibration cycles defaults */ - havoc_stack_pow2, /* HAVOC_STACK_POW2 */ + u8 havoc_stack_pow2, /* HAVOC_STACK_POW2 */ no_unlink, /* do not unlink cur_input */ debug, /* Debug mode */ custom_only, /* Custom mutator only mode */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 606254d9..dbf2920f 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -167,7 +167,7 @@ static inline u8 anything_set(void) { static void at_exit_handler(void) { - unlink(fsrv.out_file); /* Ignore errors */ + unlink(fsrv.out_file); /* Ignore errors */ } @@ -643,12 +643,14 @@ static void set_up_environment(char **argv) { } - fsrv.out_file = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid()); + fsrv.out_file = + alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid()); } unlink(fsrv.out_file); - fsrv.out_fd = open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + fsrv.out_fd = + open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); } @@ -1118,7 +1120,6 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv.target_path) { ck_free(fsrv.target_path); } if (in_data) { ck_free(in_data); } - exit(0); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 493735ff..758bad25 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -314,7 +314,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, ++q->cal_failed; afl->stage_name = "calibration"; - afl->stage_max = afl->fast_cal ? 3 : CAL_CYCLES; + afl->stage_max = afl->afl_env.afl_cal_fast ? 3 : CAL_CYCLES; /* Make sure the forkserver is up before we do anything, and let's not count its spin-up time toward binary calibration. */ @@ -403,7 +403,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } var_detected = 1; - afl->stage_max = afl->fast_cal ? CAL_CYCLES : CAL_CYCLES_LONG; + afl->stage_max = + afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; } else { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 0658070e..b832c11e 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -96,8 +96,6 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->splicing_with = -1; /* Splicing with which test case? */ afl->cpu_to_bind = -1; afl->havoc_stack_pow2 = HAVOC_STACK_POW2; - afl->cal_cycles = CAL_CYCLES; - afl->cal_cycles_long = CAL_CYCLES_LONG; afl->hang_tmout = EXEC_TIMEOUT; afl->exit_on_time = 0; afl->stats_update_freq = 1; @@ -341,6 +339,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_cal_fast = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_FAST_CAL", + + afl_environment_variable_len)) { + + afl->afl_env.afl_cal_fast = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_STATSD", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9a3780fb..e9a67ac5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1276,7 +1276,6 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; } 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_FAST_CAL")) { afl->fast_cal = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } if (afl->afl_env.afl_autoresume) { @@ -1489,14 +1488,6 @@ int main(int argc, char **argv_orig, char **envp) { check_if_tty(afl); if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } - if (afl->afl_env.afl_cal_fast) { - - /* Use less calibration cycles, for slow applications */ - afl->cal_cycles = 3; - afl->cal_cycles_long = 5; - - } - if (afl->afl_env.afl_custom_mutator_only) { /* This ensures we don't proceed to havoc/splice */ -- cgit 1.4.1 From 63504f7b7e9f17145b63ba7d5a9e837e17ccb3a6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 11 Jun 2021 10:44:06 +0200 Subject: fix cmplog screen update crash --- docs/Changelog.md | 3 +- src/afl-common.c | 2 ++ src/afl-fuzz-redqueen.c | 91 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 29ef69f9..97903c2a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,9 +9,9 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.14a (release) - - Fix for llvm 13 - afl-fuzz: - fix -F when a '/' was part of the parameter + - fixed a crash for cmplog for very slow inputs - removed implied -D determinstic from -M main - if the target becomes unavailable check out out/default/error.txt for an indicator why @@ -21,6 +21,7 @@ sending a mail to . - We do support llvm versions from 3.8 again - afl_analyze - fix timeout handling and support forkserver + - Fix for llvm 13 - ensure afl-compiler-rt is built for gcc_module - afl-analyze now uses the forkserver for increased performance diff --git a/src/afl-common.c b/src/afl-common.c index c61ce3d8..9ca2b3e8 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -751,6 +751,8 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { } +/* Get unix time in milliseconds */ + u64 get_cur_time(void) { struct timeval tv; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index b41ffa88..268f726c 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -252,7 +252,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 start_time = get_cur_time(); #endif - u32 screen_update = 1000000 / afl->queue_cur->exec_us; + u32 screen_update; u64 orig_hit_cnt, new_hit_cnt, exec_cksum; orig_hit_cnt = afl->queued_paths + afl->unique_crashes; @@ -261,6 +261,24 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, afl->stage_max = (len << 1); afl->stage_cur = 0; + if (likely(afl->queue_cur->exec_us)) { + + if (likely((100000 / 2) >= afl->queue_cur->exec_us)) { + + screen_update = 100000 / afl->queue_cur->exec_us; + + } else { + + screen_update = 1; + + } + + } else { + + screen_update = 100000; + + } + // in colorization we do not classify counts, hence we have to calculate // the original checksum. if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) { @@ -905,17 +923,16 @@ 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, - h->shape + 1, 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, + h->shape + 1, 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 u64 new_repl = (u64)((s64)repl - diff); - // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); if (unlikely(cmp_extend_encoding( afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, @@ -935,15 +952,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, diff = pattern ^ b_val; s64 o_diff = o_pattern ^ o_b_val; - /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n", - idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, - "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); + fprintf(stderr, + "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); + */ if (diff == o_diff && diff) { // this could be a XOR transformation u64 new_repl = (u64)((s64)repl ^ diff); - // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); if (unlikely(cmp_extend_encoding( afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, @@ -982,15 +1001,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n", - idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, - "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); + fprintf(stderr, + "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); + */ if (o_diff && diff) { // this could be a lower to upper u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask)); - // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); if (unlikely(cmp_extend_encoding( afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, @@ -1029,15 +1050,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n", - idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, - "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); + fprintf(stderr, + "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); + */ if (o_diff && diff) { // this could be a lower to upper u64 new_repl = (repl | (0x2020202020202020 & mask)); - // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); if (unlikely(cmp_extend_encoding( afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, @@ -1383,7 +1406,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - //#endif /* CMPLOG_SOLVE_ARITHMETIC + //#endif /* + // CMPLOG_SOLVE_ARITHMETIC return 0; @@ -2152,7 +2176,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, memcpy(buf + idx, tmp, i + 1); if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex, *status); + // fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex, + // *status); } @@ -2235,7 +2260,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, for (j = 0; j <= i; j++) buf[idx + j] = repl[j] - arith_val[j]; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith, *status); + // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith, + // *status); } @@ -2328,16 +2354,17 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, /* 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, - h->shape, 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 id=%u shape=%u attr=%u - o0=", hh->hits, hh->id, hh->shape, hh->attribute); for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", orig_o->v0[j]); - fprintf(stderr, " o1="); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", orig_o->v1[j]); - fprintf(stderr, "\n"); + fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, + h->id, h->shape, 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 id=%u shape=%u attr=%u o0=", + hh->hits, hh->id, hh->shape, hh->attribute); + for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]); + fprintf(stderr, " o1="); + for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]); + fprintf(stderr, "\n"); */ t = taint; -- cgit 1.4.1 From 74fcb365e99ce86e405e52b586baa9d0f825f70c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 14 Jun 2021 12:36:41 +0200 Subject: little inline --- src/afl-fuzz-one.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c3ce2edd..11adebf4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -73,7 +73,7 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) { /* Helper to choose random block len for block operations in fuzz_one(). Doesn't return zero, provided that max_len is > 0. */ -static u32 choose_block_len(afl_state_t *afl, u32 limit) { +static inline u32 choose_block_len(afl_state_t *afl, u32 limit) { u32 min_value, max_value; u32 rlim = MIN(afl->queue_cycle, (u32)3); -- cgit 1.4.1 From ef5fd33120ca2b5a0a8a3e282224e67ac93f44a2 Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Mon, 14 Jun 2021 15:21:01 -0400 Subject: Add debug output to alert user to calibration progress/issues (#969) --- src/afl-fuzz-run.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 758bad25..fb0b5ead 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -355,6 +355,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { + if (unlikely(afl->debug)) { DEBUGF("calibration stage %d/%d\n", afl->stage_cur+1, afl->stage_max); } + u64 cksum; write_to_testcase(afl, use_mem, q->len); @@ -402,6 +404,15 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } + if (unlikely(!var_detected)) { + // note: from_queue seems to only be set during initialization + if (afl->afl_env.afl_no_ui || from_queue) { + WARNF("instability detected during calibration\n"); + } else if (afl->debug) { + DEBUGF("instability detected during calibration\n"); + } + } + var_detected = 1; afl->stage_max = afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; -- cgit 1.4.1 From f3362007edb30cf411b7bee7c013c4e71dc69e39 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 14 Jun 2021 22:59:48 +0200 Subject: code format --- src/afl-fuzz-run.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index fb0b5ead..49856a9f 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -355,7 +355,11 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - if (unlikely(afl->debug)) { DEBUGF("calibration stage %d/%d\n", afl->stage_cur+1, afl->stage_max); } + if (unlikely(afl->debug)) { + + DEBUGF("calibration stage %d/%d\n", afl->stage_cur + 1, afl->stage_max); + + } u64 cksum; @@ -405,12 +409,18 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } if (unlikely(!var_detected)) { + // note: from_queue seems to only be set during initialization if (afl->afl_env.afl_no_ui || from_queue) { + WARNF("instability detected during calibration\n"); + } else if (afl->debug) { + DEBUGF("instability detected during calibration\n"); + } + } var_detected = 1; -- cgit 1.4.1 From a6c0b5f7667475336a26197d99ea24f18ffcdbd7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 16 Jun 2021 11:46:26 +0200 Subject: afl-cmin/afl-cmin.bash/afl-showmap -i descend into subdirectories --- docs/Changelog.md | 2 + src/afl-showmap.c | 159 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 9f70535a..530dd941 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -31,6 +31,8 @@ sending a mail to . - afl_analyze: - fix timeout handling - add forkserver support for better performance + - afl-cmin, afl-cmin.bash and afl-showmap -i do now descend into + subdirectories (like afl-fuzz does) - ensure afl-compiler-rt is built for gcc_module ### Version ++3.13c (release) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 96b72dd9..03050d91 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -67,6 +67,8 @@ static char *stdin_file; /* stdin file */ static u8 *in_dir = NULL, /* input folder */ *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */ +static u8 outfile[PATH_MAX]; + static u8 *in_data, /* Input data */ *coverage_map; /* Coverage map */ @@ -88,7 +90,8 @@ static bool quiet_mode, /* Hide non-essential messages? */ have_coverage, /* have coverage? */ no_classify, /* do not classify counts */ debug, /* debug mode */ - print_filenames; /* print the current filename */ + print_filenames, /* print the current filename */ + wait_for_gdb; static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -692,6 +695,93 @@ static void setup_signal_handlers(void) { } +u32 execute_testcases(u8 *dir) { + + struct dirent **nl; + s32 nl_cnt, subdirs = 1; + u32 i, done = 0; + u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX]; + + if (!be_quiet) { ACTF("Scanning '%s'...", dir); } + + /* We use scandir() + alphasort() rather than readdir() because otherwise, + the ordering of test cases would vary somewhat randomly and would be + difficult to control. */ + + nl_cnt = scandir(dir, &nl, NULL, alphasort); + + if (nl_cnt < 0) { return 0; } + + for (i = 0; i < (u32)nl_cnt; ++i) { + + struct stat st; + + u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name); + + if (lstat(fn2, &st) || access(fn2, R_OK)) { + + PFATAL("Unable to access '%s'", fn2); + + } + + /* obviously we want to skip "descending" into . and .. directories, + however it is a good idea to skip also directories that start with + a dot */ + if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') { + + free(nl[i]); /* not tracked */ + done += execute_testcases(fn2); + ck_free(fn2); + continue; + + } + + free(nl[i]); + + if (!S_ISREG(st.st_mode) || !st.st_size) { + + ck_free(fn2); + continue; + + } + + if (st.st_size > MAX_FILE && !be_quiet) { + + WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2, + stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), + stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE)); + + } + + // DO + if (read_file(fn2)) { + + if (wait_for_gdb) { + + fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid); + fprintf(stderr, "exec: kill -CONT %d\n", getpid()); + kill(0, SIGSTOP); + + } + + showmap_run_target_forkserver(fsrv, in_data, in_len); + ck_free(in_data); + ++done; + + if (collect_coverage) + analyze_results(fsrv); + else + tcnt = write_results_to_file(fsrv, outfile); + + } + + } + + free(nl); /* not tracked */ + return done; + +} + /* Show banner. */ static void show_banner(void) { @@ -1136,15 +1226,7 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir) { - DIR * dir_in, *dir_out = NULL; - struct dirent **file_list; - - // int done = 0; - u8 infile[PATH_MAX], outfile[PATH_MAX]; - u8 wait_for_gdb = 0; -#if !defined(DT_REG) - struct stat statbuf; -#endif + DIR *dir_in, *dir_out = NULL; if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true; @@ -1245,65 +1327,12 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - int file_count = scandir(in_dir, &file_list, NULL, alphasort); - if (file_count < 0) { + if (execute_testcases(in_dir) == 0) { - PFATAL("Failed to read from input dir at %s\n", in_dir); + FATAL("could not read input testcases from %s", in_dir); } - for (int i = 0; i < file_count; i++) { - - struct dirent *dir_ent = file_list[i]; - - if (dir_ent->d_name[0] == '.') { - - continue; // skip anything that starts with '.' - - } - -#if defined(DT_REG) /* Posix and Solaris do not know d_type and DT_REG */ - if (dir_ent->d_type != DT_REG) { - - continue; // only regular files - - } - -#endif - - snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name); - -#if !defined(DT_REG) /* use stat() */ - if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue; -#endif - - if (!collect_coverage) - snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name); - - if (read_file(infile)) { - - if (wait_for_gdb) { - - fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid); - fprintf(stderr, "exec: kill -CONT %d\n", getpid()); - kill(0, SIGSTOP); - - } - - showmap_run_target_forkserver(fsrv, in_data, in_len); - ck_free(in_data); - if (collect_coverage) - analyze_results(fsrv); - else - tcnt = write_results_to_file(fsrv, outfile); - - } - - } - - free(file_list); - file_list = NULL; - if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); } if (dir_out) { closedir(dir_out); } -- cgit 1.4.1 From c46f8c1f70918056e95c801b1a81f11c79304b05 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 16 Jun 2021 13:03:42 +0200 Subject: make afl-cmin actually work with subdirectories --- afl-cmin | 42 ++++++++++++++++++-------------- docs/Changelog.md | 4 ++-- instrumentation/afl-compiler-rt.o.c | 2 +- src/afl-showmap.c | 48 +++++++++++++++++++++---------------- 4 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/afl-cmin b/afl-cmin index 9fa63ec6..e71873d3 100755 --- a/afl-cmin +++ b/afl-cmin @@ -296,13 +296,13 @@ BEGIN { exit 1 } - if (0 == system( "test -d "in_dir"/default" )) { - in_dir = in_dir "/default" - } - - if (0 == system( "test -d "in_dir"/queue" )) { - in_dir = in_dir "/queue" - } + #if (0 == system( "test -d "in_dir"/default" )) { + # in_dir = in_dir "/default" + #} + # + #if (0 == system( "test -d "in_dir"/queue" )) { + # in_dir = in_dir "/queue" + #} system("rm -rf "trace_dir" 2>/dev/null"); system("rm "out_dir"/id[:_]* 2>/dev/null") @@ -355,30 +355,35 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "(cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r)" + cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r)" #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" while (cmdline | getline) { sub(/^[0-9]+ (\.\/)?/,"",$0) - infilesSmallToBig[i++] = $0 + infilesSmallToBigFull[i] = $0 + sub(/.*\//, "", $0) + infilesSmallToBig[i] = $0 + infilesSmallToBigMap[infilesSmallToBig[i]] = infilesSmallToBigFull[i] + infilesSmallToBigFullMap[infilesSmallToBigFull[i]] = infilesSmallToBig[i] + i++ } in_count = i - first_file = infilesSmallToBig[0] + first_file = infilesSmallToBigFull[0] - # Make sure that we're not dealing with a directory. - - if (0 == system("test -d ""\""in_dir"/"first_file"\"")) { - print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr" - exit 1 - } + #if (0 == system("test -d ""\""in_dir"/"first_file"\"")) { + # print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr" + # exit 1 + #} - if (0 == system("ln \""in_dir"/"first_file"\" "trace_dir"/.link_test")) { + system(">\""in_dir"/.afl-cmin.test\"") + if (0 == system("ln \""in_dir"/.afl-cmin.test\" "trace_dir"/.link_test")) { cp_tool = "ln" } else { cp_tool = "cp" } + system("rm -f \""in_dir"/.afl-cmin.test\"") if (!ENVIRON["AFL_SKIP_BIN_CHECK"]) { # Make sure that we can actually get anything out of afl-showmap before we @@ -511,7 +516,8 @@ BEGIN { # copy file unless already done if (! (fn in file_already_copied)) { - system(cp_tool" \""in_dir"/"fn"\" \""out_dir"/"fn"\"") + realfile = infilesSmallToBigMap[fn] + system(cp_tool" \""in_dir"/"realfile"\" \""out_dir"/"fn"\"") file_already_copied[fn] = "" ++out_count #printf "tuple nr %d (%d cnt=%d) -> %s\n",tcnt,key,key_count[key],fn > trace_dir"/.log" diff --git a/docs/Changelog.md b/docs/Changelog.md index 530dd941..9fd2a1a9 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -31,8 +31,8 @@ sending a mail to . - afl_analyze: - fix timeout handling - add forkserver support for better performance - - afl-cmin, afl-cmin.bash and afl-showmap -i do now descend into - subdirectories (like afl-fuzz does) + - afl-cmin and afl-showmap -i do now descend into subdirectories + (like afl-fuzz does) - note that afl-cmin.bash does not! - ensure afl-compiler-rt is built for gcc_module ### Version ++3.13c (release) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 50117012..404b761f 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1019,7 +1019,7 @@ static void __afl_start_forkserver(void) { if (read(FORKSRV_FD, &was_killed, 4) != 4) { - write_error("read from afl-fuzz"); + //write_error("read from afl-fuzz"); _exit(1); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 03050d91..646396ad 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -233,7 +233,11 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), caa = !!getenv("AFL_CMIN_ALLOW_ANY"); - if (!outfile) { FATAL("Output filename not set (Bug in AFL++?)"); } + if (!outfile || !*outfile) { + + FATAL("Output filename not set (Bug in AFL++?)"); + + } if (cmin_mode && (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) { @@ -753,7 +757,9 @@ u32 execute_testcases(u8 *dir) { } - // DO + if (!collect_coverage) + snprintf(outfile, sizeof(outfile), "%s/%s", out_file, nl[i]->d_name); + if (read_file(fn2)) { if (wait_for_gdb) { @@ -800,31 +806,31 @@ static void usage(u8 *argv0) { "\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" "Required parameters:\n" - " -o file - file to write the trace data to\n\n" + " -o file - file to write the trace data to\n\n" "Execution control settings:\n" - " -t msec - timeout for each run (none)\n" - " -m megs - memory limit for child process (%u MB)\n" - " -O - use binary-only instrumentation (FRIDA mode)\n" - " -Q - use binary-only instrumentation (QEMU mode)\n" - " -U - use Unicorn-based instrumentation (Unicorn mode)\n" - " -W - use qemu-based instrumentation with Wine (Wine mode)\n" - " (Not necessary, here for consistency with other afl-* " + " -t msec - timeout for each run (none)\n" + " -m megs - memory limit for child process (%u MB)\n" + " -O - use binary-only instrumentation (FRIDA mode)\n" + " -Q - use binary-only instrumentation (QEMU mode)\n" + " -U - use Unicorn-based instrumentation (Unicorn mode)\n" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n" + " (Not necessary, here for consistency with other afl-* " "tools)\n\n" "Other settings:\n" - " -i dir - process all files in this directory, must be combined " + " -i dir - process all files below this directory, must be combined " "with -o.\n" - " With -C, -o is a file, without -C it must be a " + " 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 " + " 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" - " -s - do not classify the map\n" - " -c - allow core dumps\n\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" + " -s - do not classify the map\n" + " -c - allow core dumps\n\n" "This tool displays raw tuple data captured by AFL instrumentation.\n" "For additional help, consult %s/README.md.\n\n" @@ -1259,7 +1265,7 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if ((coverage_map = (u8 *)malloc(map_size)) == NULL) + if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL) FATAL("coult not grab memory"); edges_only = false; raw_instr_output = true; -- cgit 1.4.1 From 35153e9b495e3f61c032a3d911e4906fed0b50d6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 16 Jun 2021 15:33:03 +0200 Subject: correct map size for small targets --- TODO.md | 2 -- include/forkserver.h | 1 + instrumentation/afl-compiler-rt.o.c | 6 ------ src/afl-forkserver.c | 10 ++++++---- src/afl-fuzz-run.c | 3 +-- src/afl-fuzz-stats.c | 17 +++++++++-------- 6 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/TODO.md b/TODO.md index 398f3d11..1c616b4a 100644 --- a/TODO.md +++ b/TODO.md @@ -2,13 +2,11 @@ ## Roadmap 3.00+ - - align map to 64 bytes but keep real IDs - Update afl->pending_not_fuzzed for MOpt - put fuzz target in top line of UI - afl-plot to support multiple plot_data - afl_custom_fuzz_splice_optin() - afl_custom_splice() - - intel-pt tracer - better autodetection of shifting runtime timeout values - cmplog: use colorization input for havoc? - parallel builds for source-only targets diff --git a/include/forkserver.h b/include/forkserver.h index 2baa6f0a..c6f7de00 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -54,6 +54,7 @@ typedef struct afl_forkserver { u32 exec_tmout; /* Configurable exec timeout (ms) */ u32 init_tmout; /* Configurable init timeout (ms) */ u32 map_size; /* map size used by the target */ + u32 real_map_size; /* real map size, unaligned */ u32 snapshot; /* is snapshot feature used */ u64 mem_limit; /* Memory cap for child (MB) */ diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 404b761f..92deff6a 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -271,12 +271,6 @@ static void __afl_map_shm(void) { if (__afl_final_loc) { - if (__afl_final_loc % 64) { - - __afl_final_loc = (((__afl_final_loc + 63) >> 6) << 6); - - } - __afl_map_size = __afl_final_loc; if (__afl_final_loc > MAP_SIZE) { diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3d472b36..8fb8a75a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -90,6 +90,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { /* exec related stuff */ fsrv->child_pid = -1; fsrv->map_size = get_map_size(); + fsrv->real_map_size = fsrv->map_size; fsrv->use_fauxsrv = false; fsrv->last_run_timed_out = false; fsrv->debug = false; @@ -110,6 +111,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->init_tmout = from->init_tmout; fsrv_to->mem_limit = from->mem_limit; fsrv_to->map_size = from->map_size; + fsrv_to->real_map_size = from->real_map_size; fsrv_to->support_shmem_fuzz = from->support_shmem_fuzz; fsrv_to->out_file = from->out_file; fsrv_to->dev_urandom_fd = from->dev_urandom_fd; @@ -691,15 +693,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } - if (unlikely(tmp_map_size % 64)) { + fsrv->real_map_size = tmp_map_size; + + if (tmp_map_size % 64) { - // should not happen - WARNF("Target reported non-aligned map size of %u", tmp_map_size); tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); } - if (!be_quiet) { ACTF("Target map size: %u", tmp_map_size); } + if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); } if (tmp_map_size > fsrv->map_size) { FATAL( diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 49856a9f..3de67955 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -424,8 +424,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } var_detected = 1; - afl->stage_max = - afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; + afl->stage_max = afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; } else { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 9648d795..e0930234 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -264,6 +264,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "peak_rss_mb : %lu\n" "cpu_affinity : %d\n" "edges_found : %u\n" + "total_edges : %u\n" "var_byte_count : %u\n" "havoc_expansion : %u\n" "testcache_size : %llu\n" @@ -303,10 +304,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #else -1, #endif - t_bytes, afl->var_byte_count, afl->expand_havoc, - afl->q_testcase_cache_size, afl->q_testcase_cache_count, - afl->q_testcase_evictions, afl->use_banner, - afl->unicorn_mode ? "unicorn" : "", + t_bytes, afl->fsrv.real_map_size, afl->var_byte_count, + afl->expand_havoc, afl->q_testcase_cache_size, + afl->q_testcase_cache_count, afl->q_testcase_evictions, + afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", @@ -326,7 +327,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, u32 i = 0; fprintf(f, "virgin_bytes :"); - for (i = 0; i < afl->fsrv.map_size; i++) { + for (i = 0; i < afl->fsrv.real_map_size; i++) { if (afl->virgin_bits[i] != 0xff) { @@ -338,7 +339,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fprintf(f, "\n"); fprintf(f, "var_bytes :"); - for (i = 0; i < afl->fsrv.map_size; i++) { + for (i = 0; i < afl->fsrv.real_map_size; i++) { if (afl->var_bytes[i]) { fprintf(f, " %u", i); } @@ -520,7 +521,7 @@ void show_stats(afl_state_t *afl) { /* Do some bitmap stats. */ t_bytes = count_non_255_bytes(afl, afl->virgin_bits); - t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.map_size; + t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size; if (likely(t_bytes) && unlikely(afl->var_byte_count)) { @@ -781,7 +782,7 @@ void show_stats(afl_state_t *afl) { SAYF(bV bSTOP " now processing : " cRST "%-18s " bSTG bV bSTOP, tmp); sprintf(tmp, "%0.02f%% / %0.02f%%", - ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.map_size, + ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size, t_byte_ratio); SAYF(" map density : %s%-19s" bSTG bV "\n", -- cgit 1.4.1 From ba9323f14cb4ba7c99c4081f19c12b93e112dd65 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 21 Jun 2021 11:53:46 +0200 Subject: typo --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e9a67ac5..c148086c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -125,7 +125,7 @@ static void usage(u8 *argv0, int more_help) { "entering the\n" " pacemaker mode (minutes of no new paths). 0 = " "immediately,\n" - " -1 = immediately and together with normal mutation).\n" + " -1 = immediately and together with normal mutation.\n" " See docs/README.MOpt.md\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" -- cgit 1.4.1 From cbac22d82b90d631bafc4572aa79faa0c568beeb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 22 Jun 2021 17:24:06 +0200 Subject: reverse read the queue n resumes --- docs/Changelog.md | 1 + src/afl-fuzz-init.c | 7 +++++-- src/afl-fuzz-run.c | 3 ++- src/afl-fuzz.c | 7 ++++++- 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 9fd2a1a9..afa5491b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,6 +16,7 @@ sending a mail to . - if the target becomes unavailable check out out/default/error.txt for an indicator why - AFL_CAL_FAST was a dead env, now does the same as AFL_FAST_CAL + - reverse read the queue on resumes (more effective) - afl-cc: - Update to COMPCOV/laf-intel that speeds up the instrumentation process a lot - thanks to Michael Rodler/f0rki for the PR! diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 872e3a32..cc5974d8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -710,7 +710,10 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - for (i = 0; i < (u32)nl_cnt; ++i) { + i = nl_cnt; + do { + + --i; struct stat st; @@ -801,7 +804,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) { */ - } + } while (i > 0); free(nl); /* not tracked */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 3de67955..49856a9f 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -424,7 +424,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } var_detected = 1; - afl->stage_max = afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; + afl->stage_max = + afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c148086c..5f25f728 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1911,7 +1911,12 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl); afl->start_time = get_cur_time(); - if (afl->in_place_resume || afl->afl_env.afl_autoresume) load_stats_file(afl); + if (afl->in_place_resume || afl->afl_env.afl_autoresume) { + + load_stats_file(afl); + + } + write_stats_file(afl, 0, 0, 0, 0); maybe_update_plot_file(afl, 0, 0, 0); save_auto(afl); -- cgit 1.4.1 From ff4d45eed25d9ab80441f813916034bb38cff01e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 22 Jun 2021 22:05:28 +0200 Subject: cmplog fix for qemu and frida --- docs/Changelog.md | 4 +++- instrumentation/afl-compiler-rt.o.c | 17 +++++++++-------- src/afl-forkserver.c | 3 +-- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index afa5491b..4dd68cd2 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -25,10 +25,12 @@ sending a mail to . - support partial linking - We do support llvm versions from 3.8 to 5.0 again - frida_mode: - - fix for cmplog + - several fixes for cmplog - remove need for AFL_FRIDA_PERSISTENT_RETADDR_OFFSET - feature parity of aarch64 with intel now (persistent, cmplog, in-memory testcases, asan) + - qemu_mode: + - performance fix when cmplog was used - afl_analyze: - fix timeout handling - add forkserver support for better performance diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 92deff6a..d4529e2c 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -617,6 +617,7 @@ static void __afl_unmap_shm(void) { #endif __afl_cmp_map = NULL; + __afl_cmp_map_backup = NULL; } @@ -1684,7 +1685,7 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr, void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); @@ -1788,7 +1789,7 @@ void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2) { void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; for (uint64_t i = 0; i < cases[0]; i++) { @@ -1885,7 +1886,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { fprintf(stderr, "\n"); */ - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; // fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2); int l1, l2; if ((l1 = area_is_valid(ptr1, 32)) <= 0 || @@ -1969,7 +1970,7 @@ static u8 *get_llvm_stdstring(u8 *string) { void __cmplog_rtn_gcc_stdstring_cstring(u8 *stdstring, u8 *cstring) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; if (area_is_valid(stdstring, 32) <= 0 || area_is_valid(cstring, 32) <= 0) return; @@ -1979,7 +1980,7 @@ void __cmplog_rtn_gcc_stdstring_cstring(u8 *stdstring, u8 *cstring) { void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0) return; @@ -1990,7 +1991,7 @@ void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; if (area_is_valid(stdstring, 32) <= 0 || area_is_valid(cstring, 32) <= 0) return; @@ -2000,7 +2001,7 @@ void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) { void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { - if (unlikely(!__afl_cmp_map)) return; + if (likely(!__afl_cmp_map)) return; if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0) return; @@ -2034,7 +2035,7 @@ void __afl_coverage_on() { if (likely(__afl_selective_coverage && __afl_selective_coverage_temp)) { __afl_area_ptr = __afl_area_ptr_backup; - __afl_cmp_map = __afl_cmp_map_backup; + if (__afl_cmp_map_backup) { __afl_cmp_map = __afl_cmp_map_backup; } } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 8fb8a75a..5e8fb9b5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -418,8 +418,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, struct rlimit r; - if (!fsrv->cmplog_binary && fsrv->qemu_mode == false && - fsrv->frida_mode == false) { + if (!fsrv->cmplog_binary) { unsetenv(CMPLOG_SHM_ENV_VAR); // we do not want that in non-cmplog fsrv -- cgit 1.4.1 From c6b77d2d05b07040c6599d8c9a142f0ad96ced62 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Jun 2021 10:53:00 +0200 Subject: force disable llvm instrumentation for frida --- src/afl-fuzz-cmplog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index c2e9c80f..c684c4b0 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -33,7 +33,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + if (fsrv->qemu_mode || fsrv->frida_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) { -- cgit 1.4.1 From d64cde8370dc6299b9280feaa575a4266163788f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Jun 2021 13:15:32 +0200 Subject: non-unix compat --- src/afl-fuzz-init.c | 118 +++++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index cc5974d8..5e4f1585 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -710,101 +710,105 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - i = nl_cnt; - do { + if (nl_cnt) { - --i; + i = nl_cnt; + do { - struct stat st; + --i; - u8 dfn[PATH_MAX]; - snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir, - nl[i]->d_name); - u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name); + struct stat st; + u8 dfn[PATH_MAX]; + snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir, + nl[i]->d_name); + u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name); - u8 passed_det = 0; + u8 passed_det = 0; - if (lstat(fn2, &st) || access(fn2, R_OK)) { + if (lstat(fn2, &st) || access(fn2, R_OK)) { - PFATAL("Unable to access '%s'", fn2); + PFATAL("Unable to access '%s'", fn2); - } + } - /* obviously we want to skip "descending" into . and .. directories, - however it is a good idea to skip also directories that start with - a dot */ - if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') { + /* obviously we want to skip "descending" into . and .. directories, + however it is a good idea to skip also directories that start with + a dot */ + if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') { - free(nl[i]); /* not tracked */ - read_testcases(afl, fn2); - ck_free(fn2); - continue; + free(nl[i]); /* not tracked */ + read_testcases(afl, fn2); + ck_free(fn2); + continue; - } + } - free(nl[i]); + free(nl[i]); - if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { + if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { - ck_free(fn2); - continue; + ck_free(fn2); + continue; - } + } - if (st.st_size > MAX_FILE) { + if (st.st_size > MAX_FILE) { - WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2, - stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), - stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE)); + WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", + fn2, + stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), + stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE)); - } + } - /* Check for metadata that indicates that deterministic fuzzing - is complete for this entry. We don't want to repeat deterministic - fuzzing when resuming aborted scans, because it would be pointless - and probably very time-consuming. */ + /* Check for metadata that indicates that deterministic fuzzing + is complete for this entry. We don't want to repeat deterministic + fuzzing when resuming aborted scans, because it would be pointless + and probably very time-consuming. */ - if (!access(dfn, F_OK)) { passed_det = 1; } + if (!access(dfn, F_OK)) { passed_det = 1; } - add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size, - passed_det); + add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size, + passed_det); - if (unlikely(afl->shm.cmplog_mode)) { + if (unlikely(afl->shm.cmplog_mode)) { - if (afl->cmplog_lvl == 1) { + if (afl->cmplog_lvl == 1) { - if (!afl->cmplog_max_filesize || - afl->cmplog_max_filesize < st.st_size) { + if (!afl->cmplog_max_filesize || + afl->cmplog_max_filesize < st.st_size) { - afl->cmplog_max_filesize = st.st_size; + afl->cmplog_max_filesize = st.st_size; - } + } - } else if (afl->cmplog_lvl == 2) { + } else if (afl->cmplog_lvl == 2) { - if (!afl->cmplog_max_filesize || - afl->cmplog_max_filesize > st.st_size) { + if (!afl->cmplog_max_filesize || + afl->cmplog_max_filesize > st.st_size) { - afl->cmplog_max_filesize = st.st_size; + afl->cmplog_max_filesize = st.st_size; + + } } } - } + /* + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { - /* - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, + HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; + afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; - u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, - HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; - afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + } - } + */ - */ + } while (i > 0); - } while (i > 0); + } free(nl); /* not tracked */ -- cgit 1.4.1 From ae50a5067769e2ee4af997c8527de84cf3fdae19 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 23 Jun 2021 23:35:32 +0200 Subject: fix afl-showmap --- src/afl-showmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 646396ad..936d3bc4 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -740,10 +740,9 @@ u32 execute_testcases(u8 *dir) { } - free(nl[i]); - if (!S_ISREG(st.st_mode) || !st.st_size) { + free(nl[i]); ck_free(fn2); continue; @@ -760,6 +759,8 @@ u32 execute_testcases(u8 *dir) { if (!collect_coverage) snprintf(outfile, sizeof(outfile), "%s/%s", out_file, nl[i]->d_name); + free(nl[i]); + if (read_file(fn2)) { if (wait_for_gdb) { -- cgit 1.4.1 From ec781af2c74c17ba3b6ce874a4fc26573872deb8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 24 Jun 2021 09:55:28 +0200 Subject: frida fix --- src/afl-fuzz-cmplog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index c684c4b0..c2e9c80f 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -33,7 +33,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (fsrv->qemu_mode || fsrv->frida_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) { -- cgit 1.4.1 From 7038e56da3952c89a51596180578153918ce6eee Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 27 Jun 2021 10:22:18 +0200 Subject: Select (#995) * favor unfuzzed * fix * reinit table after a new fuzz --- include/afl-fuzz.h | 3 ++- src/afl-fuzz-one.c | 1 + src/afl-fuzz-queue.c | 5 ++++- src/afl-fuzz.c | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 2920f905..2e2c78ef 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -519,7 +519,8 @@ typedef struct afl_state { 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 */ + old_seed_selection, /* use vanilla afl seed selection */ + 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-one.c b/src/afl-fuzz-one.c index 11adebf4..f03249e9 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2862,6 +2862,7 @@ abandon_entry: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; + afl->reinit_table = 1; if (afl->queue_cur->favored) { --afl->pending_favored; } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 811e805c..d2689c94 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -58,7 +58,8 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); } weight *= (log(q->bitmap_size) / avg_bitmap_size); weight *= (1 + (q->tc_ref / avg_top_size)); - if (unlikely(q->favored)) weight *= 5; + if (unlikely(q->favored)) { weight *= 5; } + if (unlikely(!q->was_fuzzed)) { weight *= 2; } return weight; @@ -198,6 +199,8 @@ void create_alias_table(afl_state_t *afl) { while (nS) afl->alias_probability[S[--nS]] = 1; + afl->reinit_table = 0; + /* #ifdef INTROSPECTION u8 fn[PATH_MAX]; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5f25f728..bd9b6691 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2154,7 +2154,8 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->old_seed_selection)) { - if (unlikely(prev_queued_paths < afl->queued_paths)) { + if (unlikely(prev_queued_paths < afl->queued_paths || + afl->reinit_table)) { // we have new queue entries since the last run, recreate alias table prev_queued_paths = afl->queued_paths; -- cgit 1.4.1 From 046a9520f3799f01d5df557f0a577171638e0c64 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 28 Jun 2021 09:14:41 +0200 Subject: Inline cmplog (#996) * inline cmplog check * better switch support * add cmplog-switches-pass.cc --- GNUmakefile.llvm | 5 +- instrumentation/cmplog-instructions-pass.cc | 184 ++----------- instrumentation/cmplog-routines-pass.cc | 67 ++++- instrumentation/cmplog-switches-pass.cc | 414 ++++++++++++++++++++++++++++ src/afl-cc.c | 41 ++- 5 files changed, 528 insertions(+), 183 deletions(-) create mode 100644 instrumentation/cmplog-switches-pass.cc (limited to 'src') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 95140cb0..83eb91a9 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -306,7 +306,7 @@ ifeq "$(TEST_MMAP)" "1" endif PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o -PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so +PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so # If prerequisites are not given, warn, do not build anything, and exit with code 0 ifeq "$(LLVMVER)" "" @@ -433,6 +433,9 @@ endif ./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o +./cmplog-switches-pass.so: instrumentation/cmplog-switches-pass.cc instrumentation/afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o + afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index ad334d3b..0562c5b2 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -104,7 +104,6 @@ Iterator Unique(Iterator first, Iterator last) { bool CmpLogInstructions::hookInstrs(Module &M) { std::vector icomps; - std::vector switches; LLVMContext & C = M.getContext(); Type * VoidTy = Type::getVoidTy(C); @@ -222,6 +221,18 @@ bool CmpLogInstructions::hookInstrs(Module &M) { FunctionCallee cmplogHookInsN = cN; #endif + GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map"); + + if (!AFLCmplogPtr) { + + AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalWeakLinkage, 0, + "__afl_cmp_map"); + + } + + Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0)); + /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { @@ -238,164 +249,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - SwitchInst *switchInst = nullptr; - if ((switchInst = dyn_cast(BB.getTerminator()))) { - - if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); } - - } - - } - - } - - } - - // unique the collected switches - switches.erase(Unique(switches.begin(), switches.end()), switches.end()); - - // Instrument switch values for cmplog - if (switches.size()) { - - if (!be_quiet) - errs() << "Hooking " << switches.size() << " switch instructions\n"; - - for (auto &SI : switches) { - - Value * Val = SI->getCondition(); - unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; - unsigned char do_cast = 0; - - if (!SI->getNumCases() || max_size < 16) { - - // if (!be_quiet) errs() << "skip trivial switch..\n"; - continue; - - } - - if (max_size % 8) { - - max_size = (((max_size / 8) + 1) * 8); - do_cast = 1; - - } - - IRBuilder<> IRB(SI->getParent()); - IRB.SetInsertPoint(SI); - - if (max_size > 128) { - - if (!be_quiet) { - - fprintf(stderr, - "Cannot handle this switch bit size: %u (truncating)\n", - max_size); - - } - - max_size = 128; - do_cast = 1; - - } - - // do we need to cast? - switch (max_size) { - - case 8: - case 16: - case 32: - case 64: - case 128: - cast_size = max_size; - break; - default: - cast_size = 128; - do_cast = 1; - - } - - Value *CompareTo = Val; - - if (do_cast) { - - CompareTo = - IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false); - - } - - for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; - ++i) { - -#if LLVM_VERSION_MAJOR < 5 - ConstantInt *cint = i.getCaseValue(); -#else - ConstantInt *cint = i->getCaseValue(); -#endif - - if (cint) { - - std::vector args; - args.push_back(CompareTo); - - Value *new_param = cint; - - if (do_cast) { - - new_param = - IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false); - - } - - if (new_param) { - - args.push_back(new_param); - ConstantInt *attribute = ConstantInt::get(Int8Ty, 1); - args.push_back(attribute); - if (cast_size != max_size) { - - ConstantInt *bitsize = - ConstantInt::get(Int8Ty, (max_size / 8) - 1); - args.push_back(bitsize); - - } - - switch (cast_size) { - - case 8: - IRB.CreateCall(cmplogHookIns1, args); - break; - case 16: - IRB.CreateCall(cmplogHookIns2, args); - break; - case 32: - IRB.CreateCall(cmplogHookIns4, args); - break; - case 64: - IRB.CreateCall(cmplogHookIns8, args); - break; - case 128: -#ifdef WORD_SIZE_64 - if (max_size == 128) { - - IRB.CreateCall(cmplogHookIns16, args); - - } else { - - IRB.CreateCall(cmplogHookInsN, args); - - } - -#endif - break; - default: - break; - - } - - } - - } - } } @@ -409,8 +262,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) { for (auto &selectcmpInst : icomps) { - IRBuilder<> IRB(selectcmpInst->getParent()); - IRB.SetInsertPoint(selectcmpInst); + IRBuilder<> IRB2(selectcmpInst->getParent()); + IRB2.SetInsertPoint(selectcmpInst); + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = + SplitBlockAndInsertIfThen(is_not_null, selectcmpInst, false); + + IRBuilder<> IRB(ThenTerm); Value *op0 = selectcmpInst->getOperand(0); Value *op1 = selectcmpInst->getOperand(1); @@ -601,7 +461,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (switches.size() || icomps.size()) + if (icomps.size()) return true; else return false; diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index a5992c9a..1e2610f2 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -184,6 +184,18 @@ bool CmpLogRoutines::hookRtns(Module &M) { FunctionCallee cmplogGccStdC = c4; #endif + GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map"); + + if (!AFLCmplogPtr) { + + AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalWeakLinkage, 0, + "__afl_cmp_map"); + + } + + Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0)); + /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { @@ -289,8 +301,15 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); - IRBuilder<> IRB(callInst->getParent()); - IRB.SetInsertPoint(callInst); + IRBuilder<> IRB2(callInst->getParent()); + IRB2.SetInsertPoint(callInst); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); + + IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); @@ -308,8 +327,15 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); - IRBuilder<> IRB(callInst->getParent()); - IRB.SetInsertPoint(callInst); + IRBuilder<> IRB2(callInst->getParent()); + IRB2.SetInsertPoint(callInst); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); + + IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); @@ -327,8 +353,15 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); - IRBuilder<> IRB(callInst->getParent()); - IRB.SetInsertPoint(callInst); + IRBuilder<> IRB2(callInst->getParent()); + IRB2.SetInsertPoint(callInst); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); + + IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); @@ -346,8 +379,15 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); - IRBuilder<> IRB(callInst->getParent()); - IRB.SetInsertPoint(callInst); + IRBuilder<> IRB2(callInst->getParent()); + IRB2.SetInsertPoint(callInst); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); + + IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); @@ -365,8 +405,15 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); - IRBuilder<> IRB(callInst->getParent()); - IRB.SetInsertPoint(callInst); + IRBuilder<> IRB2(callInst->getParent()); + IRB2.SetInsertPoint(callInst); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); + + IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc new file mode 100644 index 00000000..c42d44fe --- /dev/null +++ b/instrumentation/cmplog-switches-pass.cc @@ -0,0 +1,414 @@ +/* + american fuzzy lop++ - LLVM CmpLog instrumentation + -------------------------------------------------- + + Written by Andrea Fioraldi + + Copyright 2015, 2016 Google Inc. All rights reserved. + Copyright 2019-2020 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: + + http://www.apache.org/licenses/LICENSE-2.0 + +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "llvm/Config/llvm-config.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ValueTracking.h" + +#if LLVM_VERSION_MAJOR > 3 || \ + (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) + #include "llvm/IR/Verifier.h" + #include "llvm/IR/DebugInfo.h" +#else + #include "llvm/Analysis/Verifier.h" + #include "llvm/DebugInfo.h" + #define nullptr 0 +#endif + +#include +#include "afl-llvm-common.h" + +using namespace llvm; + +namespace { + +class CmpLogInstructions : public ModulePass { + + public: + static char ID; + CmpLogInstructions() : ModulePass(ID) { + + initInstrumentList(); + + } + + bool runOnModule(Module &M) override; + +#if LLVM_VERSION_MAJOR < 4 + const char *getPassName() const override { + +#else + StringRef getPassName() const override { + +#endif + return "cmplog instructions"; + + } + + private: + bool hookInstrs(Module &M); + +}; + +} // namespace + +char CmpLogInstructions::ID = 0; + +template +Iterator Unique(Iterator first, Iterator last) { + + while (first != last) { + + Iterator next(first); + last = std::remove(++next, last, *first); + first = next; + + } + + return last; + +} + +bool CmpLogInstructions::hookInstrs(Module &M) { + + std::vector switches; + LLVMContext & C = M.getContext(); + + Type * VoidTy = Type::getVoidTy(C); + IntegerType *Int8Ty = IntegerType::getInt8Ty(C); + IntegerType *Int16Ty = IntegerType::getInt16Ty(C); + IntegerType *Int32Ty = IntegerType::getInt32Ty(C); + IntegerType *Int64Ty = IntegerType::getInt64Ty(C); + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c1 = M.getOrInsertFunction("__cmplog_ins_hook1", VoidTy, Int8Ty, Int8Ty, + Int8Ty +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogHookIns1 = cast(c1); +#else + FunctionCallee cmplogHookIns1 = c1; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c2 = M.getOrInsertFunction("__cmplog_ins_hook2", VoidTy, Int16Ty, Int16Ty, + Int8Ty +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogHookIns2 = cast(c2); +#else + FunctionCallee cmplogHookIns2 = c2; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c4 = M.getOrInsertFunction("__cmplog_ins_hook4", VoidTy, Int32Ty, Int32Ty, + Int8Ty +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogHookIns4 = cast(c4); +#else + FunctionCallee cmplogHookIns4 = c4; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c8 = M.getOrInsertFunction("__cmplog_ins_hook8", VoidTy, Int64Ty, Int64Ty, + Int8Ty +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogHookIns8 = cast(c8); +#else + FunctionCallee cmplogHookIns8 = c8; +#endif + + GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map"); + + if (!AFLCmplogPtr) { + + AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalWeakLinkage, 0, + "__afl_cmp_map"); + + } + + Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0)); + + /* iterate over all functions, bbs and instruction and add suitable calls */ + for (auto &F : M) { + + if (!isInInstrumentList(&F)) continue; + + for (auto &BB : F) { + + SwitchInst *switchInst = nullptr; + if ((switchInst = dyn_cast(BB.getTerminator()))) { + + if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); } + + } + + } + + } + + // unique the collected switches + switches.erase(Unique(switches.begin(), switches.end()), switches.end()); + + // Instrument switch values for cmplog + if (switches.size()) { + + if (!be_quiet) + errs() << "Hooking " << switches.size() << " switch instructions\n"; + + for (auto &SI : switches) { + + Value * Val = SI->getCondition(); + unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; + unsigned char do_cast = 0; + + if (!SI->getNumCases() || max_size < 16) { + + // if (!be_quiet) errs() << "skip trivial switch..\n"; + continue; + + } + + if (max_size % 8) { + + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } + + IRBuilder<> IRB2(SI->getParent()); + IRB2.SetInsertPoint(SI); + + LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr); + CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); + auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, SI, false); + + IRBuilder<> IRB(ThenTerm); + + if (max_size > 128) { + + if (!be_quiet) { + + fprintf(stderr, + "Cannot handle this switch bit size: %u (truncating)\n", + max_size); + + } + + max_size = 128; + do_cast = 1; + + } + + // do we need to cast? + switch (max_size) { + + case 8: + case 16: + case 32: + case 64: + case 128: + cast_size = max_size; + break; + default: + cast_size = 128; + do_cast = 1; + + } + + Value *CompareTo = Val; + + if (do_cast) { + + CompareTo = + IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false); + + } + + for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; + ++i) { + +#if LLVM_VERSION_MAJOR < 5 + ConstantInt *cint = i.getCaseValue(); +#else + ConstantInt *cint = i->getCaseValue(); +#endif + + if (cint) { + + std::vector args; + args.push_back(CompareTo); + + Value *new_param = cint; + + if (do_cast) { + + new_param = + IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false); + + } + + if (new_param) { + + args.push_back(new_param); + ConstantInt *attribute = ConstantInt::get(Int8Ty, 1); + args.push_back(attribute); + if (cast_size != max_size) { + + ConstantInt *bitsize = + ConstantInt::get(Int8Ty, (max_size / 8) - 1); + args.push_back(bitsize); + + } + + switch (cast_size) { + + case 8: + IRB.CreateCall(cmplogHookIns1, args); + break; + case 16: + IRB.CreateCall(cmplogHookIns2, args); + break; + case 32: + IRB.CreateCall(cmplogHookIns4, args); + break; + case 64: + IRB.CreateCall(cmplogHookIns8, args); + break; + case 128: +#ifdef WORD_SIZE_64 + if (max_size == 128) { + + IRB.CreateCall(cmplogHookIns16, args); + + } else { + + IRB.CreateCall(cmplogHookInsN, args); + + } + +#endif + break; + default: + break; + + } + + } + + } + + } + + } + + } + + if (switches.size()) + return true; + else + return false; + +} + +bool CmpLogInstructions::runOnModule(Module &M) { + + if (getenv("AFL_QUIET") == NULL) + printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n"); + else + be_quiet = 1; + hookInstrs(M); + verifyModule(M); + + return true; + +} + +static void registerCmpLogInstructionsPass(const PassManagerBuilder &, + legacy::PassManagerBase &PM) { + + auto p = new CmpLogInstructions(); + PM.add(p); + +} + +static RegisterStandardPasses RegisterCmpLogInstructionsPass( + PassManagerBuilder::EP_OptimizerLast, registerCmpLogInstructionsPass); + +static RegisterStandardPasses RegisterCmpLogInstructionsPass0( + PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass); + +#if LLVM_VERSION_MAJOR >= 11 +static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( + PassManagerBuilder::EP_FullLinkTimeOptimizationLast, + registerCmpLogInstructionsPass); +#endif + diff --git a/src/afl-cc.c b/src/afl-cc.c index 980e5d86..1e761c3d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -514,14 +514,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { unsetenv("AFL_LD"); unsetenv("AFL_LD_CALLER"); + if (cmplog_mode) { if (lto_mode && !have_c) { cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path); - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path); + "-Wl,-mllvm=-load=%s/cmplog-switches-pass.so", obj_path); + cc_params[cc_par_cnt++] = alloc_printf( "-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path); @@ -531,13 +531,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-routines-pass.so", obj_path); - - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-instructions-pass.so", obj_path); + alloc_printf("%s/cmplog-switches-pass.so", obj_path); // reuse split switches from laf cc_params[cc_par_cnt++] = "-Xclang"; @@ -643,6 +637,33 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + if (cmplog_mode) { + + if (lto_mode && !have_c) { + + cc_params[cc_par_cnt++] = alloc_printf( + "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path); + cc_params[cc_par_cnt++] = alloc_printf( + "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path); + + } else { + + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = "-load"; + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = + alloc_printf("%s/cmplog-instructions-pass.so", obj_path); + + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = "-load"; + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = + alloc_printf("%s/cmplog-routines-pass.so", obj_path); + + } + + } + // cc_params[cc_par_cnt++] = "-Qunused-arguments"; // in case LLVM is installed not via a package manager or "make install" -- cgit 1.4.1 From 000b16af16bb5cb4e1ea9e4c24c693add6ae4da3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 29 Jun 2021 10:30:37 +0200 Subject: fix linefeed --- src/afl-fuzz-run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 49856a9f..e876beea 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -413,7 +413,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, // note: from_queue seems to only be set during initialization if (afl->afl_env.afl_no_ui || from_queue) { - WARNF("instability detected during calibration\n"); + WARNF("instability detected during calibration"); } else if (afl->debug) { -- cgit 1.4.1 From 6ec295db4e8188df410cf7dcccd1b3de5fbc2048 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 5 Jul 2021 16:14:54 +0200 Subject: more partial linking --- src/afl-cc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 1e761c3d..d35b177d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -789,7 +789,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!strcmp(cur, "-E")) preprocessor_only = 1; if (!strcmp(cur, "-shared")) shared_linking = 1; if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; + if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; + if (!strcmp(cur, "-r")) partial_linking = 1; + if (!strcmp(cur, "--relocatable")) partial_linking = 1; if (!strcmp(cur, "-c")) have_c = 1; if (!strncmp(cur, "-O", 2)) have_o = 1; -- cgit 1.4.1 From ac565bfe51bb16f43680a5fd1b1c29e2d7e13854 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Jul 2021 17:35:05 +0200 Subject: remove unneeded cmdline option --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bd9b6691..60595322 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -158,7 +158,7 @@ static void usage(u8 *argv0, int more_help) { " -F path - sync to a foreign fuzzer queue directory (requires " "-M, can\n" " be specified up to %u times)\n" - " -d - skip deterministic fuzzing in -M mode\n" + // " -d - skip deterministic fuzzing in -M mode\n" " -T text - text banner to show on the screen\n" " -I command - execute this command/script when a new crash is " "found\n" -- cgit 1.4.1 From a09ab9953419cc06ae88e100c934198ed6ee1802 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Jul 2021 19:59:44 +0200 Subject: help output nits --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 60595322..0c7b6e42 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -143,7 +143,7 @@ static void usage(u8 *argv0, int more_help) { " -x dict_file - fuzzer dictionary (see README.md, specify up to 4 " "times)\n\n" - "Testing settings:\n" + "Test settings:\n" " -s seed - use a fixed seed for the RNG\n" " -V seconds - fuzz for a specified time then terminate\n" " -E execs - fuzz for an approx. no. of total executions then " -- cgit 1.4.1 From 4ef12d7215b980399f81cee9cb9a7873cf1d3d78 Mon Sep 17 00:00:00 2001 From: yuan Date: Sat, 10 Jul 2021 14:57:32 +0800 Subject: remove redundant check (#1014) --- src/afl-fuzz-queue.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index d2689c94..b759532c 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -1135,12 +1135,10 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { do_once = 1; // release unneeded memory - u8 *ptr = ck_realloc( + afl->q_testcase_cache = ck_realloc( afl->q_testcase_cache, (afl->q_testcase_max_cache_entries + 1) * sizeof(size_t)); - if (ptr) { afl->q_testcase_cache = (struct queue_entry **)ptr; } - } /* Cache full. We neet to evict one or more to map one. -- cgit 1.4.1 From 37fff16a36c49f47c1a10fcf7c03aa1361a1ae2b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 11 Jul 2021 17:26:31 +0200 Subject: update custom trim --- docs/custom_mutators.md | 4 +--- src/afl-fuzz-mutators.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 129d6676..2c0ca3c5 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -204,9 +204,7 @@ trimmed input. Here's a quick API description: arguments because we already have the initial buffer from `init_trim` and we can memorize the current state in the data variables. This can also save reparsing steps for each iteration. It should return the trimmed input - buffer, where the returned data must not exceed the initial input data in - length. Returning anything that is larger than the original data (passed to - `init_trim`) will result in a fatal abort of AFL++. + buffer. - `post_trim` (optional) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index e27d6fae..6a77dfbc 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -339,7 +339,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, } - while (afl->stage_cur < afl->stage_max) { + while (afl->stage_cur <= afl->stage_max) { u8 *retbuf = NULL; -- cgit 1.4.1 From ec4ad161fc73a457fed1afb7368482df14cdc9a2 Mon Sep 17 00:00:00 2001 From: jhertz Date: Tue, 13 Jul 2021 04:56:55 -0400 Subject: Support AFL_NO_FORKSRV env-var in afl-tmin, afl-showmap, and afl-cmin (#1017) * Support AFL_NO_FORKSRV env-var * format * showmap support * showmap support * help messages now show envar support * formatting * formatting Co-authored-by: Jesse Hertz --- src/afl-showmap.c | 8 +++++++- src/afl-tmin.c | 11 +++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 936d3bc4..480de143 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -853,7 +853,8 @@ static void usage(u8 *argv0) { "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_PRINT_FILENAMES: If set, the filename currently processed will be " "printed to stdout\n" - "AFL_QUIET: do not print extra informational output\n", + "AFL_QUIET: do not print extra informational output\n" + "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n", argv0, MEM_LIMIT, doc_path); exit(1); @@ -1097,6 +1098,11 @@ int main(int argc, char **argv_orig, char **envp) { check_environment_vars(envp); + if (getenv("AFL_NO_FORKSRV")) { /* if set, use the fauxserver */ + fsrv->use_fauxsrv = true; + + } + if (getenv("AFL_DEBUG")) { DEBUGF(""); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 6656712a..2d80abe4 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -877,12 +877,13 @@ static void usage(u8 *argv0) { " the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n" + "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" "ASAN_OPTIONS: custom settings for ASAN\n" " (must contain abort_on_error=1 and symbolize=0)\n" "MSAN_OPTIONS: custom settings for MSAN\n" " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" - "TMPDIR: directory to use for temporary input files\n" - , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); + "TMPDIR: directory to use for temporary input files\n", + argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); exit(1); @@ -1104,6 +1105,12 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); + + if (getenv("AFL_NO_FORKSRV")) { /* if set, use the fauxserver */ + fsrv->use_fauxsrv = true; + + } + setenv("AFL_NO_AUTODICT", "1", 1); /* initialize cmplog_mode */ -- cgit 1.4.1 From 7cec158b0eb9b09160e58b289093cf615e2ca429 Mon Sep 17 00:00:00 2001 From: yuan Date: Wed, 14 Jul 2021 13:53:20 +0800 Subject: fix havoc comments (#1020) --- src/afl-fuzz-one.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index f03249e9..76e64f2a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2102,7 +2102,7 @@ havoc_stage: case 8 ... 9: { - /* Set word to interesting value, randomly choosing endian. */ + /* Set word to interesting value, little endian. */ if (temp_len < 2) { break; } @@ -2119,7 +2119,7 @@ havoc_stage: case 10 ... 11: { - /* Set word to interesting value, randomly choosing endian. */ + /* Set word to interesting value, big endian. */ if (temp_len < 2) { break; } @@ -2136,7 +2136,7 @@ havoc_stage: case 12 ... 13: { - /* Set dword to interesting value, randomly choosing endian. */ + /* Set dword to interesting value, little endian. */ if (temp_len < 4) { break; } @@ -2153,7 +2153,7 @@ havoc_stage: case 14 ... 15: { - /* Set dword to interesting value, randomly choosing endian. */ + /* Set dword to interesting value, big endian. */ if (temp_len < 4) { break; } -- cgit 1.4.1 From 6df597213a4406e290602f14a852f3fae64f818e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 14 Jul 2021 18:20:38 +0200 Subject: fix for -fsanitize=fuzzer on MacOS --- src/afl-cc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index d35b177d..9899f973 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -767,6 +767,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = afllib; +#ifdef __APPLE__ + cc_params[cc_par_cnt++] = "-undefined"; + cc_params[cc_par_cnt++] = "dynamic_lookup"; +#endif + } continue; -- cgit 1.4.1 From cd683ed2530d70c958c78395e7ee67b34c6821df Mon Sep 17 00:00:00 2001 From: Michael Rodler Date: Thu, 15 Jul 2021 11:03:20 +0200 Subject: fixed potential UAF with custom mutator havoc on realloc --- src/afl-fuzz-one.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 76e64f2a..7274f679 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2057,7 +2057,7 @@ havoc_stage: temp_len = new_len; if (out_buf != custom_havoc_buf) { - afl_realloc(AFL_BUF_PARAM(out), temp_len); + out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len); if (unlikely(!afl->out_buf)) { PFATAL("alloc"); } memcpy(out_buf, custom_havoc_buf, temp_len); -- cgit 1.4.1 From 8d873357a3e62a70c61564b4250e1d14d634c218 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 15 Jul 2021 15:53:22 +0200 Subject: fix "fix" --- custom_mutators/grammar_mutator/grammar_mutator | 2 +- qemu_mode/qemuafl | 2 +- src/afl-fuzz-mutators.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator index b3c4fcfa..b79d51a8 160000 --- a/custom_mutators/grammar_mutator/grammar_mutator +++ b/custom_mutators/grammar_mutator/grammar_mutator @@ -1 +1 @@ -Subproject commit b3c4fcfa6ae28918bc410f7747135eafd4fb7263 +Subproject commit b79d51a8daccbd7a693f9b6765c81ead14f28e26 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 21ff3438..d73b0336 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 21ff34383764a8c6f66509b3b8d5282468c721e1 +Subproject commit d73b0336b451fd034e5f469089fb7ee96c80adf2 diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 6a77dfbc..e27d6fae 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -339,7 +339,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, } - while (afl->stage_cur <= afl->stage_max) { + while (afl->stage_cur < afl->stage_max) { u8 *retbuf = NULL; -- cgit 1.4.1 From b5422c1a5251e74deeecc1532d50c651620bb1ca Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 15 Jul 2021 16:05:38 +0200 Subject: fix custom trimming --- src/afl-fuzz-mutators.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index e27d6fae..79a47744 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -393,6 +393,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } + classify_counts(&afl->fsrv); cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); } -- cgit 1.4.1 From 6e704e8a10d0e0033b0f8f03ee2a5bdee06e2c65 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 15 Jul 2021 16:20:55 +0200 Subject: fix aflfast --- src/afl-fuzz-bitmap.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 97f10e6f..0a9242a5 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -551,19 +551,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - if (cksum) - afl->queue_top->exec_cksum = cksum; - else - cksum = afl->queue_top->exec_cksum = - hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - - if (afl->schedule >= FAST && afl->schedule <= RARE) { + /* AFLFast schedule? update the new queue entry */ + if (cksum) { afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; } + /* due to classify counts we have to recalculate the checksum */ + cksum = afl->queue_top->exec_cksum = + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + /* Try to calibrate inline; this also calls update_bitmap_score() when successful. */ -- cgit 1.4.1 From b13b8c7e55836292330ad661e9a0386f7e0d3a91 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 16 Jul 2021 09:39:40 +0200 Subject: make afl-showmap more silent --- README.md | 5 ++++- src/afl-showmap.c | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 4104807c..37fd90e3 100644 --- a/README.md +++ b/README.md @@ -574,6 +574,8 @@ Note that the INPUTFILE argument that the target program would read from has to If the target reads from stdin instead, just omit the `@@` as this is the default. +This step is highly recommended! + #### c) Minimizing all corpus files The shorter the input files that still traverse the same path @@ -589,7 +591,8 @@ for i in *; do done ``` -This step can also be parallelized, e.g. with `parallel` +This step can also be parallelized, e.g. with `parallel`. +Note that this step is rather optional though. #### Done! diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 480de143..5c899e69 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -401,14 +401,23 @@ static u32 read_file(u8 *in_file) { if (fstat(fd, &st) || !st.st_size) { - WARNF("Zero-sized input file '%s'.", in_file); + if (!be_quiet && !quiet_mode) { + + WARNF("Zero-sized input file '%s'.", in_file); + + } } if (st.st_size > MAX_FILE) { - WARNF("Input file '%s' is too large, only reading %u bytes.", in_file, - MAX_FILE); + if (!be_quiet && !quiet_mode) { + + WARNF("Input file '%s' is too large, only reading %u bytes.", in_file, + MAX_FILE); + + } + in_len = MAX_FILE; } else { @@ -748,7 +757,7 @@ u32 execute_testcases(u8 *dir) { } - if (st.st_size > MAX_FILE && !be_quiet) { + if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) { WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2, stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), -- cgit 1.4.1