about summary refs log tree commit diff
path: root/frida_mode/src/cmplog/cmplog.c
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode/src/cmplog/cmplog.c')
-rw-r--r--frida_mode/src/cmplog/cmplog.c91
1 files changed, 47 insertions, 44 deletions
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c
index c65b98d0..8814f7f3 100644
--- a/frida_mode/src/cmplog/cmplog.c
+++ b/frida_mode/src/cmplog/cmplog.c
@@ -1,7 +1,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
-#include <syscall.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
 
 #include "frida-gum.h"
 
@@ -13,12 +15,13 @@
 #define MAX_MEMFD_SIZE (64UL << 10)
 
 extern struct cmp_map *__afl_cmp_map;
-static GArray *cmplog_ranges = NULL;
-static GHashTable * hash = NULL;
+static GArray *        cmplog_ranges = NULL;
+static GHashTable *    hash_yes = NULL;
+static GHashTable *    hash_no = NULL;
 
-static int     memfd = -1;
-static size_t  memfd_size = 0;
-static u8 scratch[MAX_MEMFD_SIZE] = {0};
+static long page_size = 0;
+static long page_offset_mask = 0;
+static long page_mask = 0;
 
 static gboolean cmplog_range(const GumRangeDetails *details,
                              gpointer               user_data) {
@@ -41,19 +44,10 @@ static void cmplog_get_ranges(void) {
 
   OKF("CMPLOG - Collecting ranges");
 
-  cmplog_ranges =
-      g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
+  cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
   gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges);
   g_array_sort(cmplog_ranges, cmplog_sort);
 
-  for (guint i = 0; i < cmplog_ranges->len; i++) {
-
-    GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
-
-  }
-
-  g_array_free(cmplog_ranges, TRUE);
-
 }
 
 void cmplog_init(void) {
@@ -71,16 +65,22 @@ void cmplog_init(void) {
 
   }
 
-  memfd = syscall(__NR_memfd_create, "cmplog_memfd", 0);
-  if (memfd < 0) {
+  page_size = sysconf(_SC_PAGE_SIZE);
+  page_offset_mask = page_size - 1;
+  page_mask = ~(page_offset_mask);
+
+  hash_yes = g_hash_table_new(g_direct_hash, g_direct_equal);
+  if (hash_yes == NULL) {
 
-    FATAL("Failed to create_memfd, errno: %d", errno);
+    FATAL("Failed to g_hash_table_new, errno: %d", errno);
 
   }
 
-  hash = g_hash_table_new (g_direct_hash, g_direct_equal);
-  if (hash == NULL) {
+  hash_no = g_hash_table_new(g_direct_hash, g_direct_equal);
+  if (hash_no == NULL) {
+
     FATAL("Failed to g_hash_table_new, errno: %d", errno);
+
   }
 
 }
@@ -94,38 +94,41 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
 
 gboolean cmplog_test_addr(guint64 addr, size_t size) {
 
-  if (g_hash_table_contains(hash, (gpointer)addr)) { return true; }
+  if (g_hash_table_contains(hash_yes, (gpointer)addr)) { return true; }
+  if (g_hash_table_contains(hash_no, (gpointer)addr)) { return false; }
 
-  if (memfd_size > MAX_MEMFD_SIZE) {
-    if (lseek(memfd, 0, SEEK_SET) < 0) {
-      FATAL("CMPLOG - Failed lseek, errno: %d", errno);
-    }
-  }
+  void * page_addr = (void *)(addr & page_mask);
+  size_t page_offset = addr & page_offset_mask;
+
+  /* If it spans a page, then bail */
+  if (page_size - page_offset < size) { return false; }
 
   /*
-   * Our address map can change (e.g. stack growth), use write as a fallback to
+   * Our address map can change (e.g. stack growth), use msync as a fallback to
    * validate our address.
    */
-  ssize_t written = syscall(SYS_write, memfd, (void *)addr, size);
-  if (written < 0 && errno != EFAULT && errno != 0) {
-    FATAL("CMPLOG - Failed __NR_write, errno: %d", errno);
-  }
-  /*
-   * If the write succeeds, then the buffer must be valid otherwise it would
-   * return EFAULT
-   */
-  if (written > 0) { memfd_size += written; }
+  if (msync(page_addr, page_offset + size, MS_ASYNC) < 0) {
+
+    if (!g_hash_table_add(hash_no, (gpointer)addr)) {
 
-  if ((size_t)written == size) {
-    if (!g_hash_table_add (hash, (gpointer)addr)) {
       FATAL("Failed - g_hash_table_add");
+
     }
-    return true;
-  }
 
+    return false;
 
+  } else {
+
+    if (!g_hash_table_add(hash_yes, (gpointer)addr)) {
+
+      FATAL("Failed - g_hash_table_add");
+
+    }
+
+    return true;
+
+  }
 
-  return false;
 }
 
 gboolean cmplog_is_readable(guint64 addr, size_t size) {
@@ -152,8 +155,8 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
 
     GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
 
-    GumAddress      outer_base = range->base_address;
-    GumAddress      outer_limit = outer_base + range->size;
+    GumAddress outer_base = range->base_address;
+    GumAddress outer_limit = outer_base + range->size;
 
     if (cmplog_contains(inner_base, inner_limit, outer_base, outer_limit))
       return true;