about summary refs log tree commit diff
path: root/frida_mode/src/cmplog
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode/src/cmplog')
-rw-r--r--frida_mode/src/cmplog/cmplog.c110
-rw-r--r--frida_mode/src/cmplog/cmplog_arm.c19
-rw-r--r--frida_mode/src/cmplog/cmplog_arm64.c297
-rw-r--r--frida_mode/src/cmplog/cmplog_x64.c24
-rw-r--r--frida_mode/src/cmplog/cmplog_x86.c2
5 files changed, 47 insertions, 405 deletions
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c
index a2609c8e..7b11c350 100644
--- a/frida_mode/src/cmplog/cmplog.c
+++ b/frida_mode/src/cmplog/cmplog.c
@@ -1,32 +1,19 @@
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "frida-gumjs.h"
+#include "frida-gum.h"
 
 #include "debug.h"
 
 #include "util.h"
 
 #define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
-#define MAX_MEMFD_SIZE (64UL << 10)
 
 extern struct cmp_map *__afl_cmp_map;
-static GArray *        cmplog_ranges = NULL;
-static GHashTable *    hash_yes = NULL;
-static GHashTable *    hash_no = NULL;
 
-static long page_size = 0;
-static long page_offset_mask = 0;
-static long page_mask = 0;
+static GArray *cmplog_ranges = NULL;
 
 static gboolean cmplog_range(const GumRangeDetails *details,
                              gpointer               user_data) {
 
-  GArray *       cmplog_ranges = (GArray *)user_data;
+  UNUSED_PARAMETER(user_data);
   GumMemoryRange range = *details->range;
   g_array_append_val(cmplog_ranges, range);
   return TRUE;
@@ -40,50 +27,20 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) {
 
 }
 
-static void cmplog_get_ranges(void) {
-
-  OKF("CMPLOG - Collecting ranges");
-
-  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);
-
-}
-
-void cmplog_config(void) {
-
-}
-
 void cmplog_init(void) {
 
   if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
 
-  cmplog_get_ranges();
+  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 - %3u: 0x%016" G_GINT64_MODIFIER
-        "X - 0x%016" G_GINT64_MODIFIER "X",
-        i, range->base_address, range->base_address + range->size);
-
-  }
-
-  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 g_hash_table_new, errno: %d", errno);
-
-  }
-
-  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);
+    OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
+        "X",
+        range->base_address, range->base_address + range->size);
 
   }
 
@@ -96,45 +53,6 @@ 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_yes, GSIZE_TO_POINTER(addr))) { return true; }
-  if (g_hash_table_contains(hash_no, GSIZE_TO_POINTER(addr))) { return false; }
-
-  void * page_addr = GSIZE_TO_POINTER(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 msync as a fallback to
-   * validate our address.
-   */
-  if (msync(page_addr, page_offset + size, MS_ASYNC) < 0) {
-
-    if (!g_hash_table_add(hash_no, GSIZE_TO_POINTER(addr))) {
-
-      FATAL("Failed - g_hash_table_add");
-
-    }
-
-    return false;
-
-  } else {
-
-    if (!g_hash_table_add(hash_yes, GSIZE_TO_POINTER(addr))) {
-
-      FATAL("Failed - g_hash_table_add");
-
-    }
-
-    return true;
-
-  }
-
-}
-
 gboolean cmplog_is_readable(guint64 addr, size_t size) {
 
   if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
@@ -149,26 +67,20 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
    */
   if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
 
-  /* Check our addres/length don't wrap around */
-  if (SIZE_MAX - addr < size) { return false; }
-
   GumAddress inner_base = 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;
+    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;
 
   }
 
-  if (cmplog_test_addr(addr, size)) { return true; }
-
   return false;
 
 }
