integration in fuzz_one
MODIFY
include/afl-fuzz.h
include/afl-fuzz.h
@@ -430,7 +430,9 @@ typedef struct afl_state {
*in_bitmap, /* Input bitmap */
*file_extension, /* File extension */
*orig_cmdline, /* Original command line */
- *infoexec; /* Command to execute on a new crash */
+ *infoexec, /* Command to execute on a new crash */
+ *taint_input_file, /* fuzz_input_one input file */
+ *taint_src, *taint_map;
u32 hang_tmout; /* Timeout used for hang det (ms) */
@@ -441,7 +443,8 @@ typedef struct afl_state {
custom_only, /* Custom mutator only mode */
python_only, /* Python-only mode */
is_main_node, /* if this is the main node */
- is_secondary_node; /* if this is a secondary instance */
+ is_secondary_node, /* if this is a secondary instance */
+ taint_needs_splode; /* explode fuzz input */
u32 stats_update_freq; /* Stats update frequency (execs) */
@@ -502,7 +505,8 @@ typedef struct afl_state {
useless_at_start, /* Number of useless starting paths */
var_byte_count, /* Bitmap bytes with var behavior */
current_entry, /* Current queue entry ID */
- havoc_div; /* Cycle count divisor for havoc */
+ havoc_div, /* Cycle count divisor for havoc */
+ taint_len;
u64 total_crashes, /* Total number of crashes */
unique_crashes, /* Crashes with unique signatures */

MODIFY
src/afl-fuzz-one.c
src/afl-fuzz-one.c
@@ -458,7 +458,80 @@ u8 fuzz_one_original(afl_state_t *afl) {
}
+ if (unlikely(afl->fsrv.taint_mode && (afl->queue_cycle % 3))) {
+
+ if (unlikely(afl->queue_cur->cal_failed)) goto abandon_entry;
+
+ u32 dst = 0, i;
+
+ fd = open(afl->queue_cur->fname, O_RDONLY);
+ afl->taint_src = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (fd < 0 || (size_t)afl->taint_src == -1)
+ FATAL("unable to open '%s'", afl->queue_cur->fname);
+ close(fd);
+
+ switch (afl->queue_cycle % 3) {
+
+ case 0: // do nothing, but cannot happen -> else
+ break;
+
+ case 1: // fuzz only tainted bytes
+ if (!afl->queue_cur->taint_bytes_all) goto abandon_entry;
+ afl->taint_needs_splode = 1;
+
+ fd = open(afl->taint_input_file, O_RDONLY);
+ len = afl->taint_len = afl->queue_cur->taint_bytes_all;
+ orig_in = in_buf =
+ mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (fd < 0 || (size_t)in_buf == -1)
+ FATAL("unable to open '%s'", afl->taint_input_file);
+ close(fd);
+
+ fd = open(afl->queue_cur->fname_taint, O_RDWR);
+ afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ if (fd < 0 || (size_t)in_buf == -1)
+ FATAL("unable to open '%s'", afl->queue_cur->fname_taint);
+ close(fd);
+
+ for (i = 0; i < afl->queue_cur->len && dst < len; i++)
+ if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
+
+ break;
+
+ case 2: // fuzz only newly tainted bytes
+ if (!afl->queue_cur->taint_bytes_new) goto abandon_entry;
+ afl->taint_needs_splode = 1;
+
+ fd = open(afl->taint_input_file, O_RDONLY);
+ len = afl->taint_len = afl->queue_cur->taint_bytes_new;
+ orig_in = in_buf =
+ mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (fd < 0 || (size_t)in_buf == -1)
+ FATAL("unable to open '%s'", afl->taint_input_file);
+ close(fd);
+
+ u8 *fn = alloc_printf("%s.new", afl->queue_cur->fname_taint);
+ fd = open(fn, O_RDWR);
+ afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ if (fd < 0 || (size_t)in_buf == -1) FATAL("unable to open '%s'", fn);
+ close(fd);
+ ck_free(fn);
+
+ for (i = 0; i < afl->queue_cur->len && dst < len; i++)
+ if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
+
+ break;
+
+ }
+
+ goto havoc_stage; // we let the normal cycles do deterministic mode - if
+
+ } else {
+
/* Map the test case into memory. */
+ afl->taint_needs_splode = 0;
fd = open(afl->queue_cur->fname, O_RDONLY);
@@ -480,6 +553,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
close(fd);
+ }
+
/* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every
single byte anyway, so it wouldn't give us any performance or memory usage
benefits. */
@@ -527,7 +602,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
************/
if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
- !afl->disable_trim) {
+ !afl->disable_trim && !afl->taint_needs_splode) {
u8 res = trim_case(afl, afl->queue_cur, in_buf);
@@ -2568,8 +2643,18 @@ abandon_entry:
++afl->queue_cur->fuzz_level;
+ if (afl->taint_needs_splode) {
+
+ munmap(afl->taint_src, afl->queue_cur->len);
+ munmap(orig_in, afl->taint_len);
+ munmap(afl->taint_map, afl->queue_cur->len);
+
+ } else {
+
munmap(orig_in, afl->queue_cur->len);
+ }
+
return ret_val;
#undef FLIP_BIT

MODIFY
src/afl-fuzz-run.c
src/afl-fuzz-run.c
@@ -863,6 +863,8 @@ abort_trimming:
}
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
/* Write a modified test case, run program, process results. Handle
error conditions, returning 1 if it's time to bail out. This is
a helper function for fuzz_one(). */
@@ -871,6 +873,27 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
+ if (unlikely(afl->taint_needs_splode)) {
+
+ s32 new_len = afl->queue_cur->len + len - afl->taint_len;
+ if (new_len < 4) new_len = 4;
+ u8 *new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len);
+
+ u32 i, taint = 0;
+ for (i = 0; i < new_len; i++) {
+
+ if (afl->taint_map[i] || i > afl->queue_cur->len)
+ new_buf[i] = out_buf[taint++];
+ else
+ new_buf[i] = afl->taint_src[i];
+
+ }
+
+ out_buf = new_buf;
+ len = new_len;
+
+ }
+
write_to_testcase(afl, out_buf, len);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@@ -918,3 +941,5 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
}
+#undef BUF_PARAMS
+

MODIFY
src/afl-fuzz.c
src/afl-fuzz.c
@@ -1260,12 +1260,15 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.taint_mode) {
ACTF("Spawning qemu_taint forkserver");
+
u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0);
+
afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv);
afl->taint_fsrv.qemu_mode = 2;
afl->taint_fsrv.taint_mode = 1;
afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits;
+
ck_free(afl->taint_fsrv.target_path);
afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind));
afl->taint_fsrv.target_path =
@@ -1290,7 +1293,16 @@ int main(int argc, char **argv_orig, char **envp) {
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);
+
+ afl->taint_input_file = alloc_printf("%s/taint/.input", afl->out_dir);
+ int fd = open(afl->taint_input_file, O_CREAT | O_TRUNC | O_RDWR, 0644);
+ if (fd < 0)
+ FATAL("Cannot create taint inpu file '%s'", afl->taint_input_file);
+ lseek(fd, MAX_FILE, SEEK_SET);
+ ck_write(fd, "\0", 1, afl->taint_input_file);
+
if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
+
OKF("Taint forkserver successfully started");
}

integration in fuzz_one