aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2023-06-06 17:36:04 +0300
committerGitHub <noreply@github.com>2023-06-06 17:36:04 +0300
commit4deb45f3b3e9f53880596d21432069b05553bcb3 (patch)
tree2dcf56dd0b540a4387f050c32ba5f50e7f42d666 /src
parent8de7f6131d48e27d53e894b65bd11e0dc3817639 (diff)
parent2f6b54e4410738d92c4981a700541f15e4fbe938 (diff)
downloadafl++-4deb45f3b3e9f53880596d21432069b05553bcb3.tar.gz
Merge pull request #1759 from AFLplusplus/dev
Dev
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c64
-rw-r--r--src/afl-cc.c644
-rw-r--r--src/afl-common.c51
-rw-r--r--src/afl-forkserver.c273
-rw-r--r--src/afl-fuzz-bitmap.c10
-rw-r--r--src/afl-fuzz-init.c71
-rw-r--r--src/afl-fuzz-mutators.c16
-rw-r--r--src/afl-fuzz-one.c26
-rw-r--r--src/afl-fuzz-python.c62
-rw-r--r--src/afl-fuzz-queue.c109
-rw-r--r--src/afl-fuzz-redqueen.c40
-rw-r--r--src/afl-fuzz-run.c32
-rw-r--r--src/afl-fuzz-state.c17
-rw-r--r--src/afl-fuzz-stats.c46
-rw-r--r--src/afl-fuzz.c262
-rw-r--r--src/afl-ld-lto.c4
-rw-r--r--src/afl-showmap.c422
-rw-r--r--src/afl-tmin.c59
18 files changed, 1652 insertions, 556 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 548956d8..5b122741 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -121,9 +121,9 @@ static void kill_child() {
}
-static void classify_counts(u8 *mem) {
+static void classify_counts(u8 *mem, u32 mem_size) {
- u32 i = map_size;
+ u32 i = mem_size;
if (edges_only) {
@@ -222,7 +222,7 @@ static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
}
- classify_counts(fsrv.trace_bits);
+ classify_counts(fsrv.trace_bits, fsrv.map_size);
total_execs++;
if (stop_soon) {
@@ -768,6 +768,7 @@ static void usage(u8 *argv0) {
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
"mode)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -814,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init(&fsrv);
- while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXYh")) > 0) {
switch (opt) {
@@ -966,6 +967,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv.nyx_mode = 1;
+ fsrv.nyx_parent = true;
+ fsrv.nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'h':
usage(argv[0]);
return -1;
@@ -997,7 +1015,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(argv);
+#ifdef __linux__
+ if (!fsrv.nyx_mode) {
+
+ fsrv.target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv.target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv.target_path = find_binary(argv[optind]);
+#endif
+
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
signal(SIGALRM, kill_child);
@@ -1020,6 +1052,26 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv.nyx_mode) {
+
+ fsrv.nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv.nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv.nyx_use_tmp_workdir = true;
+ fsrv.nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1045,7 +1097,11 @@ int main(int argc, char **argv_orig, char **envp) {
&fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
read_initial_file();
+#ifdef __linux__
+ if (!fsrv.nyx_mode) { (void)check_binary_signatures(fsrv.target_path); }
+#else
(void)check_binary_signatures(fsrv.target_path);
+#endif
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
mem_limit, exec_tmout, edges_only ? ", edges only" : "");
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 7b059d40..9e56828c 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -31,6 +31,8 @@
#include <strings.h>
#include <limits.h>
#include <assert.h>
+#include <ctype.h>
+#include <sys/stat.h>
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@@ -76,6 +78,7 @@ enum {
INSTRUMENT_OPT_NGRAM = 16,
INSTRUMENT_OPT_CALLER = 32,
INSTRUMENT_OPT_CTX_K = 64,
+ INSTRUMENT_OPT_CODECOV = 128,
};
@@ -375,15 +378,308 @@ void parse_fsanitize(char *string) {
}
+static 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, partial_linking = 0,
+ non_dash = 0;
+
+static void process_params(u32 argc, char **argv) {
+
+ if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); }
+
+ if (lto_mode && argc > 1) {
+
+ u32 idx;
+ for (idx = 1; idx < argc; idx++) {
+
+ if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
+
+ }
+
+ }
+
+ // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
+
+ /* Process the argument list. */
+
+ u8 skip_next = 0;
+ while (--argc) {
+
+ u8 *cur = *(++argv);
+
+ if (skip_next) {
+
+ skip_next = 0;
+ continue;
+
+ }
+
+ if (cur[0] != '-') { non_dash = 1; }
+ if (!strncmp(cur, "--afl", 5)) continue;
+
+ if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
+
+ FATAL(
+ "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
+ "use afl-clang-fast!");
+
+ }
+
+ if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
+ if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
+ if (!strncmp(cur, "-fno-unroll", 11)) continue;
+ if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
+ if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
+ !strcmp(cur, "--no-undefined")) {
+
+ continue;
+
+ }
+
+ if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
+
+ if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
+
+ u8 *param = *(argv + 1);
+ if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
+
+ skip_next = 1;
+ continue;
+
+ }
+
+ }
+
+ if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
+ !strncmp(cur, "-stdlib=", 8)) {
+
+ if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+ continue;
+
+ }
+
+ if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
+
+ have_instr_list = 1;
+
+ }
+
+ if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
+ strchr(cur, ',')) {
+
+ parse_fsanitize(cur);
+ if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
+
+ } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
+
+ strlen("-fsanitize=fuzzer-")) ||
+ !strncmp(cur, "-fsanitize-coverage",
+ strlen("-fsanitize-coverage"))) &&
+ (strncmp(cur, "sanitize-coverage-allow",
+ strlen("sanitize-coverage-allow")) &&
+ strncmp(cur, "sanitize-coverage-deny",
+ strlen("sanitize-coverage-deny")) &&
+ instrument_mode != INSTRUMENT_LLVMNATIVE)) {
+
+ if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+ continue;
+
+ }
+
+ if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
+
+ u8 *afllib = find_object("libAFLDriver.a", argv[0]);
+
+ if (!be_quiet) {
+
+ OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
+
+ }
+
+ if (!afllib) {
+
+ if (!be_quiet) {
+
+ WARNF(
+ "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
+ "the flags - this will fail!");
+
+ }
+
+ } else {
+
+ cc_params[cc_par_cnt++] = afllib;
+
+#ifdef __APPLE__
+ cc_params[cc_par_cnt++] = "-undefined";
+ cc_params[cc_par_cnt++] = "dynamic_lookup";
+#endif
+
+ }
+
+ if (need_aflpplib) {
+
+ need_aflpplib = 0;
+
+ } else {
+
+ continue;
+
+ }
+
+ }
+
+ if (!strcmp(cur, "-m32")) bit_mode = 32;
+ if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
+ if (!strcmp(cur, "-m64")) bit_mode = 64;
+
+ if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
+ asan_set = 1;
+
+ if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
+
+ if (!strcmp(cur, "-x")) x_set = 1;
+ if (!strcmp(cur, "-E")) preprocessor_only = 1;
+ if (!strcmp(cur, "-shared")) shared_linking = 1;
+ if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
+ if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 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;
+ if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
+
+ if (*cur == '@') {
+
+ // response file support.
+ // we have two choices - move everything to the command line or
+ // rewrite the response files to temporary files and delete them
+ // afterwards. We choose the first for easiness.
+ // We do *not* support quotes in the rsp files to cope with spaces in
+ // filenames etc! If you need that then send a patch!
+ u8 *filename = cur + 1;
+ if (debug) { DEBUGF("response file=%s\n", filename); }
+ FILE *f = fopen(filename, "r");
+ struct stat st;
+
+ // Check not found or empty? let the compiler complain if so.
+ if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) {
+
+ cc_params[cc_par_cnt++] = cur;
+ continue;
+
+ }
+
+ u8 *tmpbuf = malloc(st.st_size + 2), *ptr;
+ char **args = malloc(sizeof(char *) * (st.st_size >> 1));
+ int count = 1, cont = 0, cont_act = 0;
+
+ while (fgets(tmpbuf, st.st_size + 1, f)) {
+
+ ptr = tmpbuf;
+ // fprintf(stderr, "1: %s\n", ptr);
+ // no leading whitespace
+ while (isspace(*ptr)) {
+
+ ++ptr;
+ cont_act = 0;
+
+ }
+
+ // no comments, no empty lines
+ if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; }
+ // remove LF
+ if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; }
+ // remove CR
+ if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; }
+ // handle \ at end of line
+ if (*ptr && ptr[strlen(ptr) - 1] == '\\') {
+
+ cont = 1;
+ ptr[strlen(ptr) - 1] = 0;
+
+ }
+
+ // fprintf(stderr, "2: %s\n", ptr);
+
+ // remove whitespace at end
+ while (*ptr && isspace(ptr[strlen(ptr) - 1])) {
+
+ ptr[strlen(ptr) - 1] = 0;
+ cont = 0;
+
+ }
+
+ // fprintf(stderr, "3: %s\n", ptr);
+ if (*ptr) {
+
+ do {
+
+ u8 *value = ptr;
+ while (*ptr && !isspace(*ptr)) {
+
+ ++ptr;
+
+ }
+
+ while (*ptr && isspace(*ptr)) {
+
+ *ptr++ = 0;
+
+ }
+
+ if (cont_act) {
+
+ u32 len = strlen(args[count - 1]) + strlen(value) + 1;
+ u8 *tmp = malloc(len);
+ snprintf(tmp, len, "%s%s", args[count - 1], value);
+ free(args[count - 1]);
+ args[count - 1] = tmp;
+ cont_act = 0;
+
+ } else {
+
+ args[count++] = strdup(value);
+
+ }
+
+ } while (*ptr);
+
+ }
+
+ if (cont) {
+
+ cont_act = 1;
+ cont = 0;
+
+ }
+
+ }
+
+ if (count) { process_params(count, args); }
+
+ // we cannot free args[]
+ free(tmpbuf);
+
+ continue;
+
+ }
+
+ cc_params[cc_par_cnt++] = cur;
+
+ }
+
+}
+
/* Copy argv to cc_params, making the necessary edits. */
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, partial_linking = 0;
-
- cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
+ cc_params = ck_alloc(1024 * sizeof(u8 *));
if (lto_mode) {
@@ -641,10 +937,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- //#if LLVM_MAJOR >= 13
- // // Use the old pass manager in LLVM 14 which the afl++ passes still
- // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
- //#endif
+ // #if LLVM_MAJOR >= 13
+ // // Use the old pass manager in LLVM 14 which the AFL++ passes still
+ // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
+ // #endif
if (lto_mode && !have_c) {
@@ -701,7 +997,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
-#if LLVM_MAJOR >= 11
+#if LLVM_MAJOR >= 13
#if defined __ANDROID__ || ANDROID
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -718,7 +1014,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else {
- #if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR >= 13 /* use new pass manager */
#if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
#endif
@@ -739,21 +1035,35 @@ static void edit_params(u32 argc, char **argv, char **envp) {
#if LLVM_MAJOR >= 4
if (!be_quiet)
SAYF(
- "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for "
+ "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for "
"enhanced version.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
#else
- FATAL("pcguard instrumentation requires llvm 4.0.1+");
+ FATAL("pcguard instrumentation requires LLVM 4.0.1+");
#endif
#endif
} else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
#if LLVM_MAJOR >= 4
- cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+ if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
+
+ #if LLVM_MAJOR >= 6
+ cc_params[cc_par_cnt++] =
+ "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
+ #else
+ FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+");
+ #endif
+
+ } else {
+
+ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+
+ }
+
#else
- FATAL("pcguard instrumentation requires llvm 4.0.1+");
+ FATAL("pcguard instrumentation requires LLVM 4.0.1+");
#endif
} else {
@@ -816,159 +1126,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC";
-
}
}
- /* Detect stray -v calls from ./configure scripts. */
-
- u8 skip_next = 0, non_dash = 0;
- while (--argc) {
-
- u8 *cur = *(++argv);
-
- if (skip_next) {
-
- skip_next = 0;
- continue;
-
- }
-
- if (cur[0] != '-') { non_dash = 1; }
- if (!strncmp(cur, "--afl", 5)) continue;
- if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
- if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
- if (!strncmp(cur, "-fno-unroll", 11)) continue;
- if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
- if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
- !strcmp(cur, "--no-undefined")) {
-
- continue;
-
- }
-
- if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
-
- if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
-
- u8 *param = *(argv + 1);
- if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
-
- skip_next = 1;
- continue;
-
- }
-
- }
-
- if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
- !strncmp(cur, "-stdlib=", 8)) {
-
- if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
- continue;
-
- }
-
- if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
-
- have_instr_list = 1;
-
- }
-
- if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
- strchr(cur, ',')) {
-
- parse_fsanitize(cur);
- if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
-
- } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
-
- strlen("-fsanitize=fuzzer-")) ||
- !strncmp(cur, "-fsanitize-coverage",
- strlen("-fsanitize-coverage"))) &&
- (strncmp(cur, "sanitize-coverage-allow",
- strlen("sanitize-coverage-allow")) &&
- strncmp(cur, "sanitize-coverage-deny",
- strlen("sanitize-coverage-deny")) &&
- instrument_mode != INSTRUMENT_LLVMNATIVE)) {
-
- if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
- continue;
+ /* Inspect the command line parameters. */
- }
-
- if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
+ process_params(argc, argv);
- u8 *afllib = find_object("libAFLDriver.a", argv[0]);
-
- if (!be_quiet) {
-
- OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
-
- }
-
- if (!afllib) {
-
- if (!be_quiet) {
-
- WARNF(
- "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
- "the flags - this will fail!");
-
- }
-
- } else {
-
- cc_params[cc_par_cnt++] = afllib;
-
-#ifdef __APPLE__
- cc_params[cc_par_cnt++] = "-undefined";
- cc_params[cc_par_cnt++] = "dynamic_lookup";
-#endif
-
- }
-
- if (need_aflpplib) {
-
- need_aflpplib = 0;
-
- } else {
-
- continue;
-
- }
-
- }
-
- if (!strcmp(cur, "-m32")) bit_mode = 32;
- if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
- if (!strcmp(cur, "-m64")) bit_mode = 64;
-
- if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
- asan_set = 1;
-
- if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
-
- if (!strcmp(cur, "-x")) x_set = 1;
- if (!strcmp(cur, "-E")) preprocessor_only = 1;
- if (!strcmp(cur, "-shared")) shared_linking = 1;
- if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
- if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 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;
- if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
-
- cc_params[cc_par_cnt++] = cur;
-
- }
+ if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; }
// in case LLVM is installed not via a package manager or "make install"
// e.g. compiled download or compiled from github then its ./lib directory
@@ -1101,37 +1267,45 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!have_c) cc_params[cc_par_cnt++] = "-lrt";
#endif
- cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
- /* When the user tries to use persistent or deferred forkserver modes by
- appending a single line to the program, we want to reliably inject a
- signature into the binary (to be picked up by afl-fuzz) and we want
- to call a function from the runtime .o file. This is unnecessarily
- painful for three reasons:
+ /* As documented in instrumentation/README.persistent_mode.md, deferred
+ forkserver initialization and persistent mode are not available in afl-gcc
+ and afl-clang. */
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
- 1) We need to convince the compiler not to optimize out the signature.
- This is done with __attribute__((used)).
+ cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
- 2) We need to convince the linker, when called with -Wl,--gc-sections,
- not to do the same. This is done by forcing an assignment to a
- 'volatile' pointer.
+ /* When the user tries to use persistent or deferred forkserver modes by
+ appending a single line to the program, we want to reliably inject a
+ signature into the binary (to be picked up by afl-fuzz) and we want
+ to call a function from the runtime .o file. This is unnecessarily
+ painful for three reasons:
- 3) We need to declare __afl_persistent_loop() in the global namespace,
- but doing this within a method in a class is hard - :: and extern "C"
- are forbidden and __attribute__((alias(...))) doesn't work. Hence the
- __asm__ aliasing trick.
+ 1) We need to convince the compiler not to optimize out the signature.
+ This is done with __attribute__((used)).
- */
+ 2) We need to convince the linker, when called with -Wl,--gc-sections,
+ not to do the same. This is done by forcing an assignment to a
+ 'volatile' pointer.
- cc_params[cc_par_cnt++] =
- "-D__AFL_FUZZ_INIT()="
- "int __afl_sharedmem_fuzzing = 1;"
- "extern unsigned int *__afl_fuzz_len;"
- "extern unsigned char *__afl_fuzz_ptr;"
- "unsigned char __afl_fuzz_alt[1048576];"
- "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+ 3) We need to declare __afl_persistent_loop() in the global namespace,
+ but doing this within a method in a class is hard - :: and extern "C"
+ are forbidden and __attribute__((alias(...))) doesn't work. Hence the
+ __asm__ aliasing trick.
+
+ */
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_FUZZ_INIT()="
+ "int __afl_sharedmem_fuzzing = 1;"
+ "extern unsigned int *__afl_fuzz_len;"
+ "extern unsigned char *__afl_fuzz_ptr;"
+ "unsigned char __afl_fuzz_alt[1048576];"
+ "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+
+ }
if (plusplus_mode) {
@@ -1169,35 +1343,39 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff "
"? 0 : *__afl_fuzz_len)";
- cc_params[cc_par_cnt++] =
- "-D__AFL_LOOP(_A)="
- "({ static volatile char *_B __attribute__((used,unused)); "
- " _B = (char*)\"" PERSIST_SIG
- "\"; "
- "extern int __afl_connected;"
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_LOOP(_A)="
+ "({ static volatile const char *_B __attribute__((used,unused)); "
+ " _B = (const char*)\"" PERSIST_SIG
+ "\"; "
+ "extern int __afl_connected;"
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
- // if afl is connected, we run _A times, else once.
- "_L(__afl_connected ? _A : 1); })";
+ // if afl is connected, we run _A times, else once.
+ "_L(__afl_connected ? _A : 1); })";
- cc_params[cc_par_cnt++] =
- "-D__AFL_INIT()="
- "do { static volatile char *_A __attribute__((used,unused)); "
- " _A = (char*)\"" DEFER_SIG
- "\"; "
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_INIT()="
+ "do { static volatile const char *_A __attribute__((used,unused)); "
+ " _A = (const char*)\"" DEFER_SIG
+ "\"; "
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"___afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"___afl_manual_init\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"__afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
- "_I(); } while (0)";
+ "_I(); } while (0)";
+
+ }
if (x_set) {
@@ -1639,13 +1817,17 @@ int main(int argc, char **argv, char **envp) {
instrument_mode = INSTRUMENT_CLASSIC;
lto_mode = 1;
- } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
+ } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) {
instrument_mode = INSTRUMENT_AFL;
- else
+
+ } else {
+
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
+ }
+
}
if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
@@ -1660,7 +1842,8 @@ int main(int argc, char **argv, char **envp) {
}
if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 ||
- strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) {
+ strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 ||
+ strncasecmp(ptr2, "native", strlen("native")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE)
instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -1670,6 +1853,23 @@ int main(int argc, char **argv, char **envp) {
}
+ if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 ||
+ strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) {
+
+ if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) {
+
+ instrument_mode = INSTRUMENT_LLVMNATIVE;
+ instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
+
+ } else {
+
+ FATAL("main instrumentation mode already set with %s",
+ instrument_mode_string[instrument_mode]);
+
+ }
+
+ }
+
if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
@@ -1831,7 +2031,7 @@ int main(int argc, char **argv, char **envp) {
if (!compiler_mode) {
// lto is not a default because outside of afl-cc RANLIB and AR have to
- // be set to llvm versions so this would work
+ // be set to LLVM versions so this would work
if (have_llvm)
compiler_mode = LLVM;
else if (have_gcc_plugin)
@@ -1850,6 +2050,17 @@ int main(int argc, char **argv, char **envp) {
}
+ /* if our PCGUARD implementation is not available then silently switch to
+ native LLVM PCGUARD */
+ if (compiler_mode == CLANG &&
+ (instrument_mode == INSTRUMENT_DEFAULT ||
+ instrument_mode == INSTRUMENT_PCGUARD) &&
+ find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) {
+
+ instrument_mode = INSTRUMENT_LLVMNATIVE;
+
+ }
+
if (compiler_mode == GCC) {
if (clang_mode) {
@@ -1896,12 +2107,12 @@ int main(int argc, char **argv, char **envp) {
"-------------|\n"
"MODES: NCC PERSIST DICT LAF "
"CMPLOG SELECT\n"
- " [LTO] llvm LTO: %s%s\n"
+ " [LTO] LLVM LTO: %s%s\n"
" PCGUARD DEFAULT yes yes yes yes yes "
" yes\n"
" CLASSIC yes yes yes yes yes "
" yes\n"
- " [LLVM] llvm: %s%s\n"
+ " [LLVM] LLVM: %s%s\n"
" PCGUARD %s yes yes module yes yes "
"yes\n"
" CLASSIC %s no yes module yes yes "
@@ -1971,7 +2182,7 @@ int main(int argc, char **argv, char **envp) {
" (instrumentation/README.lto.md)\n"
" PERSIST: persistent mode support [code] (huge speed increase!)\n"
" (instrumentation/README.persistent_mode.md)\n"
- " DICT: dictionary in the target [yes=automatic or llvm module "
+ " DICT: dictionary in the target [yes=automatic or LLVM module "
"pass]\n"
" (instrumentation/README.lto.md + "
"instrumentation/README.llvm.md)\n"
@@ -2087,6 +2298,8 @@ int main(int argc, char **argv, char **envp) {
"bb\n"
" AFL_REAL_LD: use this lld linker instead of the compiled in "
"path\n"
+ " AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
+ "(used in WAFL mode)\n"
"If anything fails - be sure to read README.lto.md!\n");
#endif
@@ -2227,7 +2440,8 @@ int main(int argc, char **argv, char **envp) {
"(requires LLVM 11 or higher)");
#endif
- if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
+ if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
+ 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 86226c9f..84ddefd8 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -949,7 +949,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
/* Get unix time in milliseconds */
-u64 get_cur_time(void) {
+inline u64 get_cur_time(void) {
struct timeval tv;
struct timezone tz;
@@ -1359,3 +1359,52 @@ s32 create_file(u8 *fn) {
}
+#ifdef __linux__
+
+/* Nyx requires a tmp workdir to access specific files (such as mmapped files,
+ * etc.). This helper function basically creates both a path to a tmp workdir
+ * and the workdir itself. If the environment variable TMPDIR is set, we use
+ * that as the base directory, otherwise we use /tmp. */
+char *create_nyx_tmp_workdir(void) {
+
+ char *tmpdir = getenv("TMPDIR");
+
+ if (!tmpdir) { tmpdir = "/tmp"; }
+
+ char *nyx_out_dir_path =
+ alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
+
+ if (mkdir(nyx_out_dir_path, 0700)) { PFATAL("Unable to create nyx workdir"); }
+
+ return nyx_out_dir_path;
+
+}
+
+/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path) {
+
+ char *workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
+
+ if (access(workdir_path, R_OK) == 0) {
+
+ if (fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+
+ WARNF("Unable to remove nyx workdir (%s)", workdir_path);
+
+ }
+
+ }
+
+ if (rmdir(nyx_out_dir_path)) {
+
+ WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
+
+ }
+
+ ck_free(workdir_path);
+ ck_free(nyx_out_dir_path);
+
+}
+
+#endif
+
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 5aa4c2ff..7322f1ad 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -49,6 +49,134 @@
#include <sys/select.h>
#include <sys/stat.h>
+#ifdef __linux__
+ #include <dlfcn.h>
+
+/* function to load nyx_helper function from libnyx.so */
+
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
+
+ void *handle;
+ nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
+
+ ACTF("Trying to load libnyx.so plugin...");
+ handle = dlopen((char *)libnyx_binary, RTLD_NOW);
+ if (!handle) { goto fail; }
+
+ plugin->nyx_config_load = dlsym(handle, "nyx_config_load");
+ if (plugin->nyx_config_load == NULL) { goto fail; }
+
+ plugin->nyx_config_set_workdir_path =
+ dlsym(handle, "nyx_config_set_workdir_path");
+ if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_size =
+ dlsym(handle, "nyx_config_set_input_buffer_size");
+ if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_write_protection =
+ dlsym(handle, "nyx_config_set_input_buffer_write_protection");
+ if (plugin->nyx_config_set_input_buffer_write_protection == NULL) {
+
+ goto fail;
+
+ }
+
+ plugin->nyx_config_set_hprintf_fd =
+ dlsym(handle, "nyx_config_set_hprintf_fd");
+ if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; }
+
+ plugin->nyx_config_set_process_role =
+ dlsym(handle, "nyx_config_set_process_role");
+ if (plugin->nyx_config_set_process_role == NULL) { goto fail; }
+
+ plugin->nyx_config_set_reuse_snapshot_path =
+ dlsym(handle, "nyx_config_set_reuse_snapshot_path");
+ if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; }
+
+ plugin->nyx_new = dlsym(handle, "nyx_new");
+ if (plugin->nyx_new == NULL) { goto fail; }
+
+ plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
+ if (plugin->nyx_shutdown == NULL) { goto fail; }
+
+ plugin->nyx_option_set_reload_mode =
+ dlsym(handle, "nyx_option_set_reload_mode");
+ if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
+
+ plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
+ if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
+
+ plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
+ if (plugin->nyx_option_apply == NULL) { goto fail; }
+
+ plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
+ if (plugin->nyx_set_afl_input == NULL) { goto fail; }
+
+ plugin->nyx_exec = dlsym(handle, "nyx_exec");
+ if (plugin->nyx_exec == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
+ if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer_size =
+ dlsym(handle, "nyx_get_bitmap_buffer_size");
+ if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
+ if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+
+ plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
+ if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
+
+ OKF("libnyx plugin is ready!");
+ return plugin;
+
+fail:
+
+ FATAL("failed to load libnyx: %s\n", dlerror());
+ ck_free(plugin);
+ return NULL;
+
+}
+
+void afl_nyx_runner_kill(afl_forkserver_t *fsrv) {
+
+ if (fsrv->nyx_mode) {
+
+ if (fsrv->nyx_aux_string) { ck_free(fsrv->nyx_aux_string); }
+
+ /* check if we actually got a valid nyx runner */
+ if (fsrv->nyx_runner) {
+
+ fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+
+ }
+
+ /* if we have use a tmp work dir we need to remove it */
+ if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) {
+
+ remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path);
+
+ }
+
+ }
+
+}
+
+ /* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
+ * files) before exiting. Used before "afl_fsrv_killall()" is registered as
+ * an atexit() handler. */
+ #define NYX_PRE_FATAL(fsrv, x...) \
+ do { \
+ \
+ afl_nyx_runner_kill(fsrv); \
+ FATAL(x); \
+ \
+ } while (0)
+
+#endif
+
/**
* The correct fds for reading and writing pipes
*/
@@ -84,6 +212,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->nyx_runner = NULL;
fsrv->nyx_id = 0xFFFFFFFF;
fsrv->nyx_bind_cpu_id = 0xFFFFFFFF;
+ fsrv->nyx_use_tmp_workdir = false;
+ fsrv->nyx_tmp_workdir_path = NULL;
#endif
// this structure needs default so we initialize it if this was not done
@@ -359,7 +489,7 @@ static void report_error_and_exit(int error) {
break;
case FS_ERROR_OLD_CMPLOG:
FATAL(
- "the -c cmplog target was instrumented with an too old afl++ "
+ "the -c cmplog target was instrumented with an too old AFL++ "
"version, you need to recompile it.");
break;
case FS_ERROR_OLD_CMPLOG_QEMU:
@@ -397,40 +527,119 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Spinning up the NYX backend..."); }
- if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); }
+ if (fsrv->nyx_use_tmp_workdir) {
+
+ fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir();
+ fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path;
+
+ } else {
+
+ if (fsrv->out_dir_path == NULL) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path not found...");
+
+ }
+
+ }
+
+ /* libnyx expects an absolute path */
+ char *outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
+ if (outdir_path_absolute == NULL) {
- char *x = alloc_printf("%s/workdir", fsrv->out_dir_path);
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ...");
- if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); }
+ }
+
+ char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute);
+
+ if (fsrv->nyx_id == 0xFFFFFFFF) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx ID is not set...");
+
+ }
if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
- FATAL("Nyx CPU ID is not set...");
+ NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set...");
}
+ void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
+
+ fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
+ true);
+
if (fsrv->nyx_standalone) {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
} else {
if (fsrv->nyx_parent) {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_parent(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent);
} else {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_child(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, fsrv->nyx_id);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child);
+
+ }
+
+ }
+
+ if (getenv("NYX_REUSE_SNAPSHOT") != NULL) {
+
+ if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+
+ NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
+
+ }
+
+ /* stupid sanity check to avoid passing an empty or invalid snapshot
+ * directory */
+ char *snapshot_file_path =
+ alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+ if (access(snapshot_file_path, R_OK) == -1) {
+
+ NYX_PRE_FATAL(
+ fsrv,
+ "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+
+ }
+
+ ck_free(snapshot_file_path);
+
+ /* another sanity check to avoid passing a snapshot directory that is
+ * located in the current workdir (the workdir will be wiped by libnyx on
+ * startup) */
+ char *workdir_snapshot_path =
+ alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
+ char *reuse_snapshot_path_real =
+ realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+
+ if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) {
+
+ NYX_PRE_FATAL(fsrv,
+ "NYX_REUSE_SNAPSHOT path is located in current workdir "
+ "(use another output directory)");
}
+ ck_free(reuse_snapshot_path_real);
+ ck_free(workdir_snapshot_path);
+
+ fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(
+ nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+
}
- ck_free(x);
+ fsrv->nyx_runner =
+ fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
+
+ ck_free(workdir_path);
+ ck_free(outdir_path_absolute);
if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
@@ -458,15 +667,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- FATAL("Error: Nyx abort occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured...");
break;
case IoError:
- FATAL("Error: QEMU-Nyx has died...");
+ NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died...");
break;
case Error:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- FATAL("Error: Nyx runtime error has occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured...");
break;
default:
break;
@@ -476,7 +683,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* autodict in Nyx mode */
if (!ignore_autodict) {
- x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
+ char *x =
+ alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
int nyx_autodict_fd = open(x, O_RDONLY);
ck_free(x);
@@ -489,8 +697,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u8 *dict = ck_alloc(f_len);
if (dict == NULL) {
- FATAL("Could not allocate %u bytes of autodictionary memory",
- f_len);
+ NYX_PRE_FATAL(
+ fsrv, "Could not allocate %u bytes of autodictionary memory",
+ f_len);
}
@@ -507,7 +716,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} else {
- FATAL(
+ NYX_PRE_FATAL(
+ fsrv,
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
@@ -777,7 +987,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
- // workaround for recent afl++ versions
+ // workaround for recent AFL++ versions
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff);
@@ -849,7 +1059,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
FATAL(
"Target's coverage map size of %u is larger than the one this "
- "afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
+ "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
"afl-fuzz",
tmp_map_size, fsrv->map_size, tmp_map_size);
@@ -1016,7 +1226,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke <afl-users@googlegroups.com> for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n");
} else {
@@ -1061,7 +1271,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke <afl-users@googlegroups.com> for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n",
stringify_mem_size(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
fsrv->mem_limit - 1);
@@ -1111,7 +1321,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
"Otherwise there is a horrible bug in the fuzzer.\n"
- "Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
+ "Poke the Awesome Fuzzing Discord for troubleshooting tips.\n");
} else {
@@ -1160,7 +1370,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke <afl-users@googlegroups.com> for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n",
getenv(DEFER_ENV_VAR)
? " - You are using deferred forkserver, but __AFL_INIT() is "
@@ -1194,13 +1404,7 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
fsrv->child_pid = -1;
#ifdef __linux__
- if (fsrv->nyx_mode) {
-
- free(fsrv->nyx_aux_string);
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
-
- }
-
+ afl_nyx_runner_kill(fsrv);
#endif
}
@@ -1377,7 +1581,6 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
break;
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
FATAL("Error: Nyx abort occured...");
case IoError:
if (*stop_soon_p) {
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index a937c96d..fb8a1d4b 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -465,7 +465,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
u8 fn[PATH_MAX];
u8 *queue_fn = "";
- u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0;
+ u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0,
+ need_hash = 1;
s32 fd;
u64 cksum = 0;
@@ -477,6 +478,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
classify_counts(&afl->fsrv);
classified = 1;
+ need_hash = 0;
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@@ -499,6 +501,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
+ if (unlikely(new_bits)) { classified = 1; }
+
}
if (likely(!new_bits)) {
@@ -577,12 +581,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- if (unlikely(!classified && new_bits)) {
+ if (unlikely(need_hash && new_bits)) {
/* due to classify counts we have to recalculate the checksum */
afl->queue_top->exec_cksum =
hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
- classified = 1;
+ need_hash = 0;
}
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 01d1e82e..13802f40 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -716,12 +716,25 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
+ // if (getenv("MYTEST")) afl->in_place_resume = 1;
+
if (nl_cnt) {
- i = nl_cnt;
+ u32 done = 0;
+
+ if (unlikely(afl->in_place_resume)) {
+
+ i = nl_cnt;
+
+ } else {
+
+ i = 0;
+
+ }
+
do {
- --i;
+ if (unlikely(afl->in_place_resume)) { --i; }
struct stat st;
u8 dfn[PATH_MAX];
@@ -745,7 +758,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
free(nl[i]); /* not tracked */
read_testcases(afl, fn2);
ck_free(fn2);
- continue;
+ goto next_entry;
}
@@ -754,7 +767,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
ck_free(fn2);
- continue;
+ goto next_entry;
}
@@ -801,21 +814,23 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
- /*
- if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ next_entry:
+ if (unlikely(afl->in_place_resume)) {
- 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;
+ if (unlikely(i == 0)) { done = 1; }
- }
+ } else {
- */
+ if (unlikely(++i >= (u32)nl_cnt)) { done = 1; }
- } while (i > 0);
+ }
+
+ } while (!done);
}
+ // if (getenv("MYTEST")) afl->in_place_resume = 0;
+
free(nl); /* not tracked */
if (!afl->queued_items && directory == NULL) {
@@ -897,8 +912,10 @@ void perform_dry_run(afl_state_t *afl) {
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
- SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST,
- q->len, q->bitmap_size, q->exec_us);
+ SAYF(cGRA
+ " len = %u, map size = %u, exec speed = %llu us, hash = "
+ "%016llx\n" cRST,
+ q->len, q->bitmap_size, q->exec_us, q->exec_cksum);
}
@@ -995,7 +1012,7 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n"
- " fail, poke <afl-users@googlegroups.com> for "
+ " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n",
stringify_mem_size(val_buf, sizeof(val_buf),
afl->fsrv.mem_limit << 20),
@@ -1024,7 +1041,7 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n"
- " fail, poke <afl-users@googlegroups.com> for "
+ " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n");
}
@@ -1153,14 +1170,14 @@ void perform_dry_run(afl_state_t *afl) {
u32 duplicates = 0, i;
- for (idx = 0; idx < afl->queued_items; idx++) {
+ for (idx = 0; idx < afl->queued_items - 1; idx++) {
q = afl->queue_buf[idx];
if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
-
u32 done = 0;
+
for (i = idx + 1;
- i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) {
+ likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) {
struct queue_entry *p = afl->queue_buf[i];
if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
@@ -1183,6 +1200,13 @@ void perform_dry_run(afl_state_t *afl) {
p->disabled = 1;
p->perf_score = 0;
+ if (afl->debug) {
+
+ WARNF("Same coverage - %s is kept active, %s is disabled.",
+ q->fname, p->fname);
+
+ }
+
} else {
if (!q->was_fuzzed) {
@@ -1196,7 +1220,14 @@ void perform_dry_run(afl_state_t *afl) {
q->disabled = 1;
q->perf_score = 0;
- done = 1;
+ if (afl->debug) {
+
+ WARNF("Same coverage - %s is kept active, %s is disabled.",
+ p->fname, q->fname);
+
+ }
+
+ done = 1; // end inner loop because outer loop entry is disabled now
}
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 9ea46e7a..64dbe7c6 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -179,11 +179,19 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
void *dh;
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
- mutator->name = fn;
- if (memchr(fn, '/', strlen(fn)))
- mutator->name_short = strrchr(fn, '/') + 1;
- else
+ if (memchr(fn, '/', strlen(fn))) {
+
+ mutator->name_short = strdup(strrchr(fn, '/') + 1);
+
+ } else {
+
mutator->name_short = strdup(fn);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
+ mutator->name = fn;
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 312e180d..ec348a95 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -799,6 +799,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
@@ -1868,6 +1869,7 @@ custom_mutator_stage:
afl->stage_name = "custom mutator";
afl->stage_short = "custom";
+ afl->stage_cur = 0;
afl->stage_val_type = STAGE_VAL_NONE;
bool has_custom_fuzz = false;
u32 shift = unlikely(afl->custom_only) ? 7 : 8;
@@ -1888,6 +1890,7 @@ custom_mutator_stage:
if (el->afl_custom_fuzz) {
afl->current_custom_fuzz = el;
+ afl->stage_name = el->name_short;
if (el->afl_custom_fuzz_count) {
@@ -2003,20 +2006,22 @@ custom_mutator_stage:
afl->queue_cur->stats_mutated += afl->stage_max;
#endif
- if (likely(afl->custom_only)) {
+ /****************
+ * RANDOM HAVOC *
+ ****************/
+
+havoc_stage:
+
+ if (unlikely(afl->custom_only)) {
+ /* Force UI update */
+ show_stats(afl);
/* Skip other stages */
ret_val = 0;
goto abandon_entry;
}
- /****************
- * RANDOM HAVOC *
- ****************/
-
-havoc_stage:
-
afl->stage_cur_byte = -1;
/* The havoc stage mutation code is also invoked when splicing files; if the
@@ -2028,7 +2033,7 @@ havoc_stage:
afl->stage_short = "havoc";
afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
perf_score / afl->havoc_div) >>
- 7;
+ 8;
} else {
@@ -2037,7 +2042,7 @@ havoc_stage:
snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = "splice";
- afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
@@ -3880,6 +3885,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
@@ -4951,7 +4957,7 @@ pacemaker_fuzzing:
MOpt_globals.splice_stageformat, splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = MOpt_globals.splice_stagenameshort;
- afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 2799268b..7dad0770 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -219,11 +219,14 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (py_module != NULL) {
- u8 py_notrim = 0, py_idx;
- /* init, required */
+ u8 py_notrim = 0;
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
- if (!py_functions[PY_FUNC_INIT])
- FATAL("init function not found in python module");
+ if (!py_functions[PY_FUNC_INIT]) {
+
+ WARNF("init function not found in python module");
+
+ }
+
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
@@ -231,12 +234,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
- if (!py_functions[PY_FUNC_FUZZ]) {
-
- WARNF("fuzz function not found in python module");
-
- }
-
py_functions[PY_FUNC_POST_PROCESS] =
PyObject_GetAttrString(py_module, "post_process");
py_functions[PY_FUNC_INIT_TRIM] =
@@ -263,36 +260,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (!py_functions[PY_FUNC_DEINIT])
WARNF("deinit function not found in python module");
- for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
-
- if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
-
- if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
-
- // Implementing the trim API is optional for now
- if (PyErr_Occurred()) { PyErr_Print(); }
- py_notrim = 1;
-
- } else if (py_idx >= PY_OPTIONAL) {
-
- // Only _init and _deinit are not optional currently
-
- if (PyErr_Occurred()) { PyErr_Print(); }
-
- } else {
-
- fprintf(stderr,
- "Cannot find/call function with index %d in external "
- "Python module.\n",
- py_idx);
- return NULL;
-
- }
-
- }
-
- }
-
if (py_notrim) {
py_functions[PY_FUNC_INIT_TRIM] = NULL;
@@ -345,6 +312,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
(void)afl;
+ if (py_mutator->py_functions[PY_FUNC_INIT] == NULL) { return; }
+
PyObject *py_args, *py_value;
/* Provide the init function a seed for the Python RNG */
@@ -414,10 +383,21 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
struct custom_mutator *mutator;
mutator = ck_alloc(sizeof(struct custom_mutator));
-
mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
+ if (memchr(module_name, '/', strlen(module_name))) {
+
+ mutator->name_short = strdup(strrchr(module_name, '/') + 1);
+
+ } else {
+
+ mutator->name_short = strdup(module_name);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
py_mutator_t *py_mutator;
py_mutator = init_py_module(afl, module_name);
mutator->data = py_mutator;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index fff8db03..48fd33ec 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
u32 s = rand_below(afl, afl->queued_items);
double p = rand_next_percent(afl);
+
/*
fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u"
" ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p <
afl->alias_probability[s] ? s : afl->alias_table[s]);
*/
+
return (p < afl->alias_probability[s] ? s : afl->alias_table[s]);
}
@@ -74,7 +76,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(weight < 1.0)) { weight = 1.0; }
+
+ if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
@@ -86,25 +89,28 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
void create_alias_table(afl_state_t *afl) {
- u32 n = afl->queued_items, i = 0, a, g;
+ u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1;
double sum = 0;
+ double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
+ u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
+ u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
+
afl->alias_table =
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
afl->alias_probability = (double *)afl_realloc(
(void **)&afl->alias_probability, n * sizeof(double));
- double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
- int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
- int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
- if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
+ if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) {
FATAL("could not acquire memory for alias table");
}
- memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
+ memset((void *)afl->alias_table, 0, n * sizeof(u32));
+ memset((void *)Small, 0, n * sizeof(u32));
+ memset((void *)Large, 0, n * sizeof(u32));
if (likely(afl->schedule < RARE)) {
@@ -148,10 +154,32 @@ void create_alias_table(afl_state_t *afl) {
}
+ if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) {
+
+ u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered;
+
+ for (i = n - cnt; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+
+ if (likely(!q->disabled)) { q->weight *= 2.0; }
+
+ }
+
+ }
+
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
- P[i] = (afl->queue_buf[i]->weight * n) / sum;
+ if (unlikely(afl->queue_buf[i]->disabled)) {
+
+ P[i] = 0;
+
+ } else {
+
+ P[i] = (afl->queue_buf[i]->weight * n) / sum;
+
+ }
}
@@ -161,60 +189,81 @@ void create_alias_table(afl_state_t *afl) {
struct queue_entry *q = afl->queue_buf[i];
- if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); }
+ if (likely(!q->disabled)) {
+
+ q->perf_score = calculate_score(afl, q);
+ sum += q->perf_score;
- sum += q->perf_score;
+ }
}
for (i = 0; i < n; i++) {
// perf_score is always 0 for disabled entries
- P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+ if (unlikely(afl->queue_buf[i]->disabled)) {
+
+ P[i] = 0;
+
+ } else {
+
+ P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+
+ }
}
}
- int nS = 0, nL = 0, s;
- for (s = (s32)n - 1; s >= 0; --s) {
+ // Done collecting weightings in P, now create the arrays.
- if (P[s] < 1) {
+ for (s32 j = (s32)(n - 1); j >= 0; j--) {
- S[nS++] = s;
+ if (P[j] < 1) {
+
+ Small[nSmall++] = (u32)j;
} else {
- L[nL++] = s;
+ Large[nLarge--] = (u32)j;
}
}
- while (nS && nL) {
+ while (nSmall && nLarge != n - 1) {
+
+ u32 small = Small[--nSmall];
+ u32 large = Large[++nLarge];
+
+ afl->alias_probability[small] = P[small];
+ afl->alias_table[small] = large;
- a = S[--nS];
- g = L[--nL];
- afl->alias_probability[a] = P[a];
- afl->alias_table[a] = g;
- P[g] = P[g] + P[a] - 1;
- if (P[g] < 1) {
+ P[large] = P[large] - (1 - P[small]);
- S[nS++] = g;
+ if (P[large] < 1) {
+
+ Small[nSmall++] = large;
} else {
- L[nL++] = g;
+ Large[nLarge--] = large;
}
}
- while (nL)
- afl->alias_probability[L[--nL]] = 1;
+ while (nSmall) {
+
+ afl->alias_probability[Small[--nSmall]] = 1;
+
+ }
+
+ while (nLarge != n - 1) {
- while (nS)
- afl->alias_probability[S[--nS]] = 1;
+ afl->alias_probability[Large[++nLarge]] = 1;
+
+ }
afl->reinit_table = 0;
@@ -249,7 +298,7 @@ void create_alias_table(afl_state_t *afl) {
*/
/*
fprintf(stderr, " entry alias probability perf_score weight
- filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
+ filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
%0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i],
afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight,
afl->queue_buf[i]->fname);
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 6e4a655b..41644cb9 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -28,8 +28,8 @@
#include "afl-fuzz.h"
#include "cmplog.h"
-//#define _DEBUG
-//#define CMPLOG_INTROSPECTION
+// #define _DEBUG
+// #define CMPLOG_INTROSPECTION
// CMP attribute enum
enum {
@@ -379,7 +379,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
}
- if (++afl->stage_cur % screen_update == 0) { show_stats(afl); };
+ if (unlikely(++afl->stage_cur % screen_update == 0)) { show_stats(afl); };
}
@@ -571,7 +571,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
}
-//#ifdef CMPLOG_SOLVE_TRANSFORM
+// #ifdef CMPLOG_SOLVE_TRANSFORM
static int strntoll(const char *str, size_t sz, char **end, int base,
long long *out) {
@@ -771,7 +771,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
#endif
-//#endif
+// #endif
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern,
@@ -790,7 +790,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 its_len = MIN(len - idx, taint_len);
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -803,8 +803,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// o_pattern, pattern, repl, changed_val, idx, taint_len,
// hshape, attr);
- //#ifdef CMPLOG_SOLVE_TRANSFORM
- // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
+ // #ifdef CMPLOG_SOLVE_TRANSFORM
+ // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u8 *endptr;
@@ -1120,7 +1120,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- //#endif
+ // #endif
// we only allow this for ascii2integer (above) so leave if this is the case
if (unlikely(pattern == o_pattern)) { return 0; }
@@ -1275,7 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// 16 = modified float, 32 = modified integer (modified = wont match
// in original buffer)
- //#ifdef CMPLOG_SOLVE_ARITHMETIC
+ // #ifdef CMPLOG_SOLVE_ARITHMETIC
if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
return 0;
@@ -1440,8 +1440,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- //#endif /*
- // CMPLOG_SOLVE_ARITHMETIC
+ // #endif /*
+ // CMPLOG_SOLVE_ARITHMETIC
return 0;
@@ -1455,7 +1455,7 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 do_reverse, u8 lvl, u8 *status) {
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -1948,11 +1948,11 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
#ifndef CMPLOG_COMBINE
(void)(cbuf);
#endif
- //#ifndef CMPLOG_SOLVE_TRANSFORM
- // (void)(changed_val);
- //#endif
+ // #ifndef CMPLOG_SOLVE_TRANSFORM
+ // (void)(changed_val);
+ // #endif
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -2418,7 +2418,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
- //#endif
+ // #endif
return 0;
@@ -2818,9 +2818,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} else if ((lvl & LVL1)
- //#ifdef CMPLOG_SOLVE_TRANSFORM
+ // #ifdef CMPLOG_SOLVE_TRANSFORM
|| ((lvl & LVL3) && afl->cmplog_enable_transform)
- //#endif
+ // #endif
) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index f5425011..ac4fb4a9 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -133,7 +133,24 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
}
- if (new_mem != *mem) { *mem = new_mem; }
+ if (new_mem != *mem && new_mem != NULL && new_size > 0) {
+
+ new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+ memcpy(new_buf, new_mem, new_size);
+
+ /* if AFL_POST_PROCESS_KEEP_ORIGINAL is set then save the original memory
+ prior post-processing in new_mem to restore it later */
+ if (unlikely(afl->afl_env.afl_post_process_keep_original)) {
+
+ new_mem = *mem;
+
+ }
+
+ *mem = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+
+ }
if (unlikely(afl->custom_mutators_count)) {
@@ -154,7 +171,18 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
/* everything as planned. use the potentially new data. */
afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
- len = new_size;
+
+ if (likely(!afl->afl_env.afl_post_process_keep_original)) {
+
+ len = new_size;
+
+ } else {
+
+ /* restore the original memory which was saved in new_mem */
+ *mem = new_mem;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+
+ }
}
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 9dc258b1..99f69314 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -395,6 +395,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_statsd =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_POST_PROCESS_KEEP_ORIGINAL",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_post_process_keep_original =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_TMPDIR",
afl_environment_variable_len)) {
@@ -649,7 +656,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
- if (afl->afl_env.afl_pizza_mode) { afl->pizza_is_served = 1; }
+ if (afl->afl_env.afl_pizza_mode > 0) {
+
+ afl->pizza_is_served = 1;
+
+ } else if (afl->afl_env.afl_pizza_mode < 0) {
+
+ OKF("Pizza easter egg mode is now disabled.");
+
+ }
if (issue_detected) { sleep(2); }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index de48e10a..4ffb2536 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -753,20 +753,20 @@ void show_stats_normal(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
@@ -1560,20 +1560,22 @@ void show_stats_pizza(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
@@ -1804,10 +1806,10 @@ void show_stats_pizza(afl_state_t *afl) {
/* Show a warning about slow execution. */
- if (afl->stats_avg_exec < 100) {
+ if (afl->stats_avg_exec < 20) {
sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
- afl->stats_avg_exec < 20 ? "zzzz..." : "Gennarino is at it again!");
+ "zzzz...");
SAYF(bV bSTOP " pizza making speed : " cLRD
"%-22s ",
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index bc44367a..d727fff5 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -124,7 +124,8 @@ static void usage(u8 *argv0, int more_help) {
"\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
"Required parameters:\n"
- " -i dir - input directory with test cases\n"
+ " -i dir - input directory with test cases (or '-' to resume, "
+ "also see AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
@@ -173,7 +174,6 @@ static void usage(u8 *argv0, int more_help) {
" pacemaker mode (minutes of no new finds). 0 = "
"immediately,\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"
" if using QEMU/FRIDA or the fuzzing target is "
@@ -269,6 +269,8 @@ static void usage(u8 *argv0, int more_help) {
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
+ "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n"
+ " ignore those libs for coverage\n"
"AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
@@ -302,6 +304,8 @@ static void usage(u8 *argv0, int more_help) {
PERSISTENT_MSG
+ "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to the queue,\n"
+ " but execute the post-processed one\n"
"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"
@@ -336,7 +340,7 @@ static void usage(u8 *argv0, int more_help) {
}
#ifdef USE_PYTHON
- SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
+ SAYF("Compiled with %s module support, see docs/custom_mutators.md\n",
(char *)PYTHON_VERSION);
#else
SAYF("Compiled without Python module support.\n");
@@ -445,69 +449,6 @@ static void fasan_check_afl_preload(char *afl_preload) {
}
- #ifdef __linux__
- #include <dlfcn.h>
-
-nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
-
- void *handle;
- nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
-
- ACTF("Trying to load libnyx.so plugin...");
- handle = dlopen((char *)libnyx_binary, RTLD_NOW);
- if (!handle) { goto fail; }
-
- plugin->nyx_new = dlsym(handle, "nyx_new");
- if (plugin->nyx_new == NULL) { goto fail; }
-
- plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
- if (plugin->nyx_new_parent == NULL) { goto fail; }
-
- plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
- if (plugin->nyx_new_child == NULL) { goto fail; }
-
- plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
- if (plugin->nyx_shutdown == NULL) { goto fail; }
-
- plugin->nyx_option_set_reload_mode =
- dlsym(handle, "nyx_option_set_reload_mode");
- if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
-
- plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
- if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
-
- plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
- if (plugin->nyx_option_apply == NULL) { goto fail; }
-
- plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
- if (plugin->nyx_set_afl_input == NULL) { goto fail; }
-
- plugin->nyx_exec = dlsym(handle, "nyx_exec");
- if (plugin->nyx_exec == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
- if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer_size =
- dlsym(handle, "nyx_get_bitmap_buffer_size");
- if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
-
- plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
- if (plugin->nyx_get_aux_string == NULL) { goto fail; }
-
- OKF("libnyx plugin is ready!");
- return plugin;
-
-fail:
-
- FATAL("failed to load libnyx: %s\n", dlerror());
- free(plugin);
- return NULL;
-
-}
-
- #endif
-
/* Main entry point */
int main(int argc, char **argv_orig, char **envp) {
@@ -1383,16 +1324,16 @@ int main(int argc, char **argv_orig, char **envp) {
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\" "
- "Eißfeldt, Andrea Fioraldi and Dominik Maier");
- OKF("afl++ is open source, get it at "
+ OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
+ "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
+ OKF("AFL++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
- OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md");
+ OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
+ OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
}
@@ -1632,29 +1573,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
-
- if (afl->custom_only) {
-
- FATAL("Custom mutators are incompatible with MOpt (-L)");
-
- }
-
- u32 custom_fuzz = 0;
- LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
-
- if (el->afl_custom_fuzz) { custom_fuzz = 1; }
-
- });
-
- if (custom_fuzz) {
-
- WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
-
- }
-
- }
-
if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@@ -1871,16 +1789,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_custom_mutator_only) {
-
- /* This ensures we don't proceed to havoc/splice */
- afl->custom_only = 1;
-
- /* Ensure we also skip all deterministic steps */
- afl->skip_deterministic = 1;
-
- }
-
get_core_count(afl);
atexit(at_exit);
@@ -1929,8 +1837,107 @@ int main(int argc, char **argv_orig, char **envp) {
printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
#endif
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
+
+ }
+
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
+
+ }
+
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) {
+
+ u8 envbuf[8096] = "", tmpbuf[8096] = "";
+ for (s32 i = optind + 1; i < argc; ++i) {
+
+ strcpy(tmpbuf, envbuf);
+ if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
+ !strchr(argv[i], '\'')) {
+
+ if (!strchr(argv[i], '\'')) {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
+
+ } else {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
+
+ }
+
+ } else {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
+
+ }
+
+ }
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
+
+ }
+
+ if (!getenv("AFL_CUSTOM_INFO_OUT")) {
+
+ setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
+
+ }
+
setup_custom_mutators(afl);
+ if (afl->afl_env.afl_custom_mutator_only) {
+
+ if (!afl->custom_mutators_count) {
+
+ if (afl->shm.cmplog_mode) {
+
+ WARNF(
+ "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
+ "pointless and only allowed now to allow experiments with CMPLOG.");
+
+ } else {
+
+ FATAL(
+ "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
+
+ }
+
+ }
+
+ /* This ensures we don't proceed to havoc/splice */
+ afl->custom_only = 1;
+
+ /* Ensure we also skip all deterministic steps */
+ afl->skip_deterministic = 1;
+
+ }
+
+ if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
+
+ if (afl->custom_only) {
+
+ FATAL("Custom mutators are incompatible with MOpt (-L)");
+
+ }
+
+ u32 custom_fuzz = 0;
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz) { custom_fuzz = 1; }
+
+ });
+
+ if (custom_fuzz) {
+
+ WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
+
+ }
+
+ }
+
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind);
@@ -2082,6 +2089,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
+ u32 old_map_size = map_size;
map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
@@ -2093,6 +2101,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
+ if (old_map_size < map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
+
+ }
+
}
afl->argv = use_argv;
@@ -2120,6 +2140,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes", new_map_size);
+ u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2132,6 +2153,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
+ if (old_map_size < new_map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ new_map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+ }
+
afl_fsrv_kill(&afl->fsrv);
afl_shm_deinit(&afl->shm);
afl->fsrv.map_size = new_map_size;
@@ -2182,6 +2215,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
+ u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2194,6 +2228,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
+ if (old_map_size < new_map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ new_map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+ }
+
afl_fsrv_kill(&afl->fsrv);
afl_fsrv_kill(&afl->cmplog_fsrv);
afl_shm_deinit(&afl->shm);
@@ -2293,14 +2339,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->pending_not_fuzzed || !valid_seeds) {
- #ifdef __linux__
- if (afl->fsrv.nyx_mode) {
-
- afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
-
- }
-
- #endif
FATAL("We need at least one valid input seed that does not crash!");
}
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 5438bd9f..420dd817 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -2,7 +2,7 @@
american fuzzy lop++ - wrapper for llvm 11+ lld
-----------------------------------------------
- Written by Marc Heuse <mh@mh-sec.de> for afl++
+ Written by Marc Heuse <mh@mh-sec.de> for AFL++
Maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
@@ -210,7 +210,7 @@ static void edit_params(int argc, char **argv) {
if (strcmp(argv[i], "--afl") == 0) {
- if (!be_quiet) OKF("afl++ test command line flag detected, exiting.");
+ if (!be_quiet) OKF("AFL++ test command line flag detected, exiting.");
exit(0);
}
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 29abeb13..9c029035 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -30,8 +30,10 @@
*/
#define AFL_MAIN
+#define AFL_SHOWMAP
#include "config.h"
+#include "afl-fuzz.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"
@@ -62,10 +64,14 @@
#include <sys/types.h>
#include <sys/resource.h>
+static afl_state_t *afl;
+
static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
- *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
+ *out_file = NULL, /* output file or directory */
+ *at_file = NULL, /* Substitution string for @@ */
+ *in_filelist = NULL; /* input file list */
static u8 outfile[PATH_MAX];
@@ -136,7 +142,39 @@ static void kill_child() {
}
-static void classify_counts(afl_forkserver_t *fsrv) {
+/* dummy functions */
+u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
+
+ (void)afl;
+ (void)mem;
+ return a + b;
+
+}
+
+void show_stats(afl_state_t *afl) {
+
+ (void)afl;
+
+}
+
+void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
+
+ (void)afl;
+ (void)q;
+
+}
+
+fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
+ u32 i) {
+
+ (void)afl;
+ (void)fsrv;
+ (void)i;
+ return 0;
+
+}
+
+void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human;
@@ -308,12 +346,73 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
}
+void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) {
+
+ static u8 buf[MAX_FILE];
+ u32 sent = 0;
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ ssize_t new_size = len;
+ u8 *new_mem = mem;
+ u8 *new_buf = NULL;
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_post_process) {
+
+ new_size =
+ el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
+
+ if (unlikely(!new_buf || new_size <= 0)) {
+
+ return;
+
+ } else {
+
+ new_mem = new_buf;
+ len = new_size;
+
+ }
+
+ }
+
+ });
+
+ if (new_mem != mem && new_mem != NULL) {
+
+ mem = buf;
+ memcpy(mem, new_mem, new_size);
+
+ }
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ el->afl_custom_fuzz_send(el->data, mem, len);
+ sent = 1;
+
+ }
+
+ });
+
+ }
+
+ }
+
+ if (likely(!sent)) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
+
+}
+
/* Execute target application. */
static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
- afl_fsrv_write_to_testcase(fsrv, mem, len);
+ pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
@@ -434,6 +533,23 @@ static u32 read_file(u8 *in_file) {
}
+#ifdef __linux__
+/* Execute the target application with an empty input (in Nyx mode). */
+static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
+
+ afl_fsrv_write_to_testcase(fsrv, NULL, 0);
+
+ if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
+ FSRV_RUN_ERROR) {
+
+ FATAL("Error running target in Nyx mode");
+
+ }
+
+}
+
+#endif
+
/* Execute target application. */
static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
@@ -764,6 +880,103 @@ u32 execute_testcases(u8 *dir) {
}
+u32 execute_testcases_filelist(u8 *fn) {
+
+ u32 done = 0;
+ u8 buf[4096];
+ u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
+ FILE *f;
+
+ if (!be_quiet) { ACTF("Reading from '%s'...", fn); }
+
+ if ((f = fopen(fn, "r")) == NULL) { FATAL("could not open '%s'", fn); }
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+
+ struct stat st;
+ u8 *fn2 = buf, *fn3;
+
+ while (*fn2 == ' ') {
+
+ ++fn2;
+
+ }
+
+ while (*fn2 &&
+ (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
+ fn2[strlen(fn2) - 1] == ' ')) {
+
+ fn2[strlen(fn2) - 1] = 0;
+
+ }
+
+ if (debug) { printf("Getting coverage for '%s'\n", fn2); }
+
+ if (!*fn2) { continue; }
+
+ if (lstat(fn2, &st) || access(fn2, R_OK)) {
+
+ WARNF("Unable to access '%s'", fn2);
+ continue;
+
+ }
+
+ ++done;
+
+ if (!S_ISREG(st.st_mode) || !st.st_size) { continue; }
+
+ if ((fn3 = strrchr(fn2, '/'))) {
+
+ ++fn3;
+
+ } else {
+
+ fn3 = fn2;
+
+ }
+
+ 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),
+ stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
+
+ }
+
+ if (!collect_coverage) {
+
+ snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3);
+
+ }
+
+ 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);
+
+ if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
+
+ if (collect_coverage)
+ analyze_results(fsrv);
+ else
+ tcnt = write_results_to_file(fsrv, outfile);
+
+ }
+
+ }
+
+ return done;
+
+}
+
/* Show banner. */
static void show_banner(void) {
@@ -797,6 +1010,7 @@ static void usage(u8 *argv0) {
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
"Other settings:\n"
@@ -805,6 +1019,7 @@ static void usage(u8 *argv0) {
" With -C, -o is a file, without -C it must be a "
"directory\n"
" and each bitmap will be written there individually.\n"
+ " -I filelist - alternatively to -i, -I is a list of files\n"
" -C - collect coverage, writes all edges to -o and gives a "
"summary\n"
" Must be combined with -i.\n"
@@ -817,6 +1032,10 @@ static void usage(u8 *argv0) {
"This tool displays raw tuple data captured by AFL instrumentation.\n"
"For additional help, consult %s/README.md.\n\n"
+ "If you use -i/-I mode, then custom mutator post_process send send "
+ "functionality\n"
+ "is supported.\n\n"
+
"Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
@@ -875,7 +1094,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:I:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
switch (opt) {
@@ -893,6 +1112,11 @@ int main(int argc, char **argv_orig, char **envp) {
in_dir = optarg;
break;
+ case 'I':
+ if (in_filelist) { FATAL("Multiple -I options not supported"); }
+ in_filelist = optarg;
+ break;
+
case 'o':
if (out_file) { FATAL("Multiple -o options not supported"); }
@@ -1063,6 +1287,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthrough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'b':
/* Secret undocumented mode. Writes output in raw binary format
@@ -1098,10 +1339,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !out_file) { usage(argv[0]); }
- if (in_dir) {
+ if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
+
+ if (in_dir || in_filelist) {
if (!out_file && !collect_coverage)
- FATAL("for -i you need to specify either -C and/or -o");
+ FATAL("for -i/-I you need to specify either -C and/or -o");
}
@@ -1134,7 +1377,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+ fsrv->target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv->target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
if (!quiet_mode) {
@@ -1144,7 +1401,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (in_dir) {
+ if (in_dir || in_filelist) {
/* If we don't have a file name chosen yet, use a safe default. */
u8 *use_dir = ".";
@@ -1164,6 +1421,14 @@ int main(int argc, char **argv_orig, char **envp) {
// If @@ are in the target args, replace them and also set use_stdin=false.
detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
+ fsrv->dev_null_fd = open("/dev/null", O_RDWR);
+ if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
+
+ fsrv->out_file = stdin_file;
+ fsrv->out_fd =
+ open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+ if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); }
+
} else {
// If @@ are in the target args, replace them and also set use_stdin=false.
@@ -1190,12 +1455,35 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv->nyx_mode) {
+
+ use_argv = ck_alloc(sizeof(char *) * (1));
+ use_argv[0] = argv[0];
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv->nyx_use_tmp_workdir = true;
+ fsrv->nyx_bind_cpu_id = 0;
+#endif
+
} else {
use_argv = argv + optind;
}
+ afl = calloc(1, sizeof(afl_state_t));
+
if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
@@ -1226,7 +1514,16 @@ int main(int argc, char **argv_orig, char **envp) {
}
+#ifdef __linux__
+ if (!fsrv->nyx_mode && (in_dir || in_filelist)) {
+
+ (void)check_binary_signatures(fsrv->target_path);
+
+ }
+
+#else
if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+#endif
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
@@ -1246,8 +1543,14 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32);
- configure_afl_kill_signals(
- fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
+ configure_afl_kill_signals(fsrv, NULL, NULL,
+ (fsrv->qemu_mode || unicorn_mode
+#ifdef __linux__
+ || fsrv->nyx_mode
+#endif
+ )
+ ? SIGKILL
+ : SIGTERM);
if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
@@ -1293,28 +1596,66 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->map_size = map_size;
+ } else {
+
+ afl_fsrv_start(fsrv, use_argv, &stop_soon,
+ (get_afl_env("AFL_DEBUG_CHILD") ||
+ get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+ ? 1
+ : 0);
+
+ }
+
+ if (in_dir || in_filelist) {
+
+ afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+ afl->afl_env.afl_custom_mutator_library =
+ getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
+ afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
+ setup_custom_mutators(afl);
+
+ } else {
+
+ if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
+
+ WARNF(
+ "Custom mutator environment detected, this is only supported in "
+ "-i/-I mode!\n");
+
+ }
+
}
- if (in_dir) {
+ if (in_dir || in_filelist) {
DIR *dir_in, *dir_out = NULL;
+ u8 *dn = NULL;
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"); }
+ if (in_filelist) {
+
+ if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
+
+ } else {
+
+ // if a queue subdirectory exists switch to that
+ dn = alloc_printf("%s/queue", in_dir);
+
+ if ((dir_in = opendir(dn)) != NULL) {
+
+ closedir(dir_in);
+ in_dir = dn;
+
+ } else {
- // if a queue subdirectory exists switch to that
- u8 *dn = alloc_printf("%s/queue", in_dir);
- if ((dir_in = opendir(dn)) != NULL) {
+ ck_free(dn);
- closedir(dir_in);
- in_dir = dn;
+ }
- } else
+ if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
- ck_free(dn);
- if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
+ }
if (!collect_coverage) {
@@ -1338,10 +1679,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
atexit(at_exit_handler);
- fsrv->out_file = stdin_file;
- fsrv->out_fd =
- open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
- if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
if (get_afl_env("AFL_DEBUG")) {
@@ -1357,20 +1694,26 @@ int main(int argc, char **argv_orig, char **envp) {
}
- afl_fsrv_start(fsrv, use_argv, &stop_soon,
- (get_afl_env("AFL_DEBUG_CHILD") ||
- get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
- ? 1
- : 0);
-
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
- if (execute_testcases(in_dir) == 0) {
+ if (in_dir) {
+
+ if (execute_testcases(in_dir) == 0) {
+
+ FATAL("could not read input testcases from %s", in_dir);
+
+ }
+
+ } else {
+
+ if (execute_testcases_filelist(in_filelist) == 0) {
- FATAL("could not read input testcases from %s", in_dir);
+ FATAL("could not read input testcases from %s", in_filelist);
+
+ }
}
@@ -1390,7 +1733,20 @@ 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);
- showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+#endif
+ showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+
+ } else {
+
+ showmap_run_target_nyx_mode(fsrv);
+
+ }
+
+#endif
tcnt = write_results_to_file(fsrv, out_file);
if (!quiet_mode) {
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index c0087f5f..e7442d1d 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -789,6 +789,7 @@ static void usage(u8 *argv0) {
"mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -845,7 +846,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
switch (opt) {
@@ -1003,6 +1004,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'H': /* Hang Mode */
/* Minimizes a testcase to the minimum that still times out */
@@ -1068,7 +1086,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+ fsrv->target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv->target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
signal(SIGALRM, kill_child);
@@ -1092,6 +1124,26 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv->nyx_mode) {
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv->nyx_use_tmp_workdir = true;
+ fsrv->nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1161,7 +1213,12 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz = map + sizeof(u32);
read_initial_file();
+
+#ifdef __linux__
+ if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
+#else
(void)check_binary_signatures(fsrv->target_path);
+#endif
if (!fsrv->qemu_mode && !unicorn_mode) {