This commit is contained in:
van Hauser
2020-08-09 00:35:12 +02:00
parent d8f5502d83
commit e4a0237cbc
9 changed files with 116 additions and 8 deletions

View File

@ -98,7 +98,7 @@ ifneq "$(shell uname -m)" "x86_64"
endif endif
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) 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)\" \ -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"

View File

@ -371,6 +371,8 @@ typedef struct afl_state {
afl_env_vars_t afl_env; afl_env_vars_t afl_env;
char **argv; /* argv if needed */ char **argv; /* argv if needed */
char **argv_taint; /* argv for taint mode */
/* MOpt: /* MOpt:
Lots of globals, but mostly for the status UI and other things where it 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; char * cmplog_binary;
afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */ 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 */ /* Custom mutators */
struct custom_mutator *mutator; struct custom_mutator *mutator;
@ -889,6 +894,7 @@ u32 calculate_score(afl_state_t *, struct queue_entry *);
void write_bitmap(afl_state_t *); void write_bitmap(afl_state_t *);
u32 count_bits(afl_state_t *, u8 *); 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_bytes(afl_state_t *, u8 *);
u32 count_non_255_bytes(afl_state_t *, u8 *); u32 count_non_255_bytes(afl_state_t *, u8 *);
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64

View File

@ -79,6 +79,8 @@ typedef struct afl_forkserver {
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
u8 qemu_mode; /* if running in qemu mode or not */ 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 */ u32 *shmem_fuzz_len; /* length of the fuzzing test case */

View File

@ -18,7 +18,7 @@ Only touched bytes are then fuzzed by afl-fuzz
## How to use ## How to use
Add the -T flag to afl-fuzz Add the -A flag to afl-fuzz
## Caveats ## Caveats

View File

@ -138,6 +138,7 @@ void argv_cpy_free(char **argv) {
} }
/* Rewrite argv for QEMU. */ /* Rewrite argv for QEMU. */
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {

View File

@ -481,6 +481,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"handle_sigill=0", "handle_sigill=0",
0); 0);
fprintf(stderr, "init %p\n", fsrv->init_child_func);
fsrv->init_child_func(fsrv, argv); fsrv->init_child_func(fsrv, argv);
/* Use a distinctive bitmap signature to tell the parent about execv() /* 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]; char pid_buf[16];
sprintf(pid_buf, "%d", fsrv->fsrv_pid); 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); setenv("__AFL_TARGET_PID2", pid_buf, 1);
else
} else {
setenv("__AFL_TARGET_PID1", pid_buf, 1); setenv("__AFL_TARGET_PID1", pid_buf, 1);
}
/* Close the unneeded endpoints. */ /* Close the unneeded endpoints. */

View File

@ -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, /* Count the number of bytes set in the bitmap. Called fairly sporadically,
mostly to update the status screen or calibrate and examine confirmed mostly to update the status screen or calibrate and examine confirmed
new paths. */ new paths. */

View File

@ -471,6 +471,19 @@ abort_calibration:
afl->stage_cur = old_sc; afl->stage_cur = old_sc;
afl->stage_max = old_sm; 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); } if (!first_run) { show_stats(afl); }
return fault; return fault;

View File

@ -53,6 +53,9 @@ static void at_exit() {
ptr = getenv("__AFL_TARGET_PID2"); ptr = getenv("__AFL_TARGET_PID2");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL); 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; i = 0;
while (list[i] != NULL) { 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" " -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\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. " " -p schedule - power schedules compute a seed's performance score. "
"<explore\n" "<explore\n"
" (default), fast, coe, lin, quad, exploit, mmopt, " " (default), fast, coe, lin, quad, exploit, mmopt, "
@ -277,10 +281,15 @@ int main(int argc, char **argv_orig, char **envp) {
while ((opt = getopt( while ((opt = getopt(
argc, argv, 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) { switch (opt) {
case 'A':
afl->fsrv.taint_mode = 1;
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
break;
case 'I': case 'I':
afl->infoexec = optarg; afl->infoexec = optarg;
break; break;
@ -485,7 +494,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!optarg) { FATAL("Wrong usage of -m"); } if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none") || !strcmp(optarg, "0")) {
afl->fsrv.mem_limit = 0; afl->fsrv.mem_limit = 0;
break; 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; if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " 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->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q 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->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->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 *qemu_preload = getenv("QEMU_SET_ENV");
u8 *afl_preload = getenv("AFL_PRELOAD"); u8 *afl_preload = getenv("AFL_PRELOAD");
@ -1220,7 +1238,6 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Spawning cmplog forkserver"); ACTF("Spawning cmplog forkserver");
afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv); 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.trace_bits = afl->fsrv.trace_bits;
afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; 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"); 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); 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); afl_fsrv_deinit(&afl->fsrv);
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } 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.target_path);
ck_free(afl->fsrv.out_file); ck_free(afl->fsrv.out_file);
ck_free(afl->sync_id); ck_free(afl->sync_id);