about summary refs log tree commit diff
path: root/src/afl-fuzz-one.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-fuzz-one.c')
-rw-r--r--src/afl-fuzz-one.c191
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;