about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvanhauser-thc <vh@thc.org>2021-03-06 15:48:49 +0100
committervanhauser-thc <vh@thc.org>2021-03-06 15:48:49 +0100
commit81442ba3f953c939e2cde9c16b9cd0d5fe7f12b5 (patch)
tree45be4ebb5401bc2ed32c6ec25ac541f353f09efa
parent84f0b4f1874a9c3a5f2da4056f974df8273093d9 (diff)
downloadafl++-81442ba3f953c939e2cde9c16b9cd0d5fe7f12b5.tar.gz
implementation without testing
-rw-r--r--include/forkserver.h11
-rw-r--r--src/afl-forkserver.c68
-rw-r--r--src/afl-fuzz.c3
3 files changed, 78 insertions, 4 deletions
diff --git a/include/forkserver.h b/include/forkserver.h
index a0a60e0f..ddbc36ef 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -55,9 +55,6 @@ typedef struct afl_forkserver {
   u32 init_tmout;                       /* Configurable init timeout (ms)   */
   u32 map_size;                         /* map size used by the target      */
   u32 snapshot;                         /* is snapshot feature used         */
-  u32 persistent_replay;                /* persistent replay setting        */
-  u32 persistent_replay_idx;            /* persistent replay cache ptr      */
-  u32 persistent_replay_cnt;            /* persistent replay counter        */
   u64 mem_limit;                        /* Memory cap for child (MB)        */
 
   u64 total_execs;                      /* How often run_target was called  */
@@ -97,6 +94,14 @@ typedef struct afl_forkserver {
 
   char *cmplog_binary;                  /* the name of the cmplog binary    */
 
+  /* persistent mode replay functionality */
+  u32   persistent_replay;              /* persistent replay setting        */
+  u32   persistent_replay_idx;          /* persistent replay cache ptr      */
+  u32   persistent_replay_cnt;          /* persistent replay counter        */
+  u8 *  persistent_replay_dir;
+  u8 ** persistent_replay_data;
+  u32 **persistent_replay_len;
+
   /* Function to kick off the forkserver child */
   void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 7968f69c..05aba2e5 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -364,6 +364,21 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (!be_quiet) { ACTF("Spinning up the fork server..."); }
 
+  if (unlikely(fsrv->persistent_replay)) {
+
+    fsrv->persistent_replay_data =
+        (u8 **)ck_alloc(fsrv->persistent_replay * sizeof(size_t));
+    fsrv->persistent_replay_len =
+        (u32 **)ck_alloc(fsrv->persistent_replay * sizeof(u32));
+
+    if (!fsrv->persistent_replay_data || !fsrv->persistent_replay_len) {
+
+      FATAL("Unable to allocate memory for persistent replay.");
+
+    }
+
+  }
+
   if (fsrv->use_fauxsrv) {
 
     /* TODO: Come up with some nice way to initialize this all */
@@ -998,6 +1013,29 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
 
 void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
+  if (unlikely(fsrv->persistent_replay)) {
+
+    *fsrv->persistent_replay_len[fsrv->persistent_replay_idx] = len;
+    fsrv->persistent_replay_data[fsrv->persistent_replay_idx] = afl_realloc(
+        (void **)&fsrv->persistent_replay_data[fsrv->persistent_replay_idx],
+        len);
+
+    if (unlikely(!fsrv->persistent_replay_data[fsrv->persistent_replay_idx])) {
+
+      FATAL("allocating replay memory failed.");
+
+    }
+
+    memcpy(fsrv->persistent_replay_data[fsrv->persistent_replay_idx], buf, len);
+
+    if (unlikely(++fsrv->persistent_replay_idx >= fsrv->persistent_replay)) {
+
+      fsrv->persistent_replay_idx = 0;
+
+    }
+
+  }
+
   if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
 
     if (unlikely(len > MAX_FILE)) len = MAX_FILE;
@@ -1208,6 +1246,36 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
           (fsrv->uses_crash_exitcode &&
            WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
 
+    if (unlikely(fsrv->persistent_replay)) {
+
+      char fn[4096];
+      u32  i, writecnt = 0;
+      for (i = 0; i < fsrv->persistent_replay; ++i) {
+
+        u32 entry = (i + fsrv->persistent_replay_idx) % fsrv->persistent_replay;
+        u8 *data = fsrv->persistent_replay_data[entry];
+        u32 *len = fsrv->persistent_replay_len[entry];
+        if (likely(len && *len && data)) {
+
+          snprintf(fn, sizeof(fn), "%s/replay_%u_%u.bin",
+                   fsrv->persistent_replay_dir, fsrv->persistent_replay_cnt,
+                   writecnt++);
+          int fd = open(fn, O_WRONLY, 0644);
+          if (fd >= 0) {
+
+            ck_write(fd, data, *len, fn);
+            close(fd);
+
+          }
+
+        }
+
+      }
+
+      ++fsrv->persistent_replay_cnt;
+
+    }
+
     /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
     fsrv->last_kill_signal =
         WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 77e6e2ce..f3aea2c7 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1239,9 +1239,10 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->afl_env.afl_persistent_replay) {
+  if (unlikely(afl->afl_env.afl_persistent_replay)) {
 
     afl->fsrv.persistent_replay = atoi(afl->afl_env.afl_persistent_replay);
+    afl->fsrv.persistent_replay_dir = alloc_printf("%s/crashes", afl->out_dir);
 
   }