diff --git a/frida_mode/src/cmplog/cmplog_arm.c b/frida_mode/src/cmplog/cmplog_arm.c
new file mode 100644
index 00000000..5af28f3f
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog_arm.c
@@ -0,0 +1,19 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "frida_cmplog.h"
+#include "util.h"
+
+#if defined(__arm__)
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(iterator);
+  if (__afl_cmp_map == NULL) { return; }
+  FATAL("CMPLOG mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/cmplog/cmplog_arm64.c b/frida_mode/src/cmplog/cmplog_arm64.c
index dd97f38d..187d0162 100644
--- a/frida_mode/src/cmplog/cmplog_arm64.c
+++ b/frida_mode/src/cmplog/cmplog_arm64.c
@@ -1,304 +1,17 @@
-#include "frida-gumjs.h"
+#include "frida-gum.h"
 
 #include "debug.h"
-#include "cmplog.h"
 
-#include "ctx.h"
 #include "frida_cmplog.h"
 #include "util.h"
 
 #if defined(__aarch64__)
-
-typedef struct {
-
-  arm64_op_type type;
-  uint8_t       size;
-
-  union {
-
-    arm64_op_mem mem;
-    arm64_reg    reg;
-    int64_t      imm;
-
-  };
-
-} cmplog_ctx_t;
-
-typedef struct {
-
-  cmplog_ctx_t operand1;
-  cmplog_ctx_t operand2;
-  size_t       size;
-
-} cmplog_pair_ctx_t;
-
-static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size,
-                                arm64_op_mem *mem, gsize *val) {
-
-  gsize base = 0;
-  gsize index = 0;
-  gsize address;
-
-  if (mem->base != ARM64_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); }
-
-  if (mem->index != ARM64_REG_INVALID) {
-
-    index = ctx_read_reg(ctx, mem->index);
-
-  }
-
-  address = base + index + mem->disp;
-
-  if (!cmplog_is_readable(address, size)) { return FALSE; }
-
-  switch (size) {
-
-    case 1:
-      *val = *((guint8 *)GSIZE_TO_POINTER(address));
-      return TRUE;
-    case 2:
-      *val = *((guint16 *)GSIZE_TO_POINTER(address));
-      return TRUE;
-    case 4:
-      *val = *((guint32 *)GSIZE_TO_POINTER(address));
-      return TRUE;
-    case 8:
-      *val = *((guint64 *)GSIZE_TO_POINTER(address));
-      return TRUE;
-    default:
-      FATAL("Invalid operand size: %d\n", size);
-
-  }
-
-  return FALSE;
-
-}
-
-static gboolean cmplog_get_operand_value(GumCpuContext *context,
-                                         cmplog_ctx_t *ctx, gsize *val) {
-
-  switch (ctx->type) {
-
-    case ARM64_OP_REG:
-      *val = ctx_read_reg(context, ctx->reg);
-      return TRUE;
-    case ARM64_OP_IMM:
-      *val = ctx->imm;
-      return TRUE;
-    case ARM64_OP_MEM:
-      return cmplog_read_mem(context, ctx->size, &ctx->mem, val);
-    default:
-      FATAL("Invalid operand type: %d\n", ctx->type);
-
-  }
-
-  return FALSE;
-
-}
-
-static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
-
-  UNUSED_PARAMETER(user_data);
-
-  gsize address = context->pc;
-  gsize x0 = ctx_read_reg(context, ARM64_REG_X0);
-  gsize x1 = ctx_read_reg(context, ARM64_REG_X1);
-
-  if (((G_MAXULONG - x0) < 32) || ((G_MAXULONG - x1) < 32)) return;
-
-  if (!cmplog_is_readable(x0, 32) || !cmplog_is_readable(x1, 32)) return;
-
-  void *ptr1 = GSIZE_TO_POINTER(x0);
-  void *ptr2 = GSIZE_TO_POINTER(x1);
-
-  uintptr_t k = address;
-
-  k = (k >> 4) ^ (k << 8);
-  k &= CMP_MAP_W - 1;
-
-  __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
-
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
-
-  __afl_cmp_map->headers[k].shape = 31;
-
-  hits &= CMP_MAP_RTN_H - 1;
-  gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
-             32);
-  gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
-             32);
-
-}
-
-static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
-                                          cs_arm64_op * operand) {
-
-  ctx->type = operand->type;
-  switch (operand->type) {
-
-    case ARM64_OP_REG:
-      gum_memcpy(&ctx->reg, &operand->reg, sizeof(arm64_reg));
-      break;
-    case ARM64_OP_IMM:
-      gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t));
-      break;
-    case ARM64_OP_MEM:
-      gum_memcpy(&ctx->mem, &operand->mem, sizeof(arm64_op_mem));
-      break;
-    default:
-      FATAL("Invalid operand type: %d\n", operand->type);
-
-  }
-
-}
-
-static void cmplog_instrument_call(const cs_insn *     instr,
-                                   GumStalkerIterator *iterator) {
-
-  cs_arm64     arm64 = instr->detail->arm64;
-  cs_arm64_op *operand;
-
-  switch (instr->id) {
-
-    case ARM64_INS_BL:
-    case ARM64_INS_BLR:
-    case ARM64_INS_BLRAA:
-    case ARM64_INS_BLRAAZ:
-    case ARM64_INS_BLRAB:
-    case ARM64_INS_BLRABZ:
-      break;
-    default:
-      return;
-
-  }
-
-  if (arm64.op_count != 1) return;
-
-  operand = &arm64.operands[0];
-
-  if (operand->type == ARM64_OP_INVALID) return;
-
-  gum_stalker_iterator_put_callout(iterator, cmplog_call_callout, NULL, NULL);
-
-}
-
-static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
-                                  gsize operand2, uint8_t size) {
-
-  gsize address = context->pc;
-
-  register uintptr_t k = (uintptr_t)address;
-
-  k = (k >> 4) ^ (k << 8);
-  k &= CMP_MAP_W - 1;
-
-  __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
-
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
-
-  __afl_cmp_map->headers[k].shape = (size - 1);
-
-  hits &= CMP_MAP_H - 1;
-  __afl_cmp_map->log[k][hits].v0 = operand1;
-  __afl_cmp_map->log[k][hits].v1 = operand2;
-
-}
-
-static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
-
-  cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
-  gsize              operand1;
-  gsize              operand2;
-
-  if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
-  if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
-
-  cmplog_handle_cmp_sub(context, operand1, operand2, ctx->size);
-
-}
-
-static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
-                                                  cs_arm64_op *       operand1,
-                                                  cs_arm64_op *       operand2,
-                                                  size_t              size) {
-
-  cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
-  if (ctx == NULL) return;
-
-  cmplog_instrument_put_operand(&ctx->operand1, operand1);
-  cmplog_instrument_put_operand(&ctx->operand2, operand2);
-  ctx->size = size;
-
-  gum_stalker_iterator_put_callout(iterator, cmplog_cmp_sub_callout, ctx,
-                                   g_free);
-
-}
-
-static void cmplog_instrument_cmp_sub(const cs_insn *     instr,
-                                      GumStalkerIterator *iterator) {
-
-  cs_arm64     arm64 = instr->detail->arm64;
-  cs_arm64_op *operand1;
-  cs_arm64_op *operand2;
-  size_t       size;
-
-  switch (instr->id) {
-
-    case ARM64_INS_ADCS:
-    case ARM64_INS_ADDS:
-    case ARM64_INS_ANDS:
-    case ARM64_INS_BICS:
-    case ARM64_INS_CMN:
-    case ARM64_INS_CMP:
-    case ARM64_INS_CMPEQ:
-    case ARM64_INS_CMPGE:
-    case ARM64_INS_CMPGT:
-    case ARM64_INS_CMPHI:
-    case ARM64_INS_CMPHS:
-    case ARM64_INS_CMPLE:
-    case ARM64_INS_CMPLO:
-    case ARM64_INS_CMPLS:
-    case ARM64_INS_CMPLT:
-    case ARM64_INS_CMPNE:
-    case ARM64_INS_EORS:
-    case ARM64_INS_NANDS:
-    case ARM64_INS_NEGS:
-    case ARM64_INS_NGCS:
-    case ARM64_INS_NORS:
-    case ARM64_INS_NOTS:
-    case ARM64_INS_ORNS:
-    case ARM64_INS_ORRS:
-    case ARM64_INS_SBCS:
-    case ARM64_INS_SUBS:
-      break;
-
-    default:
-      return;
-
-  }
-
-  if (arm64.op_count != 2) return;
-
-  operand1 = &arm64.operands[0];
-  operand2 = &arm64.operands[1];
-
-  if (operand1->type == ARM64_OP_INVALID) return;
-  if (operand2->type == ARM64_OP_INVALID) return;
-
-  size = ctx_get_size(instr, &arm64.operands[0]);
-
-  cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2, size);
-
-}
-
 void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
 
-  if (__afl_cmp_map == NULL) return;
-
-  cmplog_instrument_call(instr, iterator);
-  cmplog_instrument_cmp_sub(instr, iterator);
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(iterator);
+  if (__afl_cmp_map == NULL) { return; }
+  FATAL("CMPLOG mode not supported on this architecture");
 
 }
 
diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c
index 0d18767a..9f56c32a 100644
--- a/frida_mode/src/cmplog/cmplog_x64.c
+++ b/frida_mode/src/cmplog/cmplog_x64.c
@@ -1,4 +1,4 @@
-#include "frida-gumjs.h"
+#include "frida-gum.h"
 
 #include "debug.h"
 #include "cmplog.h"
@@ -177,7 +177,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
   register uintptr_t k = (uintptr_t)address;
 
   k = (k >> 4) ^ (k << 8);
-  k &= CMP_MAP_W - 7;
+  k &= CMP_MAP_W - 1;
 
   __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
 
@@ -198,6 +198,8 @@ static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
   gsize              operand1;
   gsize              operand2;
 
+  if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
+
   if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
   if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
 
@@ -231,15 +233,6 @@ static void cmplog_instrument_cmp_sub(const cs_insn *     instr,
 
     case X86_INS_CMP:
     case X86_INS_SUB:
-    case X86_INS_SCASB:
-    case X86_INS_SCASD:
-    case X86_INS_SCASQ:
-    case X86_INS_SCASW:
-    case X86_INS_CMPSB:
-    case X86_INS_CMPSD:
-    case X86_INS_CMPSQ:
-    case X86_INS_CMPSS:
-    case X86_INS_CMPSW:
       break;
     default:
       return;
@@ -254,8 +247,13 @@ static void cmplog_instrument_cmp_sub(const cs_insn *     instr,
   if (operand1->type == X86_OP_INVALID) return;
   if (operand2->type == X86_OP_INVALID) return;
 
-  /* Both operands are the same size */
-  if (operand1->size == 1) { return; }
+  if ((operand1->type == X86_OP_MEM) &&
+      (operand1->mem.segment != X86_REG_INVALID))
+    return;
+
+  if ((operand2->type == X86_OP_MEM) &&
+      (operand2->mem.segment != X86_REG_INVALID))
+    return;
 
   cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2);
 
diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c
index dd666c34..a27df0af 100644
--- a/frida_mode/src/cmplog/cmplog_x86.c
+++ b/frida_mode/src/cmplog/cmplog_x86.c
@@ -1,4 +1,4 @@
-#include "frida-gumjs.h"
+#include "frida-gum.h"
 
 #include "debug.h"
 #include "cmplog.h"