diff options
Diffstat (limited to 'src/afl-fuzz-one.c')
-rw-r--r-- | src/afl-fuzz-one.c | 191 |
1 files changed, 164 insertions, 27 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 452c5298..9f38b8f8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -458,27 +458,107 @@ u8 fuzz_one_original(afl_state_t *afl) { } - /* Map the test case into memory. */ + u32 tmp_val = 0; - fd = open(afl->queue_cur->fname, O_RDONLY); + if (unlikely(afl->fsrv.taint_mode)) { - if (unlikely(fd < 0)) { + tmp_val = afl->queue_cycle % 2; + ret_val = 0; - PFATAL("Unable to open '%s'", afl->queue_cur->fname); + if (unlikely(afl->queue_cur->cal_failed)) goto abandon_entry; + if (unlikely(!afl->queue_cur->passed_det) && !tmp_val) goto abandon_entry; + if (tmp_val == 1 && !afl->queue_cur->taint_bytes_all) goto abandon_entry; + if (tmp_val == 0 && !afl->queue_cur->taint_bytes_new) goto abandon_entry; - } + ret_val = 1; - len = afl->queue_cur->len; + u32 dst = 0, i; + temp_len = len = afl->queue_cur->len; - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + 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); + afl->taint_needs_splode = 1; - if (unlikely(orig_in == MAP_FAILED)) { + switch (tmp_val) { - PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); + case 1: // fuzz only tainted bytes - } + fd = open(afl->taint_input_file, O_RDONLY); + temp_len = 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); - 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 0: // fuzz only newly tainted bytes + + fd = open(afl->taint_input_file, O_RDONLY); + temp_len = 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' for %u bytes", fn, len); + 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; + + } + + } else { + + afl->taint_needs_splode = 0; + + /* Map the test case into memory. */ + + fd = open(afl->queue_cur->fname, O_RDONLY); + + if (unlikely(fd < 0)) { + + PFATAL("Unable to open '%s'", afl->queue_cur->fname); + + } + + len = afl->queue_cur->len; + + orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + + if (unlikely(orig_in == MAP_FAILED)) { + + PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); + + } + + 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 @@ -494,7 +574,8 @@ u8 fuzz_one_original(afl_state_t *afl) { * CALIBRATION (only if failed earlier on) * *******************************************/ - if (unlikely(afl->queue_cur->cal_failed)) { + if (unlikely(afl->queue_cur->cal_failed && + (!afl->taint_needs_splode || tmp_val == 1))) { u8 res = FSRV_RUN_TMOUT; @@ -527,7 +608,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); @@ -2133,8 +2214,18 @@ havoc_stage: if (actually_clone) { - clone_len = choose_block_len(afl, temp_len); - clone_from = rand_below(afl, temp_len - clone_len + 1); + if (unlikely(afl->taint_needs_splode)) { + + clone_len = choose_block_len(afl, afl->queue_cur->len); + clone_from = + rand_below(afl, afl->queue_cur->len - clone_len + 1); + + } else { + + clone_len = choose_block_len(afl, temp_len); + clone_from = rand_below(afl, temp_len - clone_len + 1); + + } } else { @@ -2145,8 +2236,8 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - new_buf = - ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + temp_len + clone_len); /* Head */ @@ -2156,7 +2247,11 @@ havoc_stage: if (actually_clone) { - memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); + if (unlikely(afl->taint_needs_splode)) + memcpy(new_buf + clone_to, afl->taint_src + clone_from, + clone_len); + else + memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); } else { @@ -2189,16 +2284,38 @@ havoc_stage: if (temp_len < 2) { break; } - copy_len = choose_block_len(afl, temp_len - 1); + if (unlikely(afl->taint_needs_splode)) { + + copy_len = choose_block_len(afl, afl->queue_cur->len - 1); + copy_from = rand_below(afl, afl->queue_cur->len - copy_len + 1); + + } else { + + copy_len = choose_block_len(afl, temp_len - 1); + copy_from = rand_below(afl, temp_len - copy_len + 1); + + } - copy_from = rand_below(afl, temp_len - copy_len + 1); copy_to = rand_below(afl, temp_len - copy_len + 1); + if (unlikely(copy_to > temp_len)) copy_to = rand_below(afl, temp_len); if (rand_below(afl, 4)) { if (copy_from != copy_to) { - memmove(out_buf + copy_to, out_buf + copy_from, copy_len); + if (unlikely(afl->taint_needs_splode)) { + + if (copy_to > temp_len) copy_to = rand_below(afl, temp_len); + + // fprintf(stderr, "\nout_buf %p + copy_to %u, src %p + %u, + // copy_len %u -- len %u\n", out_buf , copy_to, afl->taint_src , + // copy_from, copy_len, afl->taint_len, afl->queue_cur->len); + memmove(out_buf + copy_to, afl->taint_src + copy_from, + copy_len); + + } else + + memmove(out_buf + copy_to, out_buf + copy_from, copy_len); } @@ -2286,7 +2403,8 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) { break; } - out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); + out_buf = + ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); /* Tail */ memmove(out_buf + insert_at + extra_len, out_buf + insert_at, @@ -2381,8 +2499,8 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - u8 *temp_buf = - ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); + u8 *temp_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + temp_len + clone_len); /* Head */ @@ -2464,10 +2582,17 @@ havoc_stage: splices them together at some offset, then relies on the havoc code to mutate that blob. */ + u32 saved_len; + + if (unlikely(afl->taint_needs_splode)) + saved_len = afl->taint_len; + else + saved_len = afl->queue_cur->len; + retry_splicing: if (afl->use_splicing && splice_cycle++ < SPLICE_CYCLES && - afl->queued_paths > 1 && afl->queue_cur->len > 1) { + afl->queued_paths > 1 && saved_len > 1) { struct queue_entry *target; u32 tid, split_at; @@ -2480,7 +2605,7 @@ retry_splicing: if (in_buf != orig_in) { in_buf = orig_in; - len = afl->queue_cur->len; + len = saved_len; } @@ -2551,6 +2676,8 @@ retry_splicing: ret_val = 0; + goto abandon_entry; + /* we are through with this queue entry - for this iteration */ abandon_entry: @@ -2570,7 +2697,17 @@ abandon_entry: ++afl->queue_cur->fuzz_level; - munmap(orig_in, afl->queue_cur->len); + 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; |