aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-09 00:35:12 +0200
committervan Hauser <vh@thc.org>2020-08-09 00:35:12 +0200
commite4a0237cbc745552a5b21a2450d7ab55ee98759d (patch)
tree4a744f0705ab405dd86017b791a510f1dde22a1e
parentd8f5502d83ec530bcc1ad15b2d23b2660cd6ce58 (diff)
downloadafl++-e4a0237cbc745552a5b21a2450d7ab55ee98759d.tar.gz
step 1
-rw-r--r--GNUmakefile2
-rw-r--r--include/afl-fuzz.h6
-rw-r--r--include/forkserver.h2
-rw-r--r--qemu_taint/README.md2
-rw-r--r--src/afl-common.c1
-rw-r--r--src/afl-forkserver.c15
-rw-r--r--src/afl-fuzz-bitmap.c32
-rw-r--r--src/afl-fuzz-run.c13
-rw-r--r--src/afl-fuzz.c51
9 files changed, 116 insertions, 8 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 9b064eb6..4d0c434e 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -98,7 +98,7 @@ ifneq "$(shell uname -m)" "x86_64"
endif
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
-override CFLAGS += -Wall -Wextra -Werror -g -Wno-pointer-sign \
+override CFLAGS += -g -Wno-pointer-sign \
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index bb1bb314..eb7f8ca5 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -371,6 +371,8 @@ typedef struct afl_state {
afl_env_vars_t afl_env;
char **argv; /* argv if needed */
+
+ char **argv_taint; /* argv for taint mode */
/* MOpt:
Lots of globals, but mostly for the status UI and other things where it
@@ -581,6 +583,9 @@ typedef struct afl_state {
char * cmplog_binary;
afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */
+ /* Taint mode */
+ afl_forkserver_t taint_fsrv; /* taint mode has its own little forkserver */
+
/* Custom mutators */
struct custom_mutator *mutator;
@@ -889,6 +894,7 @@ u32 calculate_score(afl_state_t *, struct queue_entry *);
void write_bitmap(afl_state_t *);
u32 count_bits(afl_state_t *, u8 *);
+u32 count_bits_len(afl_state_t *, u8 *, u32);
u32 count_bytes(afl_state_t *, u8 *);
u32 count_non_255_bytes(afl_state_t *, u8 *);
#ifdef WORD_SIZE_64
diff --git a/include/forkserver.h b/include/forkserver.h
index 717493db..a5fca30e 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -79,6 +79,8 @@ typedef struct afl_forkserver {
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
u8 qemu_mode; /* if running in qemu mode or not */
+
+ u8 taint_mode; /* if running taint analysis or not */
u32 *shmem_fuzz_len; /* length of the fuzzing test case */
diff --git a/qemu_taint/README.md b/qemu_taint/README.md
index c842da0e..6a7d19af 100644
--- a/qemu_taint/README.md
+++ b/qemu_taint/README.md
@@ -18,7 +18,7 @@ Only touched bytes are then fuzzed by afl-fuzz
## How to use
-Add the -T flag to afl-fuzz
+Add the -A flag to afl-fuzz
## Caveats
diff --git a/src/afl-common.c b/src/afl-common.c
index 367dec72..134d3180 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -138,6 +138,7 @@ void argv_cpy_free(char **argv) {
}
+
/* Rewrite argv for QEMU. */
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 752641d7..b4f92e5b 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -481,6 +481,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"handle_sigill=0",
0);
+fprintf(stderr, "init %p\n", fsrv->init_child_func);
fsrv->init_child_func(fsrv, argv);
/* Use a distinctive bitmap signature to tell the parent about execv()
@@ -496,10 +497,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
char pid_buf[16];
sprintf(pid_buf, "%d", fsrv->fsrv_pid);
- if (fsrv->cmplog_binary)
+
+ if (fsrv->qemu_mode == 2) {
+
+ setenv("__AFL_TARGET_PID3", pid_buf, 1);
+
+ } else if (fsrv->cmplog_binary) {
+
setenv("__AFL_TARGET_PID2", pid_buf, 1);
- else
+
+ } else {
+
setenv("__AFL_TARGET_PID1", pid_buf, 1);
+
+ }
/* Close the unneeded endpoints. */
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index aa8d5a18..9cb1b83f 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -177,6 +177,38 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
}
+u32 count_bits_len(afl_state_t *afl, u8 *mem, u32 len) {
+
+ u32 *ptr = (u32 *)mem;
+ u32 i = (len >> 2);
+ u32 ret = 0;
+
+ if (len % 4) i++;
+
+ while (i--) {
+
+ u32 v = *(ptr++);
+
+ /* This gets called on the inverse, virgin bitmap; optimize for sparse
+ data. */
+
+ if (v == 0xffffffff) {
+
+ ret += 32;
+ continue;
+
+ }
+
+ v -= ((v >> 1) & 0x55555555);
+ v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+ ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24;
+
+ }
+
+ return ret;
+
+}
+
/* Count the number of bytes set in the bitmap. Called fairly sporadically,
mostly to update the status screen or calibrate and examine confirmed
new paths. */
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 8d652155..207b3046 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -471,6 +471,19 @@ abort_calibration:
afl->stage_cur = old_sc;
afl->stage_max = old_sm;
+ /* if taint mode was selected, run the taint */
+
+ if (afl->fsrv.taint_mode) {
+ write_to_testcase(afl, use_mem, q->len);
+ if (afl_fsrv_run_target(&afl->taint_fsrv, use_tmout, &afl->stop_soon) == 0) {
+ u32 len = q->len / 8;
+ if (q->len % 8) len++;
+ u32 bits = count_bits_len(afl, afl->taint_fsrv.trace_bits, len);
+ if (afl->debug) fprintf(stderr, "Debug: tainted bytes: %u\n", bits);
+
+ }
+ }
+
if (!first_run) { show_stats(afl); }
return fault;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 031c4049..bc780b55 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -53,6 +53,9 @@ static void at_exit() {
ptr = getenv("__AFL_TARGET_PID2");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+ ptr = getenv("__AFL_TARGET_PID3");
+ if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+
i = 0;
while (list[i] != NULL) {
@@ -89,6 +92,7 @@ static void usage(u8 *argv0, int more_help) {
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
+ " -A - use first level taint analysis (see qemu_taint/README.md)\n"
" -p schedule - power schedules compute a seed's performance score. "
"<explore\n"
" (default), fast, coe, lin, quad, exploit, mmopt, "
@@ -277,10 +281,15 @@ int main(int argc, char **argv_orig, char **envp) {
while ((opt = getopt(
argc, argv,
- "+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) {
+ "+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QANUWe:p:s:V:E:L:hRP:")) > 0) {
switch (opt) {
+ case 'A':
+ afl->fsrv.taint_mode = 1;
+ if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
+ break;
+
case 'I':
afl->infoexec = optarg;
break;
@@ -485,7 +494,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!optarg) { FATAL("Wrong usage of -m"); }
- if (!strcmp(optarg, "none")) {
+ if (!strcmp(optarg, "none") || !strcmp(optarg, "0")) {
afl->fsrv.mem_limit = 0;
break;
@@ -815,6 +824,14 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->fsrv.taint_mode && afl->fsrv.map_size < (MAX_FILE / 8) + 1) {
+
+ afl->shm.map_size = (MAX_FILE / 8);
+ if (MAX_FILE % 8) afl->shm.map_size++;
+ afl->fsrv.map_size = afl->shm.map_size;
+
+ }
+
if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
@@ -869,6 +886,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
+ if (afl->fsrv.taint_mode) { FATAL("-A and -n are mutually exclusive"); }
}
@@ -969,7 +987,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->afl_env.afl_preload) {
- if (afl->fsrv.qemu_mode) {
+ if (afl->fsrv.qemu_mode || afl->fsrv.taint_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
u8 *afl_preload = getenv("AFL_PRELOAD");
@@ -1220,7 +1238,6 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Spawning cmplog forkserver");
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.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
@@ -1230,6 +1247,29 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Cmplog forkserver successfully started");
}
+
+ if (afl->fsrv.taint_mode) {
+
+ ACTF("Spawning qemu_taint forkserver");
+ afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv);
+ afl->taint_fsrv.qemu_mode = 2;
+ afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits;
+ ck_free(afl->taint_fsrv.target_path);
+ afl->taint_fsrv.target_path = ck_strdup(afl->fsrv.target_path);
+ afl->argv_taint = get_qemu_argv(argv[0], &afl->taint_fsrv.target_path,
+ argc - optind, argv + optind);
+ u32 len = strlen(afl->taint_fsrv.target_path);
+ strcpy(afl->taint_fsrv.target_path + len - 5, "taint");
+ strcpy((afl->argv_taint[0]) + len - 5, "taint");
+ if (afl->fsrv.use_stdin)
+ unsetenv("AFL_TAINT_INPUT");
+ else
+ setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1);
+ afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon,
+ afl->afl_env.afl_debug_child_output);
+ OKF("Taint forkserver successfully started");
+
+ }
perform_dry_run(afl);
@@ -1493,8 +1533,11 @@ stop_fuzzing:
}
+ if (afl->cmplog_binary) afl_fsrv_deinit(&afl->cmplog_fsrv);
+ if (afl->fsrv.taint_mode) afl_fsrv_deinit(&afl->taint_fsrv);
afl_fsrv_deinit(&afl->fsrv);
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
+ if (afl->argv_taint) { ck_free(afl->argv_taint); }
ck_free(afl->fsrv.target_path);
ck_free(afl->fsrv.out_file);
ck_free(afl->sync_id);