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.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c
new file mode 100644
index 00000000..3fab1951
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog.c
@@ -0,0 +1,87 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "util.h"
+
+#define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
+
+extern struct cmp_map *__afl_cmp_map;
+
+static GArray *cmplog_ranges = NULL;
+
+static gboolean cmplog_range(const GumRangeDetails *details,
+                             gpointer               user_data) {
+
+  UNUSED_PARAMETER(user_data);
+  GumMemoryRange range = *details->range;
+  g_array_append_val(cmplog_ranges, range);
+  return TRUE;
+
+}
+
+static gint cmplog_sort(gconstpointer a, gconstpointer b) {
+
+  return ((GumMemoryRange *)b)->base_address -
+         ((GumMemoryRange *)a)->base_address;
+
+}
+
+void cmplog_init(void) {
+
+  if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
+
+  cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
+  gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, NULL);
+  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);
+    OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
+        "X",
+        range->base_address, range->base_address + range->size);
+
+  }
+
+}
+
+static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
+                                GumAddress outer_base, GumAddress outer_limit) {
+
+  return (inner_base >= outer_base && inner_limit <= outer_limit);
+
+}
+
+gboolean cmplog_is_readable(void *addr, size_t size) {
+
+  if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
+
+  /*
+   * The Linux kernel prevents mmap from allocating from the very bottom of the
+   * address space to mitigate NULL pointer dereference attacks. The exact size
+   * is set by sysctl by setting mmap_min_addr and 64k is suggested on most
+   * platforms with 32k on ARM systems. We therefore fail fast if the address
+   * is lower than this. This should avoid some overhead when functions are
+   * called where one of the parameters is a size, or a some other small value.
+   */
+  if (GPOINTER_TO_SIZE(addr) < DEFAULT_MMAP_MIN_ADDR) { return false; }
+
+  GumAddress inner_base = GUM_ADDRESS(addr);
+  GumAddress inner_limit = inner_base + size;
+
+  for (guint i = 0; i < cmplog_ranges->len; i++) {
+
+    GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
+    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;
+
+  }
+
+  return false;
+
+}
+