Fixes to memory operands for complog
MODIFY
frida_mode/include/frida_cmplog.h
frida_mode/include/frida_cmplog.h
@@ -8,7 +8,7 @@ void cmplog_init(void);
/* Functions to be implemented by the different architectures */
void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator);
-gboolean cmplog_is_readable(void *addr, size_t size);
+gboolean cmplog_is_readable(guint64 addr, size_t size);
#endif

MODIFY
frida_mode/src/cmplog/cmplog.c
frida_mode/src/cmplog/cmplog.c
@@ -53,7 +53,7 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
}
-gboolean cmplog_is_readable(void *addr, size_t size) {
+gboolean cmplog_is_readable(guint64 addr, size_t size) {
if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
@@ -65,9 +65,9 @@ gboolean cmplog_is_readable(void *addr, size_t size) {
* 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; }
+ if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
- GumAddress inner_base = GUM_ADDRESS(addr);
+ GumAddress inner_base = addr;
GumAddress inner_limit = inner_base + size;
for (guint i = 0; i < cmplog_ranges->len; i++) {

MODIFY
frida_mode/src/cmplog/cmplog_x64.c
frida_mode/src/cmplog/cmplog_x64.c
@@ -134,7 +134,8 @@ static guint64 cmplog_read_reg(GumX64CpuContext *ctx, x86_reg reg) {
}
-static guint64 cmplog_read_mem(GumX64CpuContext *ctx, x86_op_mem *mem) {
+static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size,
+ x86_op_mem *mem, guint64 *val) {
guint64 base = 0;
guint64 index = 0;
@@ -145,26 +146,52 @@ static guint64 cmplog_read_mem(GumX64CpuContext *ctx, x86_op_mem *mem) {
if (mem->index != X86_REG_INVALID) index = cmplog_read_reg(ctx, mem->index);
address = base + (index * mem->scale) + mem->disp;
- return address;
+
+ if (!cmplog_is_readable(address, size)) { return FALSE; }
+
+ switch (size) {
+
+ case 1:
+ *val = *((guint8 *)address);
+ return TRUE;
+ case 2:
+ *val = *((guint16 *)address);
+ return TRUE;
+ case 4:
+ *val = *((guint32 *)address);
+ return TRUE;
+ case 8:
+ *val = *((guint64 *)address);
+ return TRUE;
+ default:
+ FATAL("Invalid operand size: %d\n", size);
+
+ }
+
+ return FALSE;
}
-static guint64 cmplog_get_operand_value(GumCpuContext *context,
- cmplog_ctx_t * ctx) {
+static gboolean cmplog_get_operand_value(GumCpuContext *context,
+ cmplog_ctx_t *ctx, guint64 *val) {
switch (ctx->type) {
case X86_OP_REG:
- return cmplog_read_reg(context, ctx->reg);
+ *val = cmplog_read_reg(context, ctx->reg);
+ return TRUE;
case X86_OP_IMM:
- return ctx->imm;
+ *val = ctx->imm;
+ return TRUE;
case X86_OP_MEM:
- return cmplog_read_mem(context, &ctx->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) {
@@ -177,11 +204,11 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return;
+ if (!cmplog_is_readable(rdi, 32) || !cmplog_is_readable(rsi, 32)) return;
+
void *ptr1 = GSIZE_TO_POINTER(rdi);
void *ptr2 = GSIZE_TO_POINTER(rsi);
- if (!cmplog_is_readable(ptr1, 32) || !cmplog_is_readable(ptr2, 32)) return;
-
uintptr_t k = address;
k = (k >> 4) ^ (k << 8);
@@ -271,11 +298,13 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, guint64 operand1,
static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
+ guint64 operand1;
+ guint64 operand2;
if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
- guint64 operand1 = cmplog_get_operand_value(context, &ctx->operand1);
- guint64 operand2 = cmplog_get_operand_value(context, &ctx->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->operand1.size);

MODIFY
frida_mode/test/cmplog/GNUmakefile
frida_mode/test/cmplog/GNUmakefile
@@ -41,24 +41,24 @@ $(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_DIR)compcovtest.cc
qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
$(ROOT)afl-fuzz \
- -D \
-Q \
-i $(TEST_DATA_DIR) \
-o $(QEMU_OUT) \
-c 0 \
-l 3AT \
+ -Z \
-- \
$(TEST_CMPLOG_OBJ) @@
frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
XAFL_FRIDA_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \
$(ROOT)afl-fuzz \
- -D \
-O \
-i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \
-c 0 \
-l 3AT \
+ -Z \
-- \
$(TEST_CMPLOG_OBJ) @@

Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>