aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-12-09 11:55:36 +0100
committerGitHub <noreply@github.com>2021-12-09 11:55:36 +0100
commit08ca4d54a55fe73e64a994c41a12af61f52e497e (patch)
tree2d0f060cf98afbe80f5bf810fd6b167a5152be81 /src
parent773baf9391ff5f1793deb7968366819e7fa07adc (diff)
parent4c6d94ea5f854071277ed9729de2d4ef7d07cc84 (diff)
downloadafl++-08ca4d54a55fe73e64a994c41a12af61f52e497e.tar.gz
Merge pull request #1101 from AFLplusplus/dev
Dev
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c48
-rw-r--r--src/afl-as.c7
-rw-r--r--src/afl-cc.c67
-rw-r--r--src/afl-common.c101
-rw-r--r--src/afl-forkserver.c62
-rw-r--r--src/afl-fuzz-bitmap.c29
-rw-r--r--src/afl-fuzz-cmplog.c2
-rw-r--r--src/afl-fuzz-extras.c2
-rw-r--r--src/afl-fuzz-init.c51
-rw-r--r--src/afl-fuzz-mutators.c5
-rw-r--r--src/afl-fuzz-one.c27
-rw-r--r--src/afl-fuzz-python.c2
-rw-r--r--src/afl-fuzz-queue.c93
-rw-r--r--src/afl-fuzz-redqueen.c367
-rw-r--r--src/afl-fuzz-run.c32
-rw-r--r--src/afl-fuzz-state.c2
-rw-r--r--src/afl-fuzz-stats.c74
-rw-r--r--src/afl-fuzz.c102
-rw-r--r--src/afl-gotcpu.c2
-rw-r--r--src/afl-ld-lto.c2
-rw-r--r--src/afl-performance.c8
-rw-r--r--src/afl-sharedmem.c2
-rw-r--r--src/afl-showmap.c81
-rw-r--r--src/afl-tmin.c47
24 files changed, 896 insertions, 319 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index e19df3ce..ac5a324c 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
A nifty utility that grabs an input file and takes a stab at explaining
its structure by observing how changes to it affect the execution path.
@@ -77,6 +77,7 @@ static volatile u8 stop_soon; /* Ctrl-C pressed? */
static u8 *target_path;
static u8 frida_mode;
static u8 qemu_mode;
+static u8 cs_mode;
static u32 map_size = MAP_SIZE;
static afl_forkserver_t fsrv = {0}; /* The forkserver */
@@ -120,6 +121,17 @@ static u8 count_class_lookup[256] = {
#undef TIMES8
#undef TIMES4
+static void kill_child() {
+
+ if (fsrv.child_pid > 0) {
+
+ kill(fsrv.child_pid, fsrv.kill_signal);
+ fsrv.child_pid = -1;
+
+ }
+
+}
+
static void classify_counts(u8 *mem) {
u32 i = map_size;
@@ -184,7 +196,7 @@ static void read_initial_file(void) {
if (st.st_size >= TMIN_MAX_FILE) {
- FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
+ FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024);
}
@@ -779,6 +791,8 @@ static void set_up_environment(char **argv) {
} else {
+ /* CoreSight mode uses the default behavior. */
+
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@@ -834,11 +848,17 @@ static void usage(u8 *argv0) {
" -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+ " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
" -O - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
- "mode)\n\n"
+ "mode)\n"
+#endif
+ "\n"
"Analysis settings:\n"
@@ -879,7 +899,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init(&fsrv);
- while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
switch (opt) {
@@ -978,13 +998,25 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'A': /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+ FATAL("-A option is not supported on this platform");
+#endif
+
+ if (cs_mode) { FATAL("Multiple -A options not supported"); }
+
+ cs_mode = 1;
+ fsrv.cs_mode = cs_mode;
+ break;
+
case 'O': /* FRIDA mode */
if (frida_mode) { FATAL("Multiple -O options not supported"); }
frida_mode = 1;
fsrv.frida_mode = frida_mode;
- setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+ setenv("AFL_FRIDA_INST_SEED", "1", 1);
break;
@@ -1053,6 +1085,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv.target_path = find_binary(argv[optind]);
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
+ signal(SIGALRM, kill_child);
if (qemu_mode) {
@@ -1068,6 +1101,10 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else if (cs_mode) {
+
+ use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
+
} else {
use_argv = argv + optind;
@@ -1093,6 +1130,7 @@ int main(int argc, char **argv_orig, char **envp) {
parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
read_initial_file();
+ (void)check_binary_signatures(fsrv.target_path);
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-as.c b/src/afl-as.c
index 7119d630..b644b82a 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
The sole purpose of this wrapper is to preprocess assembly files generated
by GCC / clang and inject the instrumentation bits included from afl-as.h. It
@@ -101,7 +101,7 @@ static void edit_params(int argc, char **argv) {
/* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
with the code generated by newer versions of clang that are hand-built
- by the user. See the thread here: http://goo.gl/HBWDtn.
+ by the user. See the thread here: https://goo.gl/HBWDtn.
To work around this, when using clang and running without AFL_AS
specified, we will actually call 'clang -c' instead of 'as -q' to
@@ -517,10 +517,11 @@ static void add_instrumentation(void) {
} else {
char modeline[100];
- snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
+ snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s",
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
+ getenv("AFL_USE_TSAN") ? ", TSAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "",
getenv("AFL_USE_LSAN") ? ", LSAN" : "");
diff --git a/src/afl-cc.c b/src/afl-cc.c
index e49addc4..1448d8ae 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -11,7 +11,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
*/
@@ -423,6 +423,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
cc_params[cc_par_cnt++] = fplugin_arg;
+ cc_params[cc_par_cnt++] = "-fno-if-conversion";
+ cc_params[cc_par_cnt++] = "-fno-if-conversion2";
}
@@ -553,7 +555,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (lto_mode && !have_c) {
- u8 *ld_path = strdup(AFL_REAL_LD);
+ u8 *ld_path = NULL;
+ if (getenv("AFL_REAL_LD")) { ld_path = strdup(getenv("AFL_REAL_LD")); }
if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); }
if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); }
#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12
@@ -564,22 +567,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
free(ld_path);
cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
-
- if (instrument_mode == INSTRUMENT_CFG ||
- instrument_mode == INSTRUMENT_PCGUARD)
- cc_params[cc_par_cnt++] = alloc_printf(
- "-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
- else
-
- cc_params[cc_par_cnt++] = alloc_printf(
- "-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
cc_params[cc_par_cnt++] = lto_flag;
} else {
if (instrument_mode == INSTRUMENT_PCGUARD) {
-#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
+#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR >= 1)
#if defined __ANDROID__ || ANDROID
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -735,6 +731,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
+ 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=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
(strncmp(cur, "sanitize-coverage-allow",
@@ -847,6 +851,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-fsanitize=undefined";
cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error";
cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all";
+ cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
+
+ }
+
+ if (getenv("AFL_USE_TSAN")) {
+
+ cc_params[cc_par_cnt++] = "-fsanitize=thread";
+ cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
}
@@ -1007,7 +1019,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
// prevent unnecessary build errors
- cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
+ if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) {
+
+ cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
+
+ }
if (preprocessor_only || have_c) {
@@ -1152,7 +1168,7 @@ int main(int argc, char **argv, char **envp) {
}
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) {
@@ -1181,7 +1197,7 @@ int main(int argc, char **argv, char **envp) {
}
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
if (strncmp(callname, "afl-clang-fast", 14) == 0) {
@@ -1709,8 +1725,8 @@ int main(int argc, char **argv, char **envp) {
compiler_mode == LTO ? " [SELECTED]" : "",
have_llvm ? "AVAILABLE" : "unavailable!",
compiler_mode == LLVM ? " [SELECTED]" : "",
- LLVM_MAJOR > 6 ? "DEFAULT" : " ",
- LLVM_MAJOR > 6 ? " " : "DEFAULT",
+ LLVM_MAJOR >= 7 ? "DEFAULT" : " ",
+ LLVM_MAJOR >= 7 ? " " : "DEFAULT",
have_gcc_plugin ? "AVAILABLE" : "unavailable!",
compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "",
have_gcc ? "AVAILABLE" : "unavailable!",
@@ -1800,6 +1816,7 @@ int main(int argc, char **argv, char **envp) {
" AFL_USE_CFISAN: activate control flow sanitizer\n"
" AFL_USE_MSAN: activate memory sanitizer\n"
" AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
+ " AFL_USE_TSAN: activate thread sanitizer\n"
" AFL_USE_LSAN: activate leak-checker sanitizer\n");
if (have_gcc_plugin)
@@ -1810,12 +1827,12 @@ int main(int argc, char **argv, char **envp) {
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
"filename\n");
-#if LLVM_MAJOR < 9
+#if LLVM_MAJOR >= 9
#define COUNTER_BEHAVIOUR \
- " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
+ " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
#else
#define COUNTER_BEHAVIOUR \
- " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
+ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
#endif
if (have_llvm)
SAYF(
@@ -1889,7 +1906,7 @@ int main(int argc, char **argv, char **envp) {
"consult the README.md, especially section 3.1 about instrumenting "
"targets.\n\n");
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
if (have_lto)
SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO);
if (have_llvm)
@@ -1951,9 +1968,7 @@ int main(int argc, char **argv, char **envp) {
if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) {
-#if LLVM_MAJOR <= 6
- instrument_mode = INSTRUMENT_AFL;
-#else
+#if LLVM_MAJOR >= 7
#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
if (have_instr_env) {
@@ -1968,6 +1983,8 @@ int main(int argc, char **argv, char **envp) {
#endif
instrument_mode = INSTRUMENT_PCGUARD;
+#else
+ instrument_mode = INSTRUMENT_AFL;
#endif
}
@@ -2034,7 +2051,7 @@ int main(int argc, char **argv, char **envp) {
if ((isatty(2) && !be_quiet) || debug) {
SAYF(cCYA
- "afl-cc " VERSION cRST
+ "afl-cc" VERSION cRST
" by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n",
compiler_mode_string[compiler_mode], ptr);
diff --git a/src/afl-common.c b/src/afl-common.c
index 9ca2b3e8..6c2d0753 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
Gather some functions common to multiple executables
@@ -25,8 +25,12 @@
#include <stdlib.h>
#include <stdio.h>
+#define _GNU_SOURCE
+#define __USE_GNU
+#include <string.h>
#include <strings.h>
#include <math.h>
+#include <sys/mman.h>
#include "debug.h"
#include "alloc-inl.h"
@@ -51,6 +55,66 @@ u8 last_intr = 0;
#define AFL_PATH "/usr/local/lib/afl/"
#endif
+u32 check_binary_signatures(u8 *fn) {
+
+ int ret = 0, fd = open(fn, O_RDONLY);
+ if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
+ struct stat st;
+ if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
+ u32 f_len = st.st_size;
+ u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
+ close(fd);
+
+ if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
+
+ if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); }
+ setenv(PERSIST_ENV_VAR, "1", 1);
+ ret = 1;
+
+ } else if (getenv("AFL_PERSISTENT")) {
+
+ if (!be_quiet) {
+
+ WARNF("AFL_PERSISTENT is no longer supported and may misbehave!");
+
+ }
+
+ } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
+
+ if (!be_quiet) {
+
+ OKF("FRIDA Persistent mode configuration options detected.");
+
+ }
+
+ setenv(PERSIST_ENV_VAR, "1", 1);
+ ret = 1;
+
+ }
+
+ if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+
+ if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); }
+ setenv(DEFER_ENV_VAR, "1", 1);
+ ret += 2;
+
+ } else if (getenv("AFL_DEFER_FORKSRV")) {
+
+ if (!be_quiet) {
+
+ WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!");
+
+ }
+
+ }
+
+ if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
+
+ return ret;
+
+}
+
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
u32 i = 0;
@@ -140,6 +204,35 @@ void argv_cpy_free(char **argv) {
}
+/* Rewrite argv for CoreSight process tracer. */
+
+char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
+
+ if (unlikely(getenv("AFL_CS_CUSTOM_BIN"))) {
+
+ WARNF(
+ "AFL_CS_CUSTOM_BIN is enabled. "
+ "You must run your target under afl-cs-proxy on your own!");
+ return argv;
+
+ }
+
+ char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
+ if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
+
+ memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
+ new_argv[argc + 3] = NULL;
+
+ new_argv[2] = *target_path_p;
+ new_argv[1] = "--";
+
+ /* Now we need to actually find the cs-proxy binary to put in argv[0]. */
+
+ *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-cs-proxy");
+ return new_argv;
+
+}
+
/* Rewrite argv for QEMU. */
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
@@ -153,11 +246,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
}
- char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
+ char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
- new_argv[argc + 3] = NULL;
new_argv[2] = *target_path_p;
new_argv[1] = "--";
@@ -173,11 +265,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
- char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
+ char **new_argv = ck_alloc(sizeof(char *) * (argc + 2));
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
- new_argv[argc + 2] = NULL;
new_argv[1] = *target_path_p;
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c8c94c08..b871ea8c 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -19,7 +19,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
Shared code that implements a forkserver. This is used by the fuzzer
as well the other components like afl-tmin.
@@ -342,6 +342,16 @@ static void report_error_and_exit(int error) {
"the fuzzing target reports that the mmap() call to the shared "
"memory failed.");
break;
+ case FS_ERROR_OLD_CMPLOG:
+ FATAL(
+ "the -c cmplog target was instrumented with an too old afl++ "
+ "version, you need to recompile it.");
+ break;
+ case FS_ERROR_OLD_CMPLOG_QEMU:
+ FATAL(
+ "The AFL++ QEMU/FRIDA loaders are from an older version, for -c you "
+ "need to recompile it.\n");
+ break;
default:
FATAL("unknown error code %d from fuzzing target!", error);
@@ -351,7 +361,7 @@ static void report_error_and_exit(int error) {
/* Spins up fork server. The idea is explained here:
- http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
+ https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
In essence, the instrumentation allows us to skip execve(), and just keep
cloning a stopped child. So, we just execute once, and then send commands
@@ -603,19 +613,31 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* Wait for the fork server to come up, but don't wait too long. */
rlen = 0;
- if (fsrv->exec_tmout) {
+ if (fsrv->init_tmout) {
u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
stop_soon_p);
if (!time_ms) {
- kill(fsrv->fsrv_pid, fsrv->kill_signal);
+ s32 tmp_pid = fsrv->fsrv_pid;
+ if (tmp_pid > 0) {
+
+ kill(tmp_pid, fsrv->kill_signal);
+ fsrv->fsrv_pid = -1;
+
+ }
} else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1;
- kill(fsrv->fsrv_pid, fsrv->kill_signal);
+ s32 tmp_pid = fsrv->fsrv_pid;
+ if (tmp_pid > 0) {
+
+ kill(tmp_pid, fsrv->kill_signal);
+ fsrv->fsrv_pid = -1;
+
+ }
} else {
@@ -651,6 +673,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff);
+ if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
+
+ if (fsrv->qemu_mode || fsrv->frida_mode) {
+
+ report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
+
+ } else {
+
+ report_error_and_exit(FS_ERROR_OLD_CMPLOG);
+
+ }
+
+ }
+
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
fsrv->snapshot = 1;
@@ -905,8 +941,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
MSG_ULIMIT_USAGE
" /path/to/fuzzed_app )\n\n"
- " Tip: you can use http://jwilk.net/software/recidivm to "
- "quickly\n"
+ " Tip: you can use https://jwilk.net/software/recidivm to\n"
" estimate the required amount of virtual memory for the "
"binary.\n\n"
@@ -1005,7 +1040,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
MSG_ULIMIT_USAGE
" /path/to/fuzzed_app )\n\n"
- " Tip: you can use http://jwilk.net/software/recidivm to quickly\n"
+ " Tip: you can use https://jwilk.net/software/recidivm to\n"
" estimate the required amount of virtual memory for the "
"binary.\n\n"
@@ -1248,7 +1283,14 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */
- kill(fsrv->child_pid, fsrv->kill_signal);
+ s32 tmp_pid = fsrv->child_pid;
+ if (tmp_pid > 0) {
+
+ kill(tmp_pid, fsrv->kill_signal);
+ fsrv->child_pid = -1;
+
+ }
+
fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }
@@ -1282,7 +1324,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
- if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; }
+ if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1; }
fsrv->total_execs++;
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 0ae4d607..fa413dcf 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -58,7 +58,7 @@ void write_bitmap(afl_state_t *afl) {
u32 count_bits(afl_state_t *afl, u8 *mem) {
u32 *ptr = (u32 *)mem;
- u32 i = (afl->fsrv.map_size >> 2);
+ u32 i = ((afl->fsrv.real_map_size + 3) >> 2);
u32 ret = 0;
while (i--) {
@@ -68,7 +68,7 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
/* This gets called on the inverse, virgin bitmap; optimize for sparse
data. */
- if (v == 0xffffffff) {
+ if (likely(v == 0xffffffff)) {
ret += 32;
continue;
@@ -92,14 +92,14 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
u32 count_bytes(afl_state_t *afl, u8 *mem) {
u32 *ptr = (u32 *)mem;
- u32 i = (afl->fsrv.map_size >> 2);
+ u32 i = ((afl->fsrv.real_map_size + 3) >> 2);
u32 ret = 0;
while (i--) {
u32 v = *(ptr++);
- if (!v) { continue; }
+ if (likely(!v)) { continue; }
if (v & 0x000000ffU) { ++ret; }
if (v & 0x0000ff00U) { ++ret; }
if (v & 0x00ff0000U) { ++ret; }
@@ -117,7 +117,7 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
u32 *ptr = (u32 *)mem;
- u32 i = (afl->fsrv.map_size >> 2);
+ u32 i = ((afl->fsrv.real_map_size + 3) >> 2);
u32 ret = 0;
while (i--) {
@@ -127,7 +127,7 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
/* This is called on the virgin bitmap, so optimize for the most likely
case. */
- if (v == 0xffffffffU) { continue; }
+ if (likely(v == 0xffffffffU)) { continue; }
if ((v & 0x000000ffU) != 0x000000ffU) { ++ret; }
if ((v & 0x0000ff00U) != 0x0000ff00U) { ++ret; }
if ((v & 0x00ff0000U) != 0x00ff0000U) { ++ret; }
@@ -216,14 +216,14 @@ inline u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
u64 *current = (u64 *)afl->fsrv.trace_bits;
u64 *virgin = (u64 *)virgin_map;
- u32 i = (afl->fsrv.map_size >> 3);
+ u32 i = ((afl->fsrv.real_map_size + 7) >> 3);
#else
u32 *current = (u32 *)afl->fsrv.trace_bits;
u32 *virgin = (u32 *)virgin_map;
- u32 i = (afl->fsrv.map_size >> 2);
+ u32 i = ((afl->fsrv.real_map_size + 3) >> 2);
#endif /* ^WORD_SIZE_64 */
@@ -317,8 +317,9 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
}
- sprintf(ret + strlen(ret), ",time:%llu",
- get_cur_time() + afl->prev_run_time - afl->start_time);
+ sprintf(ret + strlen(ret), ",time:%llu,execs:%llu",
+ get_cur_time() + afl->prev_run_time - afl->start_time,
+ afl->fsrv.total_execs);
if (afl->current_custom_fuzz &&
afl->current_custom_fuzz->afl_custom_describe) {
@@ -451,14 +452,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) { return 0; }
+ u8 fn[PATH_MAX];
u8 *queue_fn = "";
- u8 new_bits = '\0';
+ u8 new_bits = 0, keeping = 0, res, classified = 0;
s32 fd;
- u8 keeping = 0, res, classified = 0;
u64 cksum = 0;
- u8 fn[PATH_MAX];
-
/* Update path frequency. */
/* Generating a hash on every input is super expensive. Bad idea and should
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index c2e9c80f..6fc926f0 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -17,7 +17,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
Shared code to handle the shared memory. This is used by the fuzzer
as well the other components like afl-tmin, afl-showmap, etc...
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 584241d4..0f0fe331 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 9bb25785..4c030c0a 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -974,8 +974,7 @@ void perform_dry_run(afl_state_t *afl) {
MSG_ULIMIT_USAGE
" /path/to/binary [...] <testcase )\n\n"
- " Tip: you can use http://jwilk.net/software/recidivm to "
- "quickly\n"
+ " Tip: you can use https://jwilk.net/software/recidivm to\n"
" estimate the required amount of virtual memory for the "
"binary. Also,\n"
" if you are using ASAN, set '-m 0'.\n\n"
@@ -1325,8 +1324,8 @@ void pivot_inputs(afl_state_t *afl) {
}
- nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id,
- use_name);
+ nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
+ afl->out_dir, id, afl->fsrv.total_execs, use_name);
#else
@@ -2645,6 +2644,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
(afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
+ (afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) ||
afl->non_instrumented_mode) {
return;
@@ -2721,7 +2721,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
#endif /* ^!__APPLE__ */
if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
- !afl->non_instrumented_mode &&
+ !afl->fsrv.cs_mode && !afl->non_instrumented_mode &&
!memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST
@@ -2752,7 +2752,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
- if ((afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
+ if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST
@@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
-/* Trim and possibly create a banner for the run. */
-
-void fix_up_banner(afl_state_t *afl, u8 *name) {
-
- if (!afl->use_banner) {
-
- if (afl->sync_id) {
-
- afl->use_banner = afl->sync_id;
-
- } else {
-
- u8 *trim = strrchr(name, '/');
- if (!trim) {
-
- afl->use_banner = name;
-
- } else {
-
- afl->use_banner = trim + 1;
-
- }
-
- }
-
- }
-
- if (strlen(afl->use_banner) > 32) {
-
- u8 *tmp = ck_alloc(36);
- sprintf(tmp, "%.32s...", afl->use_banner);
- afl->use_banner = tmp;
-
- }
-
-}
-
/* Check if we're on TTY. */
void check_if_tty(afl_state_t *afl) {
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 5332b9fe..e0dfd6b0 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -16,7 +16,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -255,6 +255,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
if (!mutator->afl_custom_init_trim) {
+ notrim = 1;
ACTF("optional symbol 'afl_custom_init_trim' not found.");
}
@@ -263,6 +264,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
if (!mutator->afl_custom_trim) {
+ notrim = 1;
ACTF("optional symbol 'afl_custom_trim' not found.");
}
@@ -271,6 +273,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
if (!mutator->afl_custom_post_trim) {
+ notrim = 1;
ACTF("optional symbol 'afl_custom_post_trim' not found.");
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 17749601..f4d3b77f 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -448,11 +448,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
ACTF(
"Fuzzing test case #%u (%u total, %llu uniq crashes found, "
- "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
+ "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
afl->current_entry, afl->queued_paths, afl->unique_crashes,
afl->queue_cur->perf_score, afl->queue_cur->exec_us,
likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
- afl->queue_cur->bitmap_size);
+ afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii);
fflush(stdout);
}
@@ -2003,11 +2003,16 @@ havoc_stage:
where we take the input file and make random stacked tweaks. */
#define MAX_HAVOC_ENTRY 59 /* 55 to 60 */
+#define MUTATE_ASCII_DICT 64
u32 r_max, r;
r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
- (afl->a_extras_cnt ? 4 : 0);
+ (afl->a_extras_cnt
+ ? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)
+ ? MUTATE_ASCII_DICT
+ : 4)
+ : 0);
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
@@ -2592,7 +2597,15 @@ havoc_stage:
if (afl->a_extras_cnt) {
- if (r < 2) {
+ u32 r_cmp = 2;
+
+ if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) {
+
+ r_cmp = MUTATE_ASCII_DICT >> 1;
+
+ }
+
+ if (r < r_cmp) {
/* Use the dictionary. */
@@ -2612,7 +2625,7 @@ havoc_stage:
break;
- } else if (r < 4) {
+ } else if (r < (r_cmp << 1)) {
u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len;
@@ -2641,7 +2654,7 @@ havoc_stage:
} else {
- r -= 4;
+ r -= (r_cmp << 1);
}
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 065977c0..6484768b 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 16af2c6b..1523d556 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -14,7 +14,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -315,7 +315,96 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
}
-/* check if ascii or UTF-8 */
+/* check if pointer is ascii or UTF-8 */
+
+u8 check_if_text_buf(u8 *buf, u32 len) {
+
+ u32 offset = 0, ascii = 0, utf8 = 0;
+
+ while (offset < len) {
+
+ // ASCII: <= 0x7F to allow ASCII control characters
+ if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A ||
+ buf[offset + 0] == 0x0D ||
+ (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) {
+
+ offset++;
+ utf8++;
+ ascii++;
+ continue;
+
+ }
+
+ if (isascii((int)buf[offset]) || isprint((int)buf[offset])) {
+
+ ascii++;
+ // we continue though as it can also be a valid utf8
+
+ }
+
+ // non-overlong 2-byte
+ if (len - offset > 1 &&
+ ((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
+
+ offset += 2;
+ utf8++;
+ continue;
+
+ }
+
+ // excluding overlongs
+ if ((len - offset > 2) &&
+ ((buf[offset + 0] == 0xE0 &&
+ (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] &&
+ buf[offset + 2] <= 0xBF)) || // straight 3-byte
+ (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) ||
+ buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] &&
+ buf[offset + 2] <= 0xBF)) || // excluding surrogates
+ (buf[offset + 0] == 0xED &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF)))) {
+
+ offset += 3;
+ utf8++;
+ continue;
+
+ }
+
+ // planes 1-3
+ if ((len - offset > 3) &&
+ ((buf[offset + 0] == 0xF0 &&
+ (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] &&
+ buf[offset + 3] <= 0xBF)) || // planes 4-15
+ ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16
+ (buf[offset + 0] == 0xF4 &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)))) {
+
+ offset += 4;
+ utf8++;
+ continue;
+
+ }
+
+ offset++;
+
+ }
+
+ return (utf8 > ascii ? utf8 : ascii);
+
+}
+
+/* check if queue entry is ascii or UTF-8 */
static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 268f726c..0a6e5eee 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -17,7 +17,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
Shared code to handle the shared memory. This is used by the fuzzer
as well the other components like afl-tmin, afl-showmap, etc...
@@ -45,6 +45,23 @@ enum {
};
+// add to dictionary enum
+// DEFAULT = 1, notTXT = 2, FOUND = 4, notSAME = 8
+enum {
+
+ DICT_ADD_NEVER = 0,
+ DICT_ADD_NOTFOUND_SAME_TXT = 1,
+ DICT_ADD_NOTFOUND_SAME = 3,
+ DICT_ADD_FOUND_SAME_TXT = 5,
+ DICT_ADD_FOUND_SAME = 7,
+ DICT_ADD_NOTFOUND_TXT = 9,
+ DICT_ADD_NOTFOUND = 11,
+ DICT_ADD_FOUND_TXT = 13,
+ DICT_ADD_FOUND = 15,
+ DICT_ADD_ANY = DICT_ADD_FOUND
+
+};
+
// CMPLOG LVL
enum {
@@ -54,6 +71,8 @@ enum {
};
+#define DICT_ADD_STRATEGY DICT_ADD_FOUND_SAME
+
struct range {
u32 start;
@@ -64,6 +83,10 @@ struct range {
};
+static u32 hshape;
+static u64 screen_update;
+static u64 last_update;
+
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
struct range *r = ck_alloc_nozero(sizeof(struct range));
@@ -252,7 +275,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u64 start_time = get_cur_time();
#endif
- u32 screen_update;
u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@@ -261,24 +283,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
afl->stage_max = (len << 1);
afl->stage_cur = 0;
- if (likely(afl->queue_cur->exec_us)) {
-
- if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
-
- screen_update = 100000 / afl->queue_cur->exec_us;
-
- } else {
-
- screen_update = 1;
-
- }
-
- } else {
-
- screen_update = 100000;
-
- }
-
// in colorization we do not classify counts, hence we have to calculate
// the original checksum.
if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
@@ -348,7 +352,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
}
- if (++afl->stage_cur % screen_update) { show_stats(afl); };
+ if (++afl->stage_cur % screen_update == 0) { show_stats(afl); };
}
@@ -440,10 +444,10 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
fprintf(
f,
"Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu "
- "taint=%u\n",
+ "taint=%u ascii=%u auto_extra_before=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time,
afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt,
- positions);
+ positions, afl->queue_cur->is_ascii ? 1 : 0, afl->a_extras_cnt);
#ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); }
@@ -759,11 +763,18 @@ 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) {
+
+ show_stats(afl);
+ last_update = afl->fsrv.total_execs;
+
+ }
+
// fprintf(stderr,
// "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
// "taint_len=%u shape=%u attr=%u\n",
// o_pattern, pattern, repl, changed_val, idx, taint_len,
- // h->shape + 1, attr);
+ // hshape, attr);
//#ifdef CMPLOG_SOLVE_TRANSFORM
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
@@ -845,7 +856,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 b_val, o_b_val, mask;
u8 bytes;
- switch (SHAPE_BYTES(h->shape)) {
+ switch (hshape) {
case 0:
case 1:
@@ -924,7 +935,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
s64 diff = pattern - b_val;
s64 o_diff = o_pattern - o_b_val;
/* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
- h->shape + 1, o_pattern, o_b_val, o_diff);
+ hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
b_val, diff); */
if (diff == o_diff && diff) {
@@ -953,7 +964,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
s64 o_diff = o_pattern ^ o_b_val;
/* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
@@ -1002,7 +1013,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
/* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
@@ -1051,7 +1062,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
/* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
@@ -1089,7 +1100,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if ((lvl & LVL1) || attr >= IS_FP_MOD) {
- if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
+ if (hshape >= 8 && *status != 1) {
// if (its_len >= 8)
// fprintf(stderr,
@@ -1132,7 +1143,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) {
+ if (hshape >= 4 && *status != 1) {
// if (its_len >= 4 && (attr <= 1 || attr >= 8))
// fprintf(stderr,
@@ -1173,7 +1184,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) {
+ if (hshape >= 2 && *status != 1) {
if (its_len >= 2 &&
((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) ||
@@ -1244,11 +1255,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
-
- return 0;
-
- }
+ if (!(attr & (IS_GREATER | IS_LESSER)) || hshape < 4) { return 0; }
// transform >= to < and <= to >
if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
@@ -1272,7 +1279,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (attr & IS_GREATER) {
- if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
+ if (hshape == 4 && its_len >= 4) {
float *f = (float *)&repl;
float g = *f;
@@ -1280,7 +1287,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 *r = (u32 *)&g;
repl_new = (u32)*r;
- } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) {
+ } else if (hshape == 8 && its_len >= 8) {
double *f = (double *)&repl;
double g = *f;
@@ -1307,7 +1314,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} else {
- if (SHAPE_BYTES(h->shape) == 4) {
+ if (hshape == 4) {
float *f = (float *)&repl;
float g = *f;
@@ -1315,7 +1322,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 *r = (u32 *)&g;
repl_new = (u32)*r;
- } else if (SHAPE_BYTES(h->shape) == 8) {
+ } else if (hshape == 8) {
double *f = (double *)&repl;
double g = *f;
@@ -1342,7 +1349,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
// transform double to float, llvm likes to do that internally ...
- if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) {
+ if (hshape == 8 && its_len >= 4) {
double *f = (double *)&repl;
float g = (float)*f;
@@ -1353,7 +1360,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
#endif
changed_val = repl_new;
- h->shape = 3; // modify shape
+ hshape = 4; // modify shape
// fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
@@ -1361,12 +1368,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
- h->shape = 7; // recover shape
+ hshape = 8; // recover shape
return 1;
}
- h->shape = 7; // recover shape
+ hshape = 8; // recover shape
}
@@ -1421,6 +1428,13 @@ 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) {
+
+ show_stats(afl);
+ last_update = afl->fsrv.total_execs;
+
+ }
+
u8 *ptr = (u8 *)&buf[idx];
u8 *o_ptr = (u8 *)&orig_buf[idx];
u8 *p = (u8 *)&pattern;
@@ -1428,52 +1442,51 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u8 *r = (u8 *)&repl;
u8 backup[16];
u32 its_len = MIN(len - idx, taint_len);
- u32 shape = h->shape + 1;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
size_t off = 0;
#else
- size_t off = 16 - shape;
+ size_t off = 16 - hshape;
#endif
- if (its_len >= shape) {
+ if (its_len >= hshape) {
#ifdef _DEBUG
fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ",
- its_len, shape, len, idx, attr, off, do_reverse);
+ its_len, hshape, len, idx, attr, off, do_reverse);
u32 i;
u8 *o_r = (u8 *)&changed_val;
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", ptr[i]);
fprintf(stderr, "==");
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", p[off + i]);
fprintf(stderr, " ");
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", o_ptr[i]);
fprintf(stderr, "==");
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", o_p[off + i]);
fprintf(stderr, " <= ");
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", r[off + i]);
fprintf(stderr, "<-");
- for (i = 0; i < shape; i++)
+ for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", o_r[off + i]);
fprintf(stderr, "\n");
#endif
- if (!memcmp(ptr, p + off, shape) && !memcmp(o_ptr, o_p + off, shape)) {
+ if (!memcmp(ptr, p + off, hshape) && !memcmp(o_ptr, o_p + off, hshape)) {
- memcpy(backup, ptr, shape);
- memcpy(ptr, r + off, shape);
+ memcpy(backup, ptr, hshape);
+ memcpy(ptr, r + off, hshape);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
- if (*status == 1) { memcpy(cbuf + idx, r, shape); }
+ if (*status == 1) { memcpy(cbuf + idx, r, hshape); }
#endif
- memcpy(ptr, backup, shape);
+ memcpy(ptr, backup, hshape);
#ifdef _DEBUG
fprintf(stderr, "Status=%u\n", *status);
@@ -1485,10 +1498,10 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encodingN(
- afl, h, SWAPN(pattern, (shape << 3)), SWAPN(repl, (shape << 3)),
- SWAPN(o_pattern, (shape << 3)), SWAPN(changed_val, (shape << 3)),
- attr, idx, taint_len, orig_buf, buf, cbuf, len, 0, lvl,
- status))) {
+ afl, h, SWAPN(pattern, (hshape << 3)), SWAPN(repl, (hshape << 3)),
+ SWAPN(o_pattern, (hshape << 3)),
+ SWAPN(changed_val, (hshape << 3)), attr, idx, taint_len, orig_buf,
+ buf, cbuf, len, 0, lvl, status))) {
return 1;
@@ -1615,6 +1628,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u8 s_v0_inc = 1, s_v1_inc = 1;
u8 s_v0_dec = 1, s_v1_dec = 1;
+ hshape = SHAPE_BYTES(h->shape);
+
if (h->hits > CMP_MAP_H) {
loggeds = CMP_MAP_H;
@@ -1626,7 +1641,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
}
#ifdef WORD_SIZE_64
- switch (SHAPE_BYTES(h->shape)) {
+ switch (hshape) {
case 1:
case 2:
@@ -1669,7 +1684,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
for (j = 0; j < i; ++j) {
if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
- afl->shm.cmp_map->log[key][i].v1 == o->v1) {
+ afl->shm.cmp_map->log[key][j].v1 == o->v1) {
goto cmp_fuzz_next_iter;
@@ -1679,8 +1694,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
- orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute,
- SHAPE_BYTES(h->shape));
+ orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
#endif
t = taint;
@@ -1830,27 +1844,41 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
"END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u "
"isN=%u size=%u\n",
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one,
- is_n, SHAPE_BYTES(h->shape));
+ is_n, hshape);
#endif
- // If failed, add to dictionary
- if (!found_one) {
+ // we only learn 16 bit +
+ if (hshape > 1) {
- if (afl->pass_stats[key].total == 0) {
+ if (!found_one || afl->queue_cur->is_ascii) {
#ifdef WORD_SIZE_64
if (unlikely(is_n)) {
- try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
- try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
+ if (!found_one ||
+ check_if_text_buf((u8 *)&s128_v0, SHAPE_BYTES(h->shape)) ==
+ SHAPE_BYTES(h->shape))
+ try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
+ if (!found_one ||
+ check_if_text_buf((u8 *)&s128_v1, SHAPE_BYTES(h->shape)) ==
+ SHAPE_BYTES(h->shape))
+ try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
} else
#endif
{
- try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
- try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
+ if (!memcmp((u8 *)&o->v0, (u8 *)&orig_o->v0, SHAPE_BYTES(h->shape)) &&
+ (!found_one ||
+ check_if_text_buf((u8 *)&o->v0, SHAPE_BYTES(h->shape)) ==
+ SHAPE_BYTES(h->shape)))
+ try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
+ if (!memcmp((u8 *)&o->v1, (u8 *)&orig_o->v1, SHAPE_BYTES(h->shape)) &&
+ (!found_one ||
+ check_if_text_buf((u8 *)&o->v1, SHAPE_BYTES(h->shape)) ==
+ SHAPE_BYTES(h->shape)))
+ try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
}
@@ -1882,8 +1910,9 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
}
-static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
- u8 *o_pattern, u8 *changed_val, u8 plen, u32 idx,
+static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
+ struct cmpfn_operands *o,
+ struct cmpfn_operands *orig_o, u32 idx,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 lvl, u8 *status) {
@@ -1894,9 +1923,60 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
// (void)(changed_val);
//#endif
+ if (afl->fsrv.total_execs - last_update > screen_update) {
+
+ show_stats(afl);
+ last_update = afl->fsrv.total_execs;
+
+ }
+
+ u8 *pattern, *repl, *o_pattern, *changed_val;
+ u8 l0, l1, ol0, ol1;
+
+ if (entry == 0) {
+
+ pattern = o->v0;
+ repl = o->v1;
+ o_pattern = orig_o->v0;
+ changed_val = orig_o->v1;
+ l0 = o->v0_len;
+ ol0 = orig_o->v0_len;
+ l1 = o->v1_len;
+ ol1 = orig_o->v1_len;
+
+ } else {
+
+ pattern = o->v1;
+ repl = o->v0;
+ o_pattern = orig_o->v1;
+ changed_val = orig_o->v0;
+ l0 = o->v1_len;
+ ol0 = orig_o->v1_len;
+ l1 = o->v0_len;
+ ol1 = orig_o->v0_len;
+
+ }
+
+ if (l0 >= 0x80 || ol0 >= 0x80) {
+
+ l0 -= 0x80;
+ l1 -= 0x80;
+ ol0 -= 0x80;
+ ol1 -= 0x80;
+
+ }
+
+ if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
+ ol0 > 31 || ol1 > 31) {
+
+ l0 = l1 = ol0 = ol1 = hshape;
+
+ }
+
+ u8 lmax = MAX(l0, ol0);
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
- u32 its_len = MIN((u32)plen, len - idx);
+ u32 its_len = MIN(MIN(lmax, hshape), len - idx);
its_len = MIN(its_len, taint_len);
u32 saved_its_len = its_len;
@@ -1912,7 +1992,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
(void)(j);
#ifdef _DEBUG
- fprintf(stderr, "RTN T idx=%u lvl=%02x ", idx, lvl);
+ fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
+ o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_buf[idx + j]);
fprintf(stderr, " -> ");
@@ -1972,10 +2053,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- //#ifdef CMPLOG_SOLVE_TRANSFORM
-
if (*status == 1) return 0;
+ // transform solving
+
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
@@ -2322,6 +2403,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 i, j, idx, have_taint = 1, taint_len, loggeds;
u8 status = 0, found_one = 0;
+ hshape = SHAPE_BYTES(h->shape);
+
if (h->hits > CMP_MAP_RTN_H) {
loggeds = CMP_MAP_RTN_H;
@@ -2353,18 +2436,22 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
}
/*
- struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
- fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits,
- h->id, h->shape, h->attribute);
- for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]);
- fprintf(stderr, " v1=");
- for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]);
- fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=",
- hh->hits, hh->id, hh->shape, hh->attribute);
- for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]);
- fprintf(stderr, " o1=");
- for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]);
- fprintf(stderr, "\n");
+ struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
+ fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
+ hshape, h->attribute);
+ for (j = 0; j < 8; j++)
+ fprintf(stderr, "%02x", o->v0[j]);
+ fprintf(stderr, " v1=");
+ for (j = 0; j < 8; j++)
+ fprintf(stderr, "%02x", o->v1[j]);
+ fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
+ hh->id, hshape, hh->attribute);
+ for (j = 0; j < 8; j++)
+ fprintf(stderr, "%02x", orig_o->v0[j]);
+ fprintf(stderr, " o1=");
+ for (j = 0; j < 8; j++)
+ fprintf(stderr, "%02x", orig_o->v1[j]);
+ fprintf(stderr, "\n");
*/
t = taint;
@@ -2400,25 +2487,24 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG
int w;
- fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx,
- SHAPE_BYTES(h->shape));
- for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape);
+ for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", orig_o->v0[w]);
fprintf(stderr, " v0=");
- for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", o->v0[w]);
fprintf(stderr, " o1=");
- for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", orig_o->v1[w]);
fprintf(stderr, " v1=");
- for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+ for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", o->v1[w]);
fprintf(stderr, "\n");
#endif
- if (unlikely(rtn_extend_encoding(
- afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape),
- idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
+ if (unlikely(rtn_extend_encoding(afl, 0, o, orig_o, idx, taint_len,
+ orig_buf, buf, cbuf, len, lvl,
+ &status))) {
return 1;
@@ -2433,9 +2519,9 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
status = 0;
- if (unlikely(rtn_extend_encoding(
- afl, o->v1, o->v0, orig_o->v1, orig_o->v0, SHAPE_BYTES(h->shape),
- idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
+ if (unlikely(rtn_extend_encoding(afl, 1, o, orig_o, idx, taint_len,
+ orig_buf, buf, cbuf, len, lvl,
+ &status))) {
return 1;
@@ -2450,16 +2536,42 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
}
- // If failed, add to dictionary
- if (!found_one && (lvl & LVL1)) {
+ // if (unlikely(!afl->pass_stats[key].total)) {
+
+ if ((!found_one && (lvl & LVL1)) || afl->queue_cur->is_ascii) {
+
+ // if (unlikely(!afl->pass_stats[key].total)) {
+
+ u32 shape_len = SHAPE_BYTES(h->shape);
+ u32 v0_len = shape_len, v1_len = shape_len;
+ if (afl->queue_cur->is_ascii ||
+ check_if_text_buf((u8 *)&o->v0, shape_len) == shape_len) {
+
+ if (strlen(o->v0)) v0_len = strlen(o->v0);
+
+ }
- if (unlikely(!afl->pass_stats[key].total)) {
+ if (afl->queue_cur->is_ascii ||
+ check_if_text_buf((u8 *)&o->v1, shape_len) == shape_len) {
- maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape));
- maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape));
+ if (strlen(o->v1)) v1_len = strlen(o->v1);
}
+ // fprintf(stderr, "SHOULD: found:%u ascii:%u text?%u:%u %u:%s %u:%s \n",
+ // found_one, afl->queue_cur->is_ascii, check_if_text_buf((u8 *)&o->v0,
+ // shape_len), check_if_text_buf((u8 *)&o->v1, shape_len), v0_len,
+ // o->v0, v1_len, o->v1);
+
+ if (!memcmp(o->v0, orig_o->v0, v0_len) ||
+ (!found_one || check_if_text_buf((u8 *)&o->v0, v0_len) == v0_len))
+ maybe_add_auto(afl, o->v0, v0_len);
+ if (!memcmp(o->v1, orig_o->v1, v1_len) ||
+ (!found_one || check_if_text_buf((u8 *)&o->v1, v1_len) == v1_len))
+ maybe_add_auto(afl, o->v1, v1_len);
+
+ //}
+
}
rtn_fuzz_next_iter:
@@ -2492,6 +2604,23 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
struct tainted *taint = NULL;
+ if (likely(afl->queue_cur->exec_us)) {
+
+ if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
+
+ screen_update = 100000 / afl->queue_cur->exec_us;
+
+ } else {
+
+ screen_update = 1;
+
+ }
+
+ } else {
+
+ screen_update = 100000;
+
+ }
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
@@ -2592,8 +2721,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
- u64 screen_update = 100000 / afl->queue_cur->exec_us,
- execs = afl->fsrv.total_execs;
afl->stage_name = "input-to-state";
afl->stage_short = "its";
@@ -2630,11 +2757,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
+ // fprintf(stderr, "INS %u\n", k);
afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
} else {
+ // fprintf(stderr, "RTN %u\n", k);
afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
@@ -2673,13 +2802,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
- if (afl->fsrv.total_execs - execs > screen_update) {
-
- execs = afl->fsrv.total_execs;
- show_stats(afl);
-
- }
-
}
r = 0;
@@ -2795,9 +2917,10 @@ exit_its:
if (f) {
fprintf(f,
- "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u\n",
+ "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u "
+ "auto_extra_after=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time, r,
- new_hit_cnt - orig_hit_cnt, cmp_locations);
+ new_hit_cnt - orig_hit_cnt, cmp_locations, afl->a_extras_cnt);
#ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); }
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 4173f4e1..2789b56f 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -16,7 +16,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -291,8 +291,6 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 handicap, u8 from_queue) {
- if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
-
u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
first_run = (q->exec_cksum == 0);
u64 start_us, stop_us, diff_us;
@@ -300,6 +298,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name;
+ if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
+
/* Be a bit more generous about timeouts when resuming sessions, or when
trying to calibrate already-added finds. This helps avoid trouble due
to intermittent latency. */
@@ -343,6 +343,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
+ /* we need a dummy run if this is LTO + cmplog */
+ if (unlikely(afl->shm.cmplog_mode)) {
+
+ write_to_testcase(afl, use_mem, q->len);
+
+ fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
+
+ /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
+ we want to bail out quickly. */
+
+ if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
+
+ if (!afl->non_instrumented_mode && !afl->stage_cur &&
+ !count_bytes(afl, afl->fsrv.trace_bits)) {
+
+ fault = FSRV_RUN_NOINST;
+ goto abort_calibration;
+
+ }
+
+#ifdef INTROSPECTION
+ if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
+#endif
+
+ }
+
if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 24ccc108..737a49a7 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index eb1fe2d9..152bebe9 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -278,13 +278,14 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"total_edges : %u\n"
"var_byte_count : %u\n"
"havoc_expansion : %u\n"
+ "auto_dict_entries : %u\n"
"testcache_size : %llu\n"
"testcache_count : %u\n"
"testcache_evict : %u\n"
"afl_banner : %s\n"
"afl_version : " VERSION
"\n"
- "target_mode : %s%s%s%s%s%s%s%s%s\n"
+ "target_mode : %s%s%s%s%s%s%s%s%s%s\n"
"command_line : %s\n",
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
(afl->prev_run_time + cur_time - afl->start_time) / 1000,
@@ -316,16 +317,17 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
-1,
#endif
t_bytes, afl->fsrv.real_map_size, afl->var_byte_count,
- afl->expand_havoc, afl->q_testcase_cache_size,
+ afl->expand_havoc, afl->a_extras_cnt, afl->q_testcase_cache_size,
afl->q_testcase_cache_count, afl->q_testcase_evictions,
afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
afl->fsrv.qemu_mode ? "qemu " : "",
+ afl->fsrv.cs_mode ? "coresight" : "",
afl->non_instrumented_mode ? " non_instrumented " : "",
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
afl->persistent_mode ? "persistent " : "",
afl->shmem_testcase_mode ? "shmem_testcase " : "",
afl->deferred_mode ? "deferred " : "",
- (afl->unicorn_mode || afl->fsrv.qemu_mode ||
+ (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode ||
afl->non_instrumented_mode || afl->no_forkserver ||
afl->crash_mode || afl->persistent_mode || afl->deferred_mode)
? ""
@@ -441,9 +443,10 @@ void show_stats(afl_state_t *afl) {
u64 cur_ms;
u32 t_bytes, t_bits;
- u32 banner_len, banner_pad;
- u8 tmp[256];
- u8 time_tmp[64];
+ static u8 banner[128];
+ u32 banner_len, banner_pad;
+ u8 tmp[256];
+ u8 time_tmp[64];
u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
#define IB(i) (val_buf[(i)])
@@ -540,9 +543,11 @@ void show_stats(afl_state_t *afl) {
FATAL(
"Incorrect fuzzing setup detected. Your target seems to have loaded "
- "incorrectly instrumented shared libraries. If you use LTO mode "
+ "incorrectly instrumented shared libraries (%u of %u/%u). If you use "
+ "LTO mode "
"please see instrumentation/README.lto.md. To ignore this problem "
- "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n");
+ "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n",
+ t_bytes, afl->fsrv.real_map_size, afl->fsrv.map_size);
}
@@ -560,8 +565,9 @@ void show_stats(afl_state_t *afl) {
/* Roughly every minute, update fuzzer stats and save auto tokens. */
- if (unlikely(afl->force_ui_update ||
- cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000)) {
+ if (unlikely(!afl->non_instrumented_mode &&
+ (afl->force_ui_update ||
+ cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) {
afl->stats_last_stats_ms = cur_ms;
write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
@@ -655,26 +661,34 @@ void show_stats(afl_state_t *afl) {
}
/* Let's start by drawing a centered banner. */
+ if (unlikely(!banner[0])) {
- banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) +
- strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5;
- banner_pad = (79 - banner_len) / 2;
- memset(tmp, ' ', banner_pad);
+ char *si = "";
+ if (afl->sync_id) { si = afl->sync_id; }
+ memset(banner, 0, sizeof(banner));
+ banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
+ strlen(afl->power_name) + 4 + 6;
-#ifdef HAVE_AFFINITY
- sprintf(
- tmp + banner_pad,
- "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}",
- afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
- afl->use_banner, afl->power_name, afl->cpu_aff);
-#else
- sprintf(
- tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
- afl->use_banner, afl->power_name);
-#endif /* HAVE_AFFINITY */
+ if (strlen(afl->use_banner) + banner_len > 75) {
+
+ afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76;
+ memset(afl->use_banner, '.', 3);
+
+ }
+
+ banner_len += strlen(afl->use_banner);
+ banner_pad = (79 - banner_len) / 2;
+ memset(banner, ' ', banner_pad);
+
+ 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);
+
+ }
- SAYF("\n%s\n", tmp);
+ SAYF("\n%s\n", banner);
/* "Handy" shortcuts for drawing boxes... */
@@ -1227,7 +1241,9 @@ void show_init_stats(afl_state_t *afl) {
// SAYF("\n");
- if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) {
+ if (avg_us > ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->unicorn_mode)
+ ? 50000
+ : 10000)) {
WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
doc_path);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8ffc0e77..195366bd 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This is the real deal: the program takes an instrumented binary and
attempts a variety of basic fuzzing tricks, paying close attention to
@@ -113,11 +113,17 @@ static void usage(u8 *argv0, int more_help) {
"maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n"
+#if defined(__linux__) && defined(__aarch64__)
+ " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
" -O - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
- "mode)\n\n"
+ "mode)\n"
+#endif
+ "\n"
"Mutator settings:\n"
" -D - enable deterministic fuzzing (once per queue entry)\n"
@@ -434,7 +440,8 @@ int main(int argc, char **argv_orig, char **envp) {
while ((opt = getopt(
argc, argv,
- "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
+ "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) >
+ 0) {
switch (opt) {
@@ -563,6 +570,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->fsrv.cs_mode) {
+
+ FATAL("-M is not supported in ARM CoreSight mode");
+
+ }
+
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
/* sanity check for argument: should not begin with '-' (possible
@@ -609,6 +622,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->fsrv.cs_mode) {
+
+ FATAL("-S is not supported in ARM CoreSight mode");
+
+ }
+
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
/* sanity check for argument: should not begin with '-' (possible
@@ -825,6 +844,24 @@ int main(int argc, char **argv_orig, char **envp) {
afl->use_banner = optarg;
break;
+ case 'A': /* CoreSight mode */
+
+ #if !defined(__aarch64__) || !defined(__linux__)
+ FATAL("-A option is not supported on this platform");
+ #endif
+
+ if (afl->is_main_node || afl->is_secondary_node) {
+
+ FATAL("ARM CoreSight mode is not supported with -M / -S");
+
+ }
+
+ if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); }
+
+ afl->fsrv.cs_mode = 1;
+
+ break;
+
case 'O': /* FRIDA mode */
if (afl->fsrv.frida_mode) {
@@ -1189,7 +1226,17 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (afl->sync_id) { fix_up_sync(afl); }
+ if (afl->sync_id) {
+
+ if (strlen(afl->sync_id) > 24) {
+
+ FATAL("sync_id max length is 24 characters");
+
+ }
+
+ fix_up_sync(afl);
+
+ }
if (!strcmp(afl->in_dir, afl->out_dir)) {
@@ -1202,6 +1249,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
+ if (afl->fsrv.cs_mode) { FATAL("-A and -n are mutually exclusive"); }
if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
}
@@ -1218,6 +1266,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
+ if (!afl->use_banner) { afl->use_banner = argv[optind]; }
+
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD
@@ -1348,7 +1398,7 @@ int main(int argc, char **argv_orig, char **envp) {
} else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) {
- FATAL("AFL_TESTCACHE_SIZE must be set to %u or more, or 0 to disable",
+ FATAL("AFL_TESTCACHE_SIZE must be set to %ld or more, or 0 to disable",
(2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576
: 1 + ((2 * MAX_FILE) / 1048576));
@@ -1446,6 +1496,8 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
+ /* CoreSight mode uses the default behavior. */
+
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@@ -1486,9 +1538,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
save_cmdline(afl, argc, argv);
-
- fix_up_banner(afl, argv[optind]);
-
check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
@@ -1642,7 +1691,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode &&
+ if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
!afl->non_instrumented_mode) {
check_binary(afl, afl->cmplog_binary);
@@ -1688,6 +1737,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else if (afl->fsrv.cs_mode) {
+
+ use_argv = get_cs_argv(argv[0], &afl->fsrv.target_path, argc - optind,
+ argv + optind);
+
} else {
use_argv = argv + optind;
@@ -1695,9 +1749,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
- afl->fsrv.frida_mode || afl->unicorn_mode) {
+ afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
- map_size = afl->fsrv.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);
afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
@@ -1715,7 +1769,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
- !afl->unicorn_mode && !afl->fsrv.frida_mode &&
+ !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
!afl->afl_env.afl_skip_bin_check) {
if (map_size <= DEFAULT_SHMEM_SIZE) {
@@ -1768,6 +1822,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
// TODO: this is semi-nice
afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
+ afl->cmplog_fsrv.cs_mode = afl->fsrv.cs_mode;
afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
@@ -1776,7 +1831,7 @@ int main(int argc, char **argv_orig, char **envp) {
if ((map_size <= DEFAULT_SHMEM_SIZE ||
afl->cmplog_fsrv.map_size < map_size) &&
!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
- !afl->fsrv.frida_mode && !afl->unicorn_mode &&
+ !afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode &&
!afl->afl_env.afl_skip_bin_check) {
afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
@@ -1918,7 +1973,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- write_stats_file(afl, 0, 0, 0, 0);
+ if (!afl->non_instrumented_mode) { write_stats_file(afl, 0, 0, 0, 0); }
maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
@@ -2226,13 +2281,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
- write_bitmap(afl);
- save_auto(afl);
-
stop_fuzzing:
afl->force_ui_update = 1; // ensure the screen is reprinted
show_stats(afl); // print the screen one last time
+ write_bitmap(afl);
+ save_auto(afl);
SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
afl->stop_soon == 2 ? "programmatically" : "by user");
@@ -2261,6 +2315,20 @@ stop_fuzzing:
}
+ if (afl->not_on_tty) {
+
+ u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
+ u8 time_tmp[64];
+ u_stringify_time_diff(time_tmp, get_cur_time(), afl->start_time);
+ ACTF(
+ "Statistics: %u new paths found, %.02f%% coverage achieved, %llu "
+ "crashes found, %llu timeouts found, total runtime %s",
+ afl->queued_discovered,
+ ((double)t_bytes * 100) / afl->fsrv.real_map_size, afl->unique_crashes,
+ afl->unique_hangs, time_tmp);
+
+ }
+
#ifdef PROFILING
SAYF(cYEL "[!] " cRST
"Profiling information: %llu ms total work, %llu ns/run\n",
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index ac002a93..f8466680 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
This tool provides a fairly accurate measurement of CPU preemption rate.
It is meant to complement the quick-and-dirty load average widget shown
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 1ce97649..1dcdb176 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -15,7 +15,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
The sole purpose of this wrapper is to preprocess clang LTO files when
linking with lld and performing the instrumentation on the whole program.
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 89b170eb..04507410 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -5,7 +5,7 @@
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
- See <http://creativecommons.org/publicdomain/zero/1.0/>.
+ See <https://creativecommons.org/publicdomain/zero/1.0/>.
This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
It has excellent (sub-ns) speed, a state (256 bits) that is large
@@ -90,7 +90,8 @@ inline u32 hash32(u8 *key, u32 len, u32 seed) {
#endif
- return (u32)XXH64(key, len, seed);
+ (void)seed;
+ return (u32)XXH3_64bits(key, len);
}
@@ -102,7 +103,8 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
#endif
- return XXH64(key, len, seed);
+ (void)seed;
+ return XXH3_64bits(key, len);
}
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index 22fe5a62..7fb8f821 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -17,7 +17,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
Shared code to handle the shared memory. This is used by the fuzzer
as well the other components like afl-tmin, afl-showmap, etc...
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 9122cd25..8cddcb32 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -18,7 +18,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
A very simple tool that runs the targeted binary and displays
the contents of the trace bitmap in a human-readable form. Useful in
@@ -77,7 +77,7 @@ static u32 tcnt, highest; /* tuple content information */
static u32 in_len; /* Input data length */
-static u32 map_size = MAP_SIZE;
+static u32 map_size = MAP_SIZE, timed_out = 0;
static bool quiet_mode, /* Hide non-essential messages? */
edges_only, /* Ignore hit counts? */
@@ -146,6 +146,18 @@ static const u8 count_class_binary[256] = {
#undef TIMES8
#undef TIMES4
+static void kill_child() {
+
+ timed_out = 1;
+ if (fsrv->child_pid > 0) {
+
+ kill(fsrv->child_pid, fsrv->kill_signal);
+ fsrv->child_pid = -1;
+
+ }
+
+}
+
static void classify_counts(afl_forkserver_t *fsrv) {
u8 * mem = fsrv->trace_bits;
@@ -242,9 +254,14 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (cmin_mode &&
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
- // create empty file to prevent error messages in afl-cmin
- fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
- close(fd);
+ if (strcmp(outfile, "-")) {
+
+ // create empty file to prevent error messages in afl-cmin
+ fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+ close(fd);
+
+ }
+
return ret;
}
@@ -357,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
if (!quiet_mode) {
- if (fsrv->last_run_timed_out) {
+ if (timed_out || fsrv->last_run_timed_out) {
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
+ timed_out = 0;
} else if (stop_soon) {
@@ -413,7 +431,7 @@ static u32 read_file(u8 *in_file) {
if (!be_quiet && !quiet_mode) {
- WARNF("Input file '%s' is too large, only reading %u bytes.", in_file,
+ WARNF("Input file '%s' is too large, only reading %ld bytes.", in_file,
MAX_FILE);
}
@@ -521,6 +539,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
}
+ signal(SIGALRM, kill_child);
+
setitimer(ITIMER_REAL, &it, NULL);
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
@@ -563,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
if (!quiet_mode) {
- if (fsrv->last_run_timed_out) {
+ if (timed_out || fsrv->last_run_timed_out) {
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
+ timed_out = 0;
} else if (stop_soon) {
@@ -669,6 +690,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} else {
+ /* CoreSight mode uses the default behavior. */
+
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@@ -821,12 +844,18 @@ static void usage(u8 *argv0) {
"Execution control settings:\n"
" -t msec - timeout for each run (none)\n"
" -m megs - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+ " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
" -O - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use Unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
" (Not necessary, here for consistency with other afl-* "
- "tools)\n\n"
+ "tools)\n"
+#endif
+ "\n"
"Other settings:\n"
" -i dir - process all files below this directory, must be combined "
"with -o.\n"
@@ -896,7 +925,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:A:eqCZOQUWbcrsh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
switch (opt) {
@@ -1025,7 +1054,7 @@ int main(int argc, char **argv_orig, char **envp) {
quiet_mode = true;
break;
- case 'A':
+ case 'H':
/* Another afl-cmin specific feature. */
at_file = optarg;
break;
@@ -1035,10 +1064,23 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
fsrv->frida_mode = true;
- setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+ setenv("AFL_FRIDA_INST_SEED", "1", 1);
break;
+ /* FIXME: We want to use -P for consistency, but it is already unsed for
+ * undocumenetd feature "Another afl-cmin specific feature." */
+ case 'A': /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+ FATAL("-A option is not supported on this platform");
+#endif
+
+ if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
+
+ fsrv->cs_mode = true;
+ break;
+
case 'Q':
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1183,12 +1225,19 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else if (fsrv->cs_mode) {
+
+ use_argv =
+ get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+
} else {
use_argv = argv + optind;
}
+ if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
/* initialize cmplog_mode */
@@ -1207,7 +1256,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32);
- if (!fsrv->qemu_mode && !unicorn_mode) {
+ if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
u32 save_be_quiet = be_quiet;
be_quiet = !debug;
@@ -1386,9 +1435,9 @@ int main(int argc, char **argv_orig, char **envp) {
if (!quiet_mode || collect_coverage) {
if (!tcnt && !have_coverage) { FATAL("No instrumentation detected" cRST); }
- OKF("Captured %u tuples (highest value %u, total values %llu) in "
- "'%s'." cRST,
- tcnt, highest, total, out_file);
+ OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
+ "in '%s'." cRST,
+ tcnt, fsrv->real_map_size, highest, total, out_file);
if (collect_coverage)
OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
"with %llu input files.",
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 792770e0..89546c45 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -18,7 +18,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
A simple test case minimizer that takes an input file and tries to remove
as much data as possible while keeping the binary in a crashing state
@@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = {
#undef TIMES8
#undef TIMES4
+static void kill_child() {
+
+ if (fsrv->child_pid > 0) {
+
+ kill(fsrv->child_pid, fsrv->kill_signal);
+ fsrv->child_pid = -1;
+
+ }
+
+}
+
static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
sharedmem_t * shm_fuzz) {
@@ -221,7 +232,7 @@ static void read_initial_file(void) {
if (st.st_size >= TMIN_MAX_FILE) {
- FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
+ FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024);
}
@@ -797,6 +808,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} else {
+ /* CoreSight mode uses the default behavior. */
+
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@@ -853,13 +866,19 @@ static void usage(u8 *argv0) {
" -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+ " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
" -O - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
"mode)\n"
" (Not necessary, here for consistency with other afl-* "
- "tools)\n\n"
+ "tools)\n"
+#endif
+ "\n"
"Minimization settings:\n"
@@ -910,7 +929,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:xeOQUWHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) {
switch (opt) {
@@ -1022,12 +1041,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'A': /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+ FATAL("-A option is not supported on this platform");
+#endif
+
+ if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
+
+ fsrv->cs_mode = 1;
+ break;
+
case 'O': /* FRIDA mode */
if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
fsrv->frida_mode = 1;
- setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+ setenv("AFL_FRIDA_INST_SEED", "1", 1);
break;
@@ -1125,6 +1155,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->target_path = find_binary(argv[optind]);
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
+ signal(SIGALRM, kill_child);
if (fsrv->qemu_mode) {
@@ -1140,6 +1171,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else if (fsrv->cs_mode) {
+
+ use_argv =
+ get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+
} else {
use_argv = argv + optind;
@@ -1209,6 +1245,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz = map + sizeof(u32);
read_initial_file();
+ (void)check_binary_signatures(fsrv->target_path);
if (!fsrv->qemu_mode && !unicorn_mode) {