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
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)\"

View File

@ -372,6 +372,8 @@ typedef struct afl_state {
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
really makes no sense to haul them around as function parameters. */
@ -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

View File

@ -80,6 +80,8 @@ typedef struct afl_forkserver {
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 */
u8 *shmem_fuzz; /* allocated memory for fuzzing */

View File

@ -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

View File

@ -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) {

View File

@ -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,11 +497,21 @@ 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. */
close(ctl_pipe[0]);

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,
mostly to update the status screen or calibrate and examine confirmed
new paths. */

View File

@ -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;

View File

@ -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;
@ -1231,6 +1248,29 @@ int main(int argc, char **argv_orig, char **envp) {
}
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);
cull_queue(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);