From d4c01c057bb8e6741e6652567f168e9bdd00f9cd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 4 Feb 2022 12:09:07 +0100 Subject: test support for forced persistent mode --- src/afl-fuzz-init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 5449460e..9e74079b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2818,7 +2818,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; - + afl->fsrv.persistent_mode = 1; afl->shmem_testcase_mode = 1; } else if (getenv("AFL_PERSISTENT")) { @@ -2830,7 +2830,6 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF("FRIDA Persistent mode configuration options detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; - afl->shmem_testcase_mode = 1; } -- cgit 1.4.1 From 04d693721bbfe181a8d1c6361d46baa74388e6f2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 5 Feb 2022 07:25:12 +0100 Subject: force persistent and deferred also for tools --- src/afl-common.c | 6 ++++-- src/afl-fuzz-init.c | 1 + src/afl-fuzz.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/src/afl-common.c b/src/afl-common.c index 7ba3bb74..e684302a 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -63,7 +63,8 @@ u32 check_binary_signatures(u8 *fn) { if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1) || + getenv(PERSIST_ENV_VAR)) { if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); } setenv(PERSIST_ENV_VAR, "1", 1); @@ -90,7 +91,8 @@ u32 check_binary_signatures(u8 *fn) { } - if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1) || + getenv(DEFER_ENV_VAR)) { if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); } setenv(DEFER_ENV_VAR, "1", 1); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9e74079b..eb73b120 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2830,6 +2830,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF("FRIDA Persistent mode configuration options detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; + afl->fsrv.persistent_mode = 1; afl->shmem_testcase_mode = 1; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d8610df9..7a74fc7e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1912,7 +1912,7 @@ int main(int argc, char **argv_orig, char **envp) { WARNF( "Deferred forkserver mode environment variable detected, forcing " - "defered forkserver!"); + "deferred forkserver!"); afl->deferred_mode = 1; } -- cgit 1.4.1 From d5b9cd4b73253c2fbbc7da88015ae0eac303eb32 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 5 Feb 2022 08:27:17 +0100 Subject: add afl-fuzz -y fuzz length support --- docs/Changelog.md | 3 +++ include/afl-fuzz.h | 9 ++++++--- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-init.c | 5 ++--- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-run.c | 35 +++++++++++++++++++++++++++++------ src/afl-fuzz-state.c | 2 ++ src/afl-fuzz.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 9 files changed, 85 insertions(+), 17 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 94e854e4..153369b7 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,9 @@ sending a mail to . ### Version ++4.01a (dev) - fix */build_...sh scripts to work outside of git - new custom_mutator: libafl with token fuzzing :) + - afl-fuzz: + - new commandline option -y to set min and max length of generated + fuzz inputs - frida_mode: - update to new frida release, handles now c++ throw/catch diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e225211f..3712fc4f 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -726,6 +726,9 @@ typedef struct afl_state { /* queue entries ready for splicing count (len > 4) */ u32 ready_for_splicing_count; + /* min/max length for generated fuzzing inputs */ + u32 min_length, max_length; + /* This is the user specified maximum size to use for the testcase cache */ u64 q_testcase_max_cache_size; @@ -1090,12 +1093,12 @@ int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen); /* Run */ -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 *); +u32 write_to_testcase(afl_state_t *, void *, u32, u32); +u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); u8 trim_case(afl_state_t *, struct queue_entry *, u8 *); u8 common_fuzz_stuff(afl_state_t *, u8 *, u32); +fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); /* Fuzz one */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 8d044959..b963caf8 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -633,7 +633,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (afl->fsrv.exec_tmout < afl->hang_tmout) { u8 new_fault; - write_to_testcase(afl, mem, len); + len = write_to_testcase(afl, mem, len, 0); new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout); classify_counts(&afl->fsrv); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index ce8f1a83..1a8052a0 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -49,7 +49,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - write_to_testcase(afl, out_buf, len); + len = write_to_testcase(afl, out_buf, len, 0); fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index eb73b120..45f28d4b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -617,11 +617,10 @@ void read_foreign_testcases(afl_state_t *afl, int first) { } - write_to_testcase(afl, mem, st.st_size); + u32 len = write_to_testcase(afl, mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); afl->syncing_party = foreign_name; - afl->queued_imported += - save_if_interesting(afl, mem, st.st_size, fault); + afl->queued_imported += save_if_interesting(afl, mem, len, fault); afl->syncing_party = 0; munmap(mem, st.st_size); close(fd); diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 51a43dbd..e78e2dc4 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -428,7 +428,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (likely(retlen)) { - write_to_testcase(afl, retbuf, retlen); + retlen = write_to_testcase(afl, retbuf, retlen, 0); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index eaa82b19..5da0e583 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -73,8 +73,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -void __attribute__((hot)) -write_to_testcase(afl_state_t *afl, void *mem, u32 len) { +u32 __attribute__((hot)) +write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) { #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; @@ -120,16 +120,39 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { }); + if (unlikely(new_size < afl->min_length && !fix)) { + + new_size = afl->min_length; + + } else if (unlikely(new_size > afl->max_length)) { + + new_size = afl->max_length; + + } + /* everything as planned. use the potentially new data. */ afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); + len = new_size; } else { + if (unlikely(len < afl->min_length && !fix)) { + + len = afl->min_length; + + } else if (unlikely(len > afl->max_length)) { + + len = afl->max_length; + + } + /* boring uncustom. */ afl_fsrv_write_to_testcase(&afl->fsrv, mem, len); } + return len; + } /* The same, but with an adjustable gap. Used for trimming. */ @@ -346,7 +369,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, /* we need a dummy run if this is LTO + cmplog */ if (unlikely(afl->shm.cmplog_mode)) { - write_to_testcase(afl, use_mem, q->len); + (void)write_to_testcase(afl, use_mem, q->len, 1); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); @@ -389,7 +412,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u64 cksum; - write_to_testcase(afl, use_mem, q->len); + (void)write_to_testcase(afl, use_mem, q->len, 1); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); @@ -700,7 +723,7 @@ void sync_fuzzers(afl_state_t *afl) { /* See what happens. We rely on save_if_interesting() to catch major errors and save the test case. */ - write_to_testcase(afl, mem, st.st_size); + (void)write_to_testcase(afl, mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); @@ -943,7 +966,7 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - write_to_testcase(afl, out_buf, len); + len = write_to_testcase(afl, out_buf, len, 0); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 69ffa8cf..24bd28dd 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,6 +102,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_avg_exec = 0; afl->skip_deterministic = 1; afl->cmplog_lvl = 2; + afl->min_length = 1; + afl->max_length = MAX_FILE; #ifndef NO_SPLICING afl->use_splicing = 1; #endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7a74fc7e..6ca9be33 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -155,6 +155,9 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" + " -y [min-]max - set minimum and maximum length of generated fuzzing " + "input.\n" + " default: 1-%lu\n" " -D - enable deterministic fuzzing (once per queue entry)\n" " -L minutes - use MOpt(imize) mode and set the time limit for " "entering the\n" @@ -204,7 +207,7 @@ static void usage(u8 *argv0, int more_help) { "(0-...)\n" " -e ext - file extension for the fuzz test input file (if " "needed)\n\n", - argv0, EXEC_TIMEOUT, MEM_LIMIT, FOREIGN_SYNCS_MAX); + argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); if (more_help > 1) { @@ -529,11 +532,36 @@ int main(int argc, char **argv_orig, char **envp) { while ((opt = getopt( argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOXYo:p:RQs:S:t:T:UV:Wx:Z")) > + "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:Yy:Z")) > 0) { switch (opt) { + case 'y': { + + u8 *sep; + if (!(sep = strchr(optarg, '-')) && !(sep = strchr(optarg, ':'))) { + + afl->max_length = atoi(optarg); + + } else { + + afl->min_length = atoi(optarg); + afl->max_length = atoi(sep + 1); + + } + + if (afl->min_length < 1 || afl->max_length > MAX_FILE || + afl->min_length > afl->max_length) { + + FATAL("Illegal min/max length values: %s", optarg); + + } + + break; + + } + case 'Z': afl->old_seed_selection = 1; break; @@ -1622,6 +1650,16 @@ int main(int argc, char **argv_orig, char **envp) { } + OKF("Generating fuzz data with a a length of min=%u max=%u", afl->min_length, + afl->max_length); + u32 min_alloc = MAX(64U, afl->min_length); + afl_realloc(AFL_BUF_PARAM(in_scratch), min_alloc); + afl_realloc(AFL_BUF_PARAM(in), min_alloc); + afl_realloc(AFL_BUF_PARAM(out_scratch), min_alloc); + afl_realloc(AFL_BUF_PARAM(out), min_alloc); + afl_realloc(AFL_BUF_PARAM(eff), min_alloc); + afl_realloc(AFL_BUF_PARAM(ex), min_alloc); + afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; #ifdef __linux__ -- cgit 1.4.1 From cf853fb2494912a1c4b531ffcf302843266639b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 8 Feb 2022 20:15:48 +0100 Subject: reintroduce AFL_PERSISTENT and AFL_DEFER_FORKSRV --- docs/Changelog.md | 3 +++ docs/env_variables.md | 10 +++++++--- frida_mode/src/entry.c | 1 + src/afl-common.c | 22 ++++++++-------------- src/afl-fuzz-init.c | 10 ++++++++-- src/afl-fuzz-state.c | 8 ++++---- src/afl-fuzz.c | 24 ++---------------------- 7 files changed, 33 insertions(+), 45 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index bdb2dda3..142b85b3 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,9 @@ sending a mail to . - afl-fuzz: - new commandline options -g/G to set min/max length of generated fuzz inputs + - reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow + persistent mode and manual forkserver support if these are not + in the target binary (e.g. are in a shared library) - frida_mode: - update to new frida release, handles now c++ throw/catch diff --git a/docs/env_variables.md b/docs/env_variables.md index f7ad4ff9..06c08f31 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -532,9 +532,13 @@ checks or alter some of the more exotic semantics of the tool: - Setting `AFL_TRY_AFFINITY` tries to attempt binding to a specific CPU core on Linux systems, but will not terminate if that fails. - - Outdated environment variables that are not supported anymore: - - `AFL_DEFER_FORKSRV` - - `AFL_PERSISTENT` + - The following environment variables are only needed if you implemented + your own forkserver or persistent mode, or if __AFL_LOOP or __AFL_INIT + are in a shared library and not the main binary: + - `AFL_DEFER_FORKSRV` enforces a deferred forkserver even if none was + detected in the target binary + - `AFL_PERSISTENT` enforces persistent mode even if none was detected + in the target binary ## 5) Settings for afl-qemu-trace diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index 5d9bcaaf..05af7ebb 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -84,6 +84,7 @@ void entry_start(void) { stalker_trust(); } + if (entry_point == 0) { entry_launch(); } } diff --git a/src/afl-common.c b/src/afl-common.c index e684302a..7c074acc 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -63,8 +63,7 @@ u32 check_binary_signatures(u8 *fn) { if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1) || - getenv(PERSIST_ENV_VAR)) { + if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); } setenv(PERSIST_ENV_VAR, "1", 1); @@ -72,11 +71,9 @@ u32 check_binary_signatures(u8 *fn) { } else if (getenv("AFL_PERSISTENT")) { - if (!be_quiet) { - - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); - - } + if (!be_quiet) { OKF(cPIN "Persistent mode enforced."); } + setenv(PERSIST_ENV_VAR, "1", 1); + ret = 1; } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { @@ -91,8 +88,7 @@ u32 check_binary_signatures(u8 *fn) { } - if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1) || - getenv(DEFER_ENV_VAR)) { + if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); } setenv(DEFER_ENV_VAR, "1", 1); @@ -100,11 +96,9 @@ u32 check_binary_signatures(u8 *fn) { } else if (getenv("AFL_DEFER_FORKSRV")) { - if (!be_quiet) { - - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); - - } + if (!be_quiet) { OKF(cPIN "Deferred forkserver enforced."); } + setenv(DEFER_ENV_VAR, "1", 1); + ret += 2; } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 45f28d4b..05a654c8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2822,7 +2822,11 @@ void check_binary(afl_state_t *afl, u8 *fname) { } else if (getenv("AFL_PERSISTENT")) { - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + OKF(cPIN "Persistent mode enforced."); + setenv(PERSIST_ENV_VAR, "1", 1); + afl->persistent_mode = 1; + afl->fsrv.persistent_mode = 1; + afl->shmem_testcase_mode = 1; } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { @@ -2843,7 +2847,9 @@ void check_binary(afl_state_t *afl, u8 *fname) { } else if (getenv("AFL_DEFER_FORKSRV")) { - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); + OKF(cPIN "Deferred forkserver enforced."); + setenv(DEFER_ENV_VAR, "1", 1); + afl->deferred_mode = 1; } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 115e62de..129e4c8b 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -486,15 +486,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl_environment_variable_len)) { - afl->min_length = atoi( - (u8 *)get_afl_env(afl_environment_variables[i])); + afl->min_length = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); } else if (!strncmp(env, "AFL_INPUT_LEN_MAX", afl_environment_variable_len)) { - afl->max_length = atoi( - (u8 *)get_afl_env(afl_environment_variables[i])); + afl->max_length = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7e3b3c94..c923cc9d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -294,8 +294,8 @@ static void usage(u8 *argv0, int more_help) { " 'signalfx' and 'influxdb'\n" "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" - //"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n" - //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" + "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" + "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so\n" "\n" ); @@ -1920,26 +1920,6 @@ int main(int argc, char **argv_orig, char **envp) { check_binary(afl, argv[optind]); - if (getenv(PERSIST_ENV_VAR) && !afl->persistent_mode) { - - WARNF( - "Persistent mode environment variable detected, forcing persistent " - "mode!"); - afl->persistent_mode = 1; - afl->fsrv.persistent_mode = 1; - afl->shmem_testcase_mode = 1; - - } - - if (getenv(DEFER_ENV_VAR) && !afl->deferred_mode) { - - WARNF( - "Deferred forkserver mode environment variable detected, forcing " - "deferred forkserver!"); - afl->deferred_mode = 1; - - } - #ifdef AFL_PERSISTENT_RECORD if (unlikely(afl->fsrv.persistent_record)) { -- cgit 1.4.1