diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-cc.c | 50 | ||||
-rw-r--r-- | src/afl-common.c | 25 | ||||
-rw-r--r-- | src/afl-forkserver.c | 100 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 9 | ||||
-rw-r--r-- | src/afl-fuzz.c | 66 | ||||
-rw-r--r-- | src/afl-ld-lto.c | 20 |
6 files changed, 200 insertions, 70 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c index 80fc0742..d134f013 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -66,7 +66,6 @@ enum { INSTRUMENT_CLASSIC = 1, INSTRUMENT_AFL = 1, INSTRUMENT_PCGUARD = 2, - INSTRUMENT_INSTRIM = 3, INSTRUMENT_CFG = 3, INSTRUMENT_LTO = 4, INSTRUMENT_LLVMNATIVE = 5, @@ -639,10 +638,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; - if (instrument_mode == INSTRUMENT_CFG) - cc_params[cc_par_cnt++] = - alloc_printf("%s/libLLVMInsTrim.so", obj_path); - else cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); @@ -1252,8 +1247,7 @@ int main(int argc, char **argv, char **envp) { strcasecmp(ptr, "CFG") == 0) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_CFG; + FATAL("InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD (default in afl-cc).\n"); } else if (strcasecmp(ptr, "AFL") == 0 || @@ -1319,10 +1313,7 @@ int main(int argc, char **argv, char **envp) { if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || getenv("INSTRIM_LIB")) { - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_CFG; - else if (instrument_mode != INSTRUMENT_CFG) - FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together"); + FATAL("InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD (default in afl-cc).\n"); } @@ -1409,17 +1400,7 @@ int main(int argc, char **argv, char **envp) { if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { - if (instrument_mode == INSTRUMENT_LTO) { - - instrument_mode = INSTRUMENT_CFG; - lto_mode = 1; - - } else if (!instrument_mode || instrument_mode == INSTRUMENT_CFG) - - instrument_mode = INSTRUMENT_CFG; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + FATAL("InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD (default in afl-cc).\n"); } @@ -1428,7 +1409,7 @@ int main(int argc, char **argv, char **envp) { lto_mode = 1; if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) instrument_mode = INSTRUMENT_LTO; - else if (instrument_mode != INSTRUMENT_CFG) + else FATAL("main instrumentation mode already set with %s", instrument_mode_string[instrument_mode]); @@ -1642,11 +1623,6 @@ int main(int argc, char **argv, char **envp) { " - CALLER\n" " - CTX\n" " - NGRAM-{2-16}\n" - " INSTRIM no yes module yes yes " - " yes\n" - " - NORMAL\n" - " - CALLER\n" - " - NGRAM-{2-16}\n" " [GCC_PLUGIN] gcc plugin: %s%s\n" " CLASSIC DEFAULT no yes no no no " "yes\n" @@ -1697,9 +1673,7 @@ int main(int argc, char **argv, char **envp) { " CTX: CLASSIC + full callee context " "(instrumentation/README.ctx.md)\n" " NGRAM-x: CLASSIC + previous path " - "((instrumentation/README.ngram.md)\n" - " INSTRIM: Dominator tree (for LLVM <= 6.0) " - "(instrumentation/README.instrim.md)\n\n"); + "((instrumentation/README.ngram.md)\n\n"); #undef NATIVE_MSG @@ -1791,19 +1765,15 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" - " CLASSIC, INSTRIM, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, " - "NGRAM-2 ..-16\n" + " CLASSIC, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, NGRAM-2 ..-16\n" " You can also use the old environment variables instead:\n" " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" - " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" - " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed " - "(option to INSTRIM)\n" " AFL_LLVM_CALLER: use single context sensitive coverage (for " "CLASSIC)\n" " AFL_LLVM_CTX: use full context sensitive coverage (for " "CLASSIC)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC & INSTRIM)\n"); + "CLASSIC)\n"); #ifdef AFL_CLANG_FLTO if (have_lto) @@ -1951,11 +1921,7 @@ int main(int argc, char **argv, char **envp) { "(requires LLVM 11 or higher)"); #endif - if (instrument_opt_mode && instrument_mode == INSTRUMENT_CFG && - instrument_opt_mode & INSTRUMENT_OPT_CTX) - FATAL("CFG instrumentation mode supports NGRAM and CALLER, but not CTX."); - else if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) - // we will drop CFG/INSTRIM in the future so do not advertise + if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) FATAL( "CALLER, CTX and NGRAM instrumentation options can only be used with " "the LLVM CLASSIC instrumentation mode."); diff --git a/src/afl-common.c b/src/afl-common.c index 1f9839a2..087aa113 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -282,12 +282,19 @@ u8 *find_binary(u8 *fname) { u8 *find_afl_binary(u8 *own_loc, u8 *fname) { - u8 *afl_path = NULL, *target_path, *own_copy; + u8 *afl_path = NULL, *target_path, *own_copy, *tmp; + int perm = X_OK; + + if ((tmp = strrchr(fname, '.'))) { + + if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; } + + } if ((afl_path = getenv("AFL_PATH"))) { target_path = alloc_printf("%s/%s", afl_path, fname); - if (!access(target_path, X_OK)) { + if (!access(target_path, perm)) { return target_path; @@ -311,7 +318,7 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) { target_path = alloc_printf("%s/%s", own_copy, fname); ck_free(own_copy); - if (!access(target_path, X_OK)) { + if (!access(target_path, perm)) { return target_path; @@ -330,7 +337,7 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) { } target_path = alloc_printf("%s/%s", BIN_PATH, fname); - if (!access(target_path, X_OK)) { + if (!access(target_path, perm)) { return target_path; @@ -340,7 +347,15 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) { } - return find_binary(fname); + if (perm == X_OK) { + + return find_binary(fname); + + } else { + + FATAL("Library '%s' not found", fname); + + } } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c2d552cd..0037d2d5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -42,6 +42,7 @@ #include <errno.h> #include <signal.h> #include <fcntl.h> +#include <limits.h> #include <sys/time.h> #include <sys/wait.h> #include <sys/resource.h> @@ -126,7 +127,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->last_run_timed_out = 0; fsrv_to->init_child_func = from->init_child_func; - // Note: do not copy ->add_extra_func + // Note: do not copy ->add_extra_func or ->persistent_record* list_append(&fsrv_list, fsrv_to); @@ -364,6 +365,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) { ACTF("Spinning up the fork server..."); } +#ifdef AFL_PERSISTENT_RECORD + if (unlikely(fsrv->persistent_record)) { + + fsrv->persistent_record_data = + (u8 **)ck_alloc(fsrv->persistent_record * sizeof(u8 *)); + fsrv->persistent_record_len = + (u32 *)ck_alloc(fsrv->persistent_record * sizeof(u32)); + + if (!fsrv->persistent_record_data || !fsrv->persistent_record_len) { + + FATAL("Unable to allocate memory for persistent replay."); + + } + + } + +#endif + if (fsrv->use_fauxsrv) { /* TODO: Come up with some nice way to initialize this all */ @@ -1032,6 +1051,32 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { +#ifdef AFL_PERSISTENT_RECORD + if (unlikely(fsrv->persistent_record)) { + + fsrv->persistent_record_len[fsrv->persistent_record_idx] = len; + fsrv->persistent_record_data[fsrv->persistent_record_idx] = afl_realloc( + (void **)&fsrv->persistent_record_data[fsrv->persistent_record_idx], + len); + + if (unlikely(!fsrv->persistent_record_data[fsrv->persistent_record_idx])) { + + FATAL("allocating replay memory failed."); + + } + + memcpy(fsrv->persistent_record_data[fsrv->persistent_record_idx], buf, len); + + if (unlikely(++fsrv->persistent_record_idx >= fsrv->persistent_record)) { + + fsrv->persistent_record_idx = 0; + + } + + } + +#endif + if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) { if (unlikely(len > MAX_FILE)) len = MAX_FILE; @@ -1146,6 +1191,26 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } +#ifdef AFL_PERSISTENT_RECORD + // end of persistent loop? + if (unlikely(fsrv->persistent_record && + fsrv->persistent_record_pid != fsrv->child_pid)) { + + fsrv->persistent_record_pid = fsrv->child_pid; + u32 idx, val; + if (unlikely(!fsrv->persistent_record_idx)) + idx = fsrv->persistent_record - 1; + else + idx = fsrv->persistent_record_idx - 1; + val = fsrv->persistent_record_len[idx]; + memset((void *)fsrv->persistent_record_len, 0, + fsrv->persistent_record * sizeof(u32)); + fsrv->persistent_record_len[idx] = val; + + } + +#endif + if (fsrv->child_pid <= 0) { if (*stop_soon_p) { return 0; } @@ -1244,6 +1309,39 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, (fsrv->uses_crash_exitcode && WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) { +#ifdef AFL_PERSISTENT_RECORD + if (unlikely(fsrv->persistent_record)) { + + char fn[PATH_MAX]; + u32 i, writecnt = 0; + for (i = 0; i < fsrv->persistent_record; ++i) { + + u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; + u8 *data = fsrv->persistent_record_data[entry]; + u32 len = fsrv->persistent_record_len[entry]; + if (likely(len && data)) { + + snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u", + fsrv->persistent_record_dir, fsrv->persistent_record_cnt, + writecnt++); + int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd >= 0) { + + ck_write(fd, data, len, fn); + close(fd); + + } + + } + + } + + ++fsrv->persistent_record_cnt; + + } + +#endif + /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */ fsrv->last_kill_signal = WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 0ddf8cf3..f65ff1bb 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_update_freq = 1; afl->stats_avg_exec = 0; afl->skip_deterministic = 1; - afl->cmplog_lvl = 1; + afl->cmplog_lvl = 2; #ifndef NO_SPLICING afl->use_splicing = 1; #endif @@ -292,6 +292,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_autoresume = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_PERSISTENT_RECORD", + + afl_environment_variable_len)) { + + afl->afl_env.afl_persistent_record = + get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_CYCLE_SCHEDULES", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ba8feb53..a7edb924 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -127,7 +127,7 @@ static void usage(u8 *argv0, int more_help) { "it.\n" " if using QEMU, just use -c 0.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" - " 1=small files (default), 2=larger files, 3=all " + " 1=small files, 2=larger files (default), 3=all " "files,\n" " A=arithmetic solving, T=transformational solving.\n\n" "Fuzzing behavior settings:\n" @@ -223,6 +223,9 @@ static void usage(u8 *argv0, int more_help) { "AFL_PATH: path to AFL support binaries\n" "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n" "AFL_QUIET: suppress forkserver status messages\n" +#ifdef AFL_PERSISTENT_RECORD + "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in out/crashes\n" +#endif "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" @@ -254,7 +257,13 @@ static void usage(u8 *argv0, int more_help) { SAYF("Compiled with %s module support, see docs/custom_mutator.md\n", (char *)PYTHON_VERSION); #else - SAYF("Compiled without python module support\n"); + SAYF("Compiled without python module support.\n"); +#endif + +#ifdef AFL_PERSISTENT_RECORD + SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n"); +#else + SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n"); #endif #ifdef USEMMAP @@ -264,27 +273,27 @@ static void usage(u8 *argv0, int more_help) { #endif #ifdef ASAN_BUILD - SAYF("Compiled with ASAN_BUILD\n\n"); + SAYF("Compiled with ASAN_BUILD.\n"); #endif #ifdef NO_SPLICING - SAYF("Compiled with NO_SPLICING\n\n"); + SAYF("Compiled with NO_SPLICING.\n"); #endif #ifdef PROFILING - SAYF("Compiled with PROFILING\n\n"); + SAYF("Compiled with PROFILING.\n"); #endif #ifdef INTROSPECTION - SAYF("Compiled with INTROSPECTION\n\n"); + SAYF("Compiled with INTROSPECTION.\n"); #endif #ifdef _DEBUG - SAYF("Compiled with _DEBUG\n\n"); + SAYF("Compiled with _DEBUG.\n"); #endif #ifdef _AFL_DOCUMENT_MUTATIONS - SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS\n\n"); + SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n"); #endif SAYF("For additional help please consult %s/README.md :)\n\n", doc_path); @@ -1038,6 +1047,30 @@ int main(int argc, char **argv_orig, char **envp) { } + if (unlikely(afl->afl_env.afl_persistent_record)) { + + #ifdef AFL_PERSISTENT_RECORD + + afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record); + + if (afl->fsrv.persistent_record < 2) { + + FATAL( + "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is " + "100 or 1000."); + + } + + #else + + FATAL( + "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in " + "config.h!"); + + #endif + + } + if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " @@ -1532,6 +1565,23 @@ int main(int argc, char **argv_orig, char **envp) { check_binary(afl, argv[optind]); + #ifdef AFL_PERSISTENT_RECORD + if (unlikely(afl->fsrv.persistent_record)) { + + if (!getenv(PERSIST_ENV_VAR)) { + + FATAL( + "Target binary is not compiled in persistent mode, " + "AFL_PERSISTENT_RECORD makes no sense."); + + } + + afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir); + + } + + #endif + if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); } afl->start_time = get_cur_time(); diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 0a978653..8928ddc9 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -73,8 +73,7 @@ static u32 ld_param_cnt = 1; /* Number of params to 'ld' */ so we exploit this property to keep the code "simple". */ static void edit_params(int argc, char **argv) { - u32 i, instrim = 0, gold_pos = 0, gold_present = 0, rt_present = 0, - rt_lto_present = 0, inst_present = 0; + u32 i, gold_pos = 0, gold_present = 0, rt_present = 0, rt_lto_present = 0, inst_present = 0; char *ptr; ld_params = ck_alloc(4096 * sizeof(u8 *)); @@ -186,17 +185,16 @@ static void edit_params(int argc, char **argv) { } - if (getenv("AFL_LLVM_INSTRIM")) - instrim = 1; - else if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) && - (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0)) - instrim = 1; + if (getenv("AFL_LLVM_INSTRIM") || + ((ptr = getenv("AFL_LLVM_INSTRUMENT")) && + (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0))) + FATAL("InsTrim was removed because it is not effective. Use a modern LLVM and PCGUARD (which is the default in afl-cc).\n"); if (debug) DEBUGF( - "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s " + "passthrough=%s, gold_pos=%u, gold_present=%s " "inst_present=%s rt_present=%s rt_lto_present=%s\n", - passthrough ? "true" : "false", instrim, gold_pos, + passthrough ? "true" : "false", gold_pos, gold_present ? "true" : "false", inst_present ? "true" : "false", rt_present ? "true" : "false", rt_lto_present ? "true" : "false"); @@ -230,10 +228,6 @@ static void edit_params(int argc, char **argv) { if (!inst_present) { - if (instrim) - ld_params[ld_param_cnt++] = - alloc_printf("-mllvm=-load=%s/afl-llvm-lto-instrim.so", afl_path); - else ld_params[ld_param_cnt++] = alloc_printf( "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path); |