diff options
Diffstat (limited to 'frida_mode/src/cmplog')
-rw-r--r-- | frida_mode/src/cmplog/cmplog.c | 110 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_arm.c | 19 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_arm64.c | 297 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_x64.c | 24 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_x86.c | 2 |
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" |