about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--examples/qemu_persistent_hook/read_into_rdi.c19
-rw-r--r--qemu_mode/patches/afl-qemu-common.h9
-rw-r--r--qemu_mode/patches/afl-qemu-cpu-inl.h82
-rw-r--r--qemu_mode/patches/afl-qemu-cpu-translate-inl.h3
-rw-r--r--src/afl-fuzz.c2
5 files changed, 96 insertions, 19 deletions
diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c
index 6cf66ddf..29087962 100644
--- a/examples/qemu_persistent_hook/read_into_rdi.c
+++ b/examples/qemu_persistent_hook/read_into_rdi.c
@@ -35,16 +35,25 @@ enum {
 
 };
 
-void afl_persistent_hook(uint64_t *regs, uint64_t guest_base) {
+void afl_persistent_hook(uint64_t *regs, uint64_t guest_base,
+                         uint8_t* input_buf, uint32_t input_len) {
 
   // In this example the register RDI is pointing to the memory location
   // of the target buffer, and the length of the input is in RSI.
   // This can be seen with a debugger, e.g. gdb (and "disass main")
 
-  printf("reading into %p\n", regs[R_EDI]);
-  size_t r = read(0, g2h(regs[R_EDI]), 1024);
-  regs[R_ESI] = r;
-  printf("read %ld bytes\n", r);
+  printf("placing input into %p\n", regs[R_EDI]);
+
+  if (input_len > 1024)
+    input_len = 1024;
+  memcpy(g2h(regs[R_EDI]), input_buf, input_len); 
+  regs[R_ESI] = input_len;
 
 }
 
+int afl_persistent_hook_init(void) {
+
+  // 1 for shared memory input (faster), 0 for normal input (you have to use read(), input_buf will be NULL)
+  return 1;
+
+}
diff --git a/qemu_mode/patches/afl-qemu-common.h b/qemu_mode/patches/afl-qemu-common.h
index 057e1b62..5812596a 100644
--- a/qemu_mode/patches/afl-qemu-common.h
+++ b/qemu_mode/patches/afl-qemu-common.h
@@ -63,7 +63,10 @@
   #define INC_AFL_AREA(loc) afl_area_ptr[loc]++
 #endif
 
-typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base);
+typedef void (*afl_persistent_hook_fn)(uint64_t *regs,
+                                       uint64_t guest_base,
+                                       uint8_t* input_buf,
+                                       uint32_t input_buf_len);
 
 /* Declared in afl-qemu-cpu-inl.h */
 
@@ -81,6 +84,10 @@ extern unsigned char  persistent_save_gpr;
 extern uint64_t       persistent_saved_gpr[AFL_REGS_NUM];
 extern int            persisent_retaddr_offset;
 
+extern u8 *shared_buf;
+extern u32 shared_buf_len;
+extern u8 sharedmem_fuzzing;
+
 extern afl_persistent_hook_fn afl_persistent_hook_ptr;
 
 extern __thread abi_ulong afl_prev_loc;
diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h
index e4ebaf88..dc18ea95 100644
--- a/qemu_mode/patches/afl-qemu-cpu-inl.h
+++ b/qemu_mode/patches/afl-qemu-cpu-inl.h
@@ -83,6 +83,10 @@ unsigned char persistent_save_gpr;
 uint64_t      persistent_saved_gpr[AFL_REGS_NUM];
 int           persisent_retaddr_offset;
 
+u8 *shared_buf;
+u32 shared_buf_len;
+u8 sharedmem_fuzzing;
+
 afl_persistent_hook_fn afl_persistent_hook_ptr;
 
 /* Instrumentation ratio: */
@@ -128,6 +132,7 @@ static inline TranslationBlock *tb_find(CPUState *, TranslationBlock *, int,
 static inline void              tb_add_jump(TranslationBlock *tb, int n,
                                             TranslationBlock *tb_next);
 int                             open_self_maps(void *cpu_env, int fd);
+static void                     afl_map_shm_fuzz(void);
 
 /*************************
  * ACTUAL IMPLEMENTATION *
@@ -135,6 +140,36 @@ int                             open_self_maps(void *cpu_env, int fd);
 
 /* Set up SHM region and initialize other stuff. */
 
+static void afl_map_shm_fuzz(void) {
+
+  char *id_str = getenv(SHM_FUZZ_ENV_VAR);
+
+  if (id_str) {
+
+    u32 shm_id = atoi(id_str);
+    shared_buf = shmat(shm_id, NULL, 0);
+
+    /* Whooooops. */
+
+    if (shared_buf == (void *)-1) {
+
+      fprintf(stderr, "[AFL] ERROR:  could not access fuzzing shared memory\n");
+      exit(1);
+
+    }
+
+    if (getenv("AFL_DEBUG"))
+      fprintf(stderr, "[AFL] DEBUG: successfully got fuzzing shared memory\n");
+
+  } else {
+
+    fprintf(stderr, "[AFL] ERROR:  variable for fuzzing shared memory is not set\n");
+    exit(1);
+
+  }
+
+}
+
 void afl_setup(void) {
 
   char *id_str = getenv(SHM_ENV_VAR), *inst_r = getenv("AFL_INST_RATIO");
@@ -247,6 +282,11 @@ void afl_setup(void) {
       exit(1);
 
     }
+    
+    int (*afl_persistent_hook_init_ptr)(void) = dlsym(plib,
+                                                    "afl_persistent_hook_init");
+    if (afl_persistent_hook_init_ptr)
+      sharedmem_fuzzing = afl_persistent_hook_init_ptr();
 
     afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook");
     if (!afl_persistent_hook_ptr) {
@@ -262,7 +302,7 @@ void afl_setup(void) {
 #endif
 
   }
-
+  
   if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"))
     persisent_retaddr_offset =
         strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0);
@@ -278,7 +318,7 @@ void afl_setup(void) {
 
 void afl_forkserver(CPUState *cpu) {
 
-  u32           map_size = 0;
+  //u32           map_size = 0;
   unsigned char tmp[4] = {0};
 
   if (forkserver_installed == 1) return;
@@ -291,15 +331,15 @@ void afl_forkserver(CPUState *cpu) {
   pid_t child_pid;
   int   t_fd[2];
   u8    child_stopped = 0;
+  u32 was_killed;
+  int status;
 
-  // if in the future qemu has non-collding coverage then switch MAP_SIZE
   // with the max ID value
-  if (MAP_SIZE <= 0x800000) {
-
-    map_size = (FS_OPT_ENABLED | FS_OPT_MAPSIZE | FS_OPT_SET_MAPSIZE(MAP_SIZE));
-    memcpy(tmp, &map_size, 4);
-
-  }
+  if (MAP_SIZE <= FS_OPT_MAX_MAPSIZE)
+    status |= (FS_OPT_SET_MAPSIZE(MAP_SIZE) | FS_OPT_MAPSIZE);
+  if (sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
+  if (status) status |= (FS_OPT_ENABLED);
+  memcpy(tmp, &status, 4);
 
   /* Tell the parent that we're alive. If the parent doesn't want
      to talk, assume that we're not running in forkserver mode. */
@@ -309,17 +349,34 @@ void afl_forkserver(CPUState *cpu) {
   afl_forksrv_pid = getpid();
 
   int first_run = 1;
+  
+  if (sharedmem_fuzzing) {
+
+    if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
+
+    if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) ==
+        (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))
+      afl_map_shm_fuzz();
+    else {
+    
+      fprintf(stderr, "[AFL] ERROR: afl-fuzz is old and does not support"
+                      " shmem input");
+      exit(1);
+    
+    }
+
+  }
 
   /* All right, let's await orders... */
 
   while (1) {
 
-    int status;
-    u32 was_killed;
-
     /* Whoops, parent dead? */
 
     if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
+    
+    shared_buf_len = (was_killed >> 8);
+    was_killed = (was_killed & 0xff);
 
     /* If we stopped the child in persistent mode, but there was a race
        condition and afl-fuzz already issued SIGKILL, write off the old
@@ -402,6 +459,7 @@ void afl_forkserver(CPUState *cpu) {
 
 }
 
+
 /* A simplified persistent mode handler, used as explained in
  * llvm_mode/README.md. */
 
diff --git a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h
index 083c27e5..15d5c91c 100644
--- a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h
+++ b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h
@@ -161,7 +161,8 @@ static void log_x86_sp_content(void) {
 
 static void callback_to_persistent_hook(void) {
 
-  afl_persistent_hook_ptr(persistent_saved_gpr, guest_base);
+  afl_persistent_hook_ptr(persistent_saved_gpr, guest_base, shared_buf,
+                          shared_buf_len);
 
 }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index ee9c0c67..aed1e958 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -556,6 +556,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
         if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
         afl->fsrv.qemu_mode = 1;
+        afl->shmem_testcase_mode = 1;
 
         if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
 
@@ -583,6 +584,7 @@ int main(int argc, char **argv_orig, char **envp) {
         if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
         afl->fsrv.qemu_mode = 1;
         afl->use_wine = 1;
+        afl->shmem_testcase_mode = 1;
 
         if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }