diff options
37 files changed, 1176 insertions, 102 deletions
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index a15f5c32..e915f157 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -19,6 +19,7 @@ RT_CFLAGS:=-Wno-unused-parameter \ -Wno-sign-compare \ -Wno-unused-function \ -Wno-unused-result \ + -Wno-int-to-pointer-cast \ LDFLAGS+=-shared \ -lpthread \ @@ -38,6 +39,8 @@ FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/ FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded +ifndef ARCH + ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" ARCH:=arm64 @@ -46,6 +49,7 @@ endif ifeq "$(ARCH)" "i686" ARCH:=x86 endif +endif ifeq "$(shell uname)" "Darwin" OS:=macos @@ -83,13 +87,16 @@ FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME) AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o -.PHONY: all clean format $(FRIDA_GUM) +.PHONY: all 32 clean format $(FRIDA_GUM) ############################## ALL ############################################# all: $(FRIDA_TRACE) make -C $(ROOT) +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $(BUILD_DIR) @@ -161,11 +168,11 @@ $(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $( $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR) $(CC) \ - -o $@ \ $(OBJS) \ $(GUM_DEVIT_LIBRARY) \ $(AFL_COMPILER_RT_OBJ) \ $(LDFLAGS) \ + -o $@ \ cp -v $(FRIDA_TRACE) $(ROOT) diff --git a/frida_mode/Makefile b/frida_mode/Makefile index b6d64bff..6cd1a64e 100644 --- a/frida_mode/Makefile +++ b/frida_mode/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean diff --git a/frida_mode/include/ctx.h b/frida_mode/include/ctx.h index 030d124a..cbcc892a 100644 --- a/frida_mode/include/ctx.h +++ b/frida_mode/include/ctx.h @@ -3,8 +3,8 @@ #include "frida-gum.h" -#if defined(__x86_64__) -guint64 ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg); +#if defined(__x86_64__) || defined(__i386__) +gsize ctx_read_reg(GumCpuContext *ctx, x86_reg reg); #endif #endif diff --git a/frida_mode/src/asan/asan_arm.c b/frida_mode/src/asan/asan_arm.c index 526017be..79475ced 100644 --- a/frida_mode/src/asan/asan_arm.c +++ b/frida_mode/src/asan/asan_arm.c @@ -18,5 +18,11 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { } +void asan_arch_init(void) { + + FATAL("ASAN mode not supported on this architecture"); + +} + #endif diff --git a/frida_mode/src/asan/asan_arm64.c b/frida_mode/src/asan/asan_arm64.c index 4e3fbafd..6262ee18 100644 --- a/frida_mode/src/asan/asan_arm64.c +++ b/frida_mode/src/asan/asan_arm64.c @@ -18,5 +18,11 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { } +void asan_arch_init(void) { + + FATAL("ASAN mode not supported on this architecture"); + +} + #endif diff --git a/frida_mode/src/asan/asan_x64.c b/frida_mode/src/asan/asan_x64.c index bdf4ac30..a2eabe3c 100644 --- a/frida_mode/src/asan/asan_x64.c +++ b/frida_mode/src/asan/asan_x64.c @@ -7,23 +7,23 @@ #include "ctx.h" #include "util.h" +#if defined(__x86_64__) + typedef void (*asan_loadN_t)(uint64_t address, uint8_t size); typedef void (*asan_storeN_t)(uint64_t address, uint8_t size); asan_loadN_t asan_loadN = NULL; asan_storeN_t asan_storeN = NULL; -#if defined(__x86_64__) - static void asan_callout(GumCpuContext *ctx, gpointer user_data) { UNUSED_PARAMETER(user_data); cs_x86_op * operand = (cs_x86_op *)user_data; x86_op_mem *mem = &operand->mem; - uint64_t base = 0; - uint64_t index = 0; - uint64_t address; + gsize base = 0; + gsize index = 0; + gsize address; uint8_t size; if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); } diff --git a/frida_mode/src/asan/asan_x86.c b/frida_mode/src/asan/asan_x86.c index b946b3bf..8490b490 100644 --- a/frida_mode/src/asan/asan_x86.c +++ b/frida_mode/src/asan/asan_x86.c @@ -1,18 +1,89 @@ +#include <dlfcn.h> #include "frida-gum.h" #include "debug.h" #include "asan.h" +#include "ctx.h" #include "util.h" #if defined(__i386__) + +typedef void (*asan_loadN_t)(gsize address, uint8_t size); +typedef void (*asan_storeN_t)(gsize address, uint8_t size); + +asan_loadN_t asan_loadN = NULL; +asan_storeN_t asan_storeN = NULL; + +static void asan_callout(GumCpuContext *ctx, gpointer user_data) { + + UNUSED_PARAMETER(user_data); + + cs_x86_op * operand = (cs_x86_op *)user_data; + x86_op_mem *mem = &operand->mem; + gsize base = 0; + gsize index = 0; + gsize address; + uint8_t size; + + if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); } + + if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); } + + address = base + (mem->scale * index) + mem->disp; + size = operand->size; + + if (operand->access == CS_AC_READ) { + + asan_loadN(address, size); + + } else if (operand->access == CS_AC_WRITE) { + + asan_storeN(address, size); + + } + +} + void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { - UNUSED_PARAMETER(instr); UNUSED_PARAMETER(iterator); - if (asan_initialized) { - FATAL("ASAN mode not supported on this architecture"); + cs_x86 x86 = instr->detail->x86; + cs_x86_op * operand; + x86_op_mem *mem; + cs_x86_op * ctx; + + if (!asan_initialized) return; + + if (instr->id == X86_INS_LEA) return; + + if (instr->id == X86_INS_NOP) return; + + for (uint8_t i = 0; i < x86.op_count; i++) { + + operand = &x86.operands[i]; + + if (operand->type != X86_OP_MEM) { continue; } + + mem = &operand->mem; + if (mem->segment != X86_REG_INVALID) { continue; } + + ctx = g_malloc0(sizeof(cs_x86_op)); + memcpy(ctx, operand, sizeof(cs_x86_op)); + gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free); + + } + +} + +void asan_arch_init(void) { + + asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN"); + asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN"); + if (asan_loadN == NULL || asan_storeN == NULL) { + + FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'"); } diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c index c3621a29..9f56c32a 100644 --- a/frida_mode/src/cmplog/cmplog_x64.c +++ b/frida_mode/src/cmplog/cmplog_x64.c @@ -31,12 +31,12 @@ typedef struct { } cmplog_pair_ctx_t; -static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size, - x86_op_mem *mem, guint64 *val) { +static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size, + x86_op_mem *mem, gsize *val) { - guint64 base = 0; - guint64 index = 0; - guint64 address; + gsize base = 0; + gsize index = 0; + gsize address; if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base); @@ -49,16 +49,16 @@ static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size, switch (size) { case 1: - *val = *((guint8 *)address); + *val = *((guint8 *)GSIZE_TO_POINTER(address)); return TRUE; case 2: - *val = *((guint16 *)address); + *val = *((guint16 *)GSIZE_TO_POINTER(address)); return TRUE; case 4: - *val = *((guint32 *)address); + *val = *((guint32 *)GSIZE_TO_POINTER(address)); return TRUE; case 8: - *val = *((guint64 *)address); + *val = *((guint64 *)GSIZE_TO_POINTER(address)); return TRUE; default: FATAL("Invalid operand size: %d\n", size); @@ -70,7 +70,7 @@ static gboolean cmplog_read_mem(GumX64CpuContext *ctx, uint8_t size, } static gboolean cmplog_get_operand_value(GumCpuContext *context, - cmplog_ctx_t *ctx, guint64 *val) { + cmplog_ctx_t *ctx, gsize *val) { switch (ctx->type) { @@ -95,9 +95,9 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) { UNUSED_PARAMETER(user_data); - guint64 address = ctx_read_reg(context, X86_REG_RIP); - guint64 rdi = ctx_read_reg(context, X86_REG_RDI); - guint64 rsi = ctx_read_reg(context, X86_REG_RSI); + gsize address = ctx_read_reg(context, X86_REG_RIP); + gsize rdi = ctx_read_reg(context, X86_REG_RDI); + gsize rsi = ctx_read_reg(context, X86_REG_RSI); if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return; @@ -169,10 +169,10 @@ static void cmplog_instrument_call(const cs_insn * instr, } -static void cmplog_handle_cmp_sub(GumCpuContext *context, guint64 operand1, - guint64 operand2, uint8_t size) { +static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, + gsize operand2, uint8_t size) { - guint64 address = ctx_read_reg(context, X86_REG_RIP); + gsize address = ctx_read_reg(context, X86_REG_RIP); register uintptr_t k = (uintptr_t)address; @@ -195,8 +195,8 @@ 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; + gsize operand1; + gsize operand2; if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch"); diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c index 2401180c..a27df0af 100644 --- a/frida_mode/src/cmplog/cmplog_x86.c +++ b/frida_mode/src/cmplog/cmplog_x86.c @@ -1,17 +1,275 @@ #include "frida-gum.h" #include "debug.h" +#include "cmplog.h" +#include "ctx.h" #include "frida_cmplog.h" #include "util.h" #if defined(__i386__) + +typedef struct { + + x86_op_type type; + uint8_t size; + + union { + + x86_op_mem mem; + x86_reg reg; + int64_t imm; + + }; + +} cmplog_ctx_t; + +typedef struct { + + cmplog_ctx_t operand1; + cmplog_ctx_t operand2; + +} cmplog_pair_ctx_t; + +static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size, + x86_op_mem *mem, gsize *val) { + + gsize base = 0; + gsize index = 0; + gsize address; + + if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base); + + if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index); + + address = base + (index * mem->scale) + 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; + 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 X86_OP_REG: + *val = ctx_read_reg(context, ctx->reg); + return TRUE; + case X86_OP_IMM: + *val = ctx->imm; + return TRUE; + case X86_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 = ctx_read_reg(context, X86_REG_EIP); + gsize *esp = (gsize *)ctx_read_reg(context, X86_REG_ESP); + + if (!cmplog_is_readable(GPOINTER_TO_SIZE(esp), 12)) return; + + /* + * This callout is place immediately before the call instruction, and hence + * the return address is not yet pushed on the top of the stack. + */ + gsize arg1 = esp[0]; + gsize arg2 = esp[1]; + + if (((G_MAXULONG - arg1) < 32) || ((G_MAXULONG - arg2) < 32)) return; + + if (!cmplog_is_readable(arg1, 32) || !cmplog_is_readable(arg2, 32)) return; + + void *ptr1 = GSIZE_TO_POINTER(arg1); + void *ptr2 = GSIZE_TO_POINTER(arg2); + + 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_x86_op * operand) { + + ctx->type = operand->type; + ctx->size = operand->size; + switch (operand->type) { + + case X86_OP_REG: + gum_memcpy(&ctx->reg, &operand->reg, sizeof(x86_reg)); + break; + case X86_OP_IMM: + gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t)); + break; + case X86_OP_MEM: + gum_memcpy(&ctx->mem, &operand->mem, sizeof(x86_op_mem)); + break; + default: + FATAL("Invalid operand type: %d\n", operand->type); + + } + +} + +static void cmplog_instrument_call(const cs_insn * instr, + GumStalkerIterator *iterator) { + + cs_x86 x86 = instr->detail->x86; + cs_x86_op *operand; + + if (instr->id != X86_INS_CALL) return; + + if (x86.op_count != 1) return; + + operand = &x86.operands[0]; + + if (operand->type == X86_OP_INVALID) return; + if (operand->type == X86_OP_MEM && operand->mem.segment != X86_REG_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 = ctx_read_reg(context, X86_REG_EIP); + + 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 (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; } + + cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size); + +} + +static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator, + cs_x86_op * operand1, + cs_x86_op *operand2) { + + 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); + + 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_x86 x86 = instr->detail->x86; + cs_x86_op *operand1; + cs_x86_op *operand2; + + switch (instr->id) { + + case X86_INS_CMP: + case X86_INS_SUB: + break; + default: + return; + + } + + if (x86.op_count != 2) return; + + operand1 = &x86.operands[0]; + operand2 = &x86.operands[1]; + + if (operand1->type == X86_OP_INVALID) return; + if (operand2->type == X86_OP_INVALID) 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); + +} + 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"); + if (__afl_cmp_map == NULL) return; + + cmplog_instrument_call(instr, iterator); + cmplog_instrument_cmp_sub(instr, iterator); } diff --git a/frida_mode/src/ctx/ctx_x64.c b/frida_mode/src/ctx/ctx_x64.c index dec759f4..c5900533 100644 --- a/frida_mode/src/ctx/ctx_x64.c +++ b/frida_mode/src/ctx/ctx_x64.c @@ -41,7 +41,7 @@ \ } -guint64 ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) { +gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) { switch (reg) { diff --git a/frida_mode/src/ctx/ctx_x86.c b/frida_mode/src/ctx/ctx_x86.c new file mode 100644 index 00000000..45308272 --- /dev/null +++ b/frida_mode/src/ctx/ctx_x86.c @@ -0,0 +1,81 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "ctx.h" + +#if defined(__i386__) + + #define X86_REG_8L(LABEL, REG) \ + case LABEL: { \ + \ + return REG & GUM_INT8_MASK; \ + \ + } + + #define X86_REG_8H(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT16_MASK) >> 8; \ + \ + } + + #define X86_REG_16(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT16_MASK); \ + \ + } + + #define X86_REG_32(LABEL, REG) \ + case LABEL: { \ + \ + return (REG & GUM_INT32_MASK); \ + \ + } + +gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) { + + switch (reg) { + + X86_REG_8L(X86_REG_AL, ctx->eax) + X86_REG_8L(X86_REG_BL, ctx->ebx) + X86_REG_8L(X86_REG_CL, ctx->ecx) + X86_REG_8L(X86_REG_DL, ctx->edx) + X86_REG_8L(X86_REG_BPL, ctx->ebp) + X86_REG_8L(X86_REG_SIL, ctx->esi) + X86_REG_8L(X86_REG_DIL, ctx->edi) + + X86_REG_8H(X86_REG_AH, ctx->eax) + X86_REG_8H(X86_REG_BH, ctx->ebx) + X86_REG_8H(X86_REG_CH, ctx->ecx) + X86_REG_8H(X86_REG_DH, ctx->edx) + + X86_REG_16(X86_REG_AX, ctx->eax) + X86_REG_16(X86_REG_BX, ctx->ebx) + X86_REG_16(X86_REG_CX, ctx->ecx) + X86_REG_16(X86_REG_DX, ctx->edx) + X86_REG_16(X86_REG_DI, ctx->edi) + X86_REG_16(X86_REG_SI, ctx->esi) + X86_REG_16(X86_REG_BP, ctx->ebp) + + X86_REG_32(X86_REG_EAX, ctx->eax) + X86_REG_32(X86_REG_ECX, ctx->ecx) + X86_REG_32(X86_REG_EDX, ctx->edx) + X86_REG_32(X86_REG_EBX, ctx->ebx) + X86_REG_32(X86_REG_ESP, ctx->esp) + X86_REG_32(X86_REG_EBP, ctx->ebp) + X86_REG_32(X86_REG_ESI, ctx->esi) + X86_REG_32(X86_REG_EDI, ctx->edi) + X86_REG_32(X86_REG_EIP, ctx->eip) + + default: + FATAL("Failed to read register: %d", reg); + return 0; + + } + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 5c77ade6..67eadc3f 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -34,7 +34,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, */ static char buffer[200]; int len; - guint64 current_pc = (guint64)user_data; + GumAddress current_pc = GUM_ADDRESS(user_data); uint8_t * cursor; uint64_t value; if (unlikely(tracing)) { @@ -86,8 +86,8 @@ static void instr_basic_block(GumStalkerIterator *iterator, if (begin) { - prefetch_write((void *)instr->address); - if (!range_is_excluded((void *)instr->address)) { + prefetch_write(GSIZE_TO_POINTER(instr->address)); + if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) { if (optimize) { @@ -95,8 +95,8 @@ static void instr_basic_block(GumStalkerIterator *iterator, } else { - gum_stalker_iterator_put_callout(iterator, on_basic_block, - (gpointer)instr->address, NULL); + gum_stalker_iterator_put_callout( + iterator, on_basic_block, GSIZE_TO_POINTER(instr->address), NULL); } @@ -106,7 +106,7 @@ static void instr_basic_block(GumStalkerIterator *iterator, } - if (!range_is_excluded((void *)instr->address)) { + if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) { asan_instrument(instr, iterator); cmplog_instrument(instr, iterator); diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index c2d720a7..1a3c40bb 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -3,6 +3,7 @@ #include "debug.h" #include "instrument.h" +#include "util.h" #if defined(__arm__) @@ -15,6 +16,8 @@ gboolean instrument_is_coverage_optimize_supported(void) { void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); FATAL("Optimized coverage not supported on this architecture"); } diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index 5b8cbbba..585bb5b8 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -3,19 +3,81 @@ #include "debug.h" #include "instrument.h" +#include "util.h" #if defined(__i386__) +static GumAddress current_log_impl = GUM_ADDRESS(0); + +static void instrument_coverage_function(GumX86Writer *cw) { + + gum_x86_writer_put_pushfx(cw); + gum_x86_writer_put_push_reg(cw, GUM_REG_ECX); + gum_x86_writer_put_push_reg(cw, GUM_REG_EDX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, + GUM_ADDRESS(&previous_pc)); + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_EDX, GUM_REG_ECX); + gum_x86_writer_put_xor_reg_reg(cw, GUM_REG_EDX, GUM_REG_EDI); + + gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EDX, GUM_ADDRESS(__afl_area_ptr)); + + /* add byte ptr [edx], 1 */ + uint8_t add_byte_ptr_edx_1[] = {0x80, 0x02, 0x01}; + gum_x86_writer_put_bytes(cw, add_byte_ptr_edx_1, sizeof(add_byte_ptr_edx_1)); + + /* adc byte ptr [edx], 0 */ + uint8_t adc_byte_ptr_edx_0[] = {0x80, 0x12, 0x00}; + gum_x86_writer_put_bytes(cw, adc_byte_ptr_edx_0, sizeof(adc_byte_ptr_edx_0)); + + gum_x86_writer_put_shr_reg_u8(cw, GUM_REG_EDI, 1); + gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_ECX, GUM_REG_EDI); + + gum_x86_writer_put_pop_reg(cw, GUM_REG_EDX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_ECX); + gum_x86_writer_put_popfx(cw); + gum_x86_writer_put_ret(cw); + +} + gboolean instrument_is_coverage_optimize_supported(void) { - return false; + return true; } void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { - FATAL("Optimized coverage not supported on this architecture"); + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + + guint64 current_pc = instr->address; + guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8); + area_offset &= MAP_SIZE - 1; + GumX86Writer *cw = output->writer.x86; + + if (current_log_impl == 0 || + !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) || + !gum_x86_writer_can_branch_directly_between(cw->pc + 128, + current_log_impl)) { + + gconstpointer after_log_impl = cw->code + 1; + + gum_x86_writer_put_jmp_near_label(cw, after_log_impl); + + current_log_impl = cw->pc; + instrument_coverage_function(cw); + + gum_x86_writer_put_label(cw, after_log_impl); + + } + + // gum_x86_writer_put_breakpoint(cw); + gum_x86_writer_put_push_reg(cw, GUM_REG_EDI); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDI, area_offset); + gum_x86_writer_put_call_address(cw, current_log_impl); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EDI); } diff --git a/frida_mode/src/lib/lib.c b/frida_mode/src/lib/lib.c index c5045533..13a7d1e7 100644 --- a/frida_mode/src/lib/lib.c +++ b/frida_mode/src/lib/lib.c @@ -90,7 +90,8 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) { if (!found_preferred_base) { FATAL("Failed to find preferred load address"); } - OKF("Image preferred load address 0x%016lx", preferred_base); + OKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x", + preferred_base); shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff); shstrtab = &shdr[hdr->e_shstrndx]; @@ -107,15 +108,16 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) { if (curr->sh_name == 0) continue; section_name = &shstr[curr->sh_name]; - OKF("Section: %2lu - base: 0x%016lX size: 0x%016lX %s", i, curr->sh_addr, - curr->sh_size, section_name); + OKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER + "X size: 0x%016" G_GSIZE_MODIFIER "X %s", + i, curr->sh_addr, curr->sh_size, section_name); if (memcmp(section_name, text_name, sizeof(text_name)) == 0 && text_base == 0) { text_base = lib_details->base_address + curr->sh_addr - preferred_base; text_limit = text_base + curr->sh_size; - OKF("> text_addr: 0x%016lX", text_base); - OKF("> text_limit: 0x%016lX", text_limit); + OKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base); + OKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit); } @@ -153,7 +155,8 @@ void lib_init(void) { lib_details_t lib_details; gum_process_enumerate_modules(lib_find_exe, &lib_details); - OKF("Executable: 0x%016lx - %s", lib_details.base_address, lib_details.path); + OKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s", lib_details.base_address, + lib_details.path); lib_get_text_section(&lib_details); } diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index 9d39c4e9..bd7171b9 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -1,9 +1,9 @@ #include "frida-gum.h" -#include "debug.h" +#include "config.h" +#include "instrument.h" #include "persistent.h" -#include "util.h" #if defined(__i386__) @@ -38,16 +38,239 @@ struct x86_regs { typedef struct x86_regs arch_api_regs; +static arch_api_regs saved_regs = {0}; +static void * saved_return = NULL; + gboolean persistent_is_supported(void) { - return false; + return true; + +} + +static void instrument_persitent_save_regs(GumX86Writer * cw, + struct x86_regs *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + + /* Should be pushing FPU here, but meh */ + gum_x86_writer_put_pushfx(cw); + gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 1), + GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 2), + GUM_REG_ECX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 3), + GUM_REG_EDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 4), + GUM_REG_EDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 5), + GUM_REG_ESI); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 6), + GUM_REG_EBP); + + /* Store RIP */ + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EBX, + GUM_ADDRESS(persistent_start)); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 7), + GUM_REG_EBX); + + /* Store adjusted RSP */ + gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_EBX, GUM_REG_ESP); + + /* RED_ZONE + Saved flags, RAX */ + gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EBX, (0x4 * 2)); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 8), + GUM_REG_EBX); + + /* Save the flags */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x4); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 9), + GUM_REG_EBX); + + /* Save the RAX */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x0); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 0), + GUM_REG_EBX); + + /* Pop the saved values */ + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 0x8); + +} + +static void instrument_persitent_restore_regs(GumX86Writer * cw, + struct x86_regs *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address); + + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_EAX, + (0x4 * 2)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX, + (0x4 * 3)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX, + (0x4 * 4)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX, + (0x4 * 5)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX, + (0x4 * 6)); + + /* Don't restore RIP or RSP */ + + /* Restore RBX, RAX & Flags */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, + (0x4 * 1)); + gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); + + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, + (0x4 * 0)); + gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, + (0x4 * 9)); + gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); + + gum_x86_writer_put_popfx(cw); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX); + +} + +static void instrument_save_ret(GumX86Writer *cw, void **saved_return_ptr) { + + GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); + + gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); + gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x8); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, 0, GUM_REG_EBX); + + gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); + +} + +static void instrument_jump_ret(GumX86Writer *cw, void **saved_return_ptr) { + + GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); + + /* Place holder for ret */ + gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); + gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EAX, GUM_REG_EAX, 0); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_ESP, 0x4, GUM_REG_EAX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); + gum_x86_writer_put_ret(cw); + +} + +static int instrument_afl_persistent_loop_func(void) { + + int ret = __afl_persistent_loop(persistent_count); + previous_pc = 0; + return ret; + +} + +static void instrument_afl_persistent_loop(GumX86Writer *cw) { + + gum_x86_writer_put_call_address_with_arguments( + cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); + gum_x86_writer_put_test_reg_reg(cw, GUM_REG_EAX, GUM_REG_EAX); + +} + +static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { + + if (hook == NULL) return; + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, + GUM_ADDRESS(&__afl_fuzz_len)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDX, + GUM_ADDRESS(&__afl_fuzz_ptr)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EDX, 0); + + /* Base address is 64-bits (hence two zero arguments) */ + gum_x86_writer_put_call_address_with_arguments( + cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 5, GUM_ARG_ADDRESS, + GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS, + GUM_ADDRESS(0), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER, + GUM_REG_ECX); } void persistent_prologue(GumStalkerOutput *output) { - UNUSED_PARAMETER(output); - FATAL("Persistent mode not supported on this architecture"); + /* + * SAVE REGS + * SAVE RET + * POP RET + * loop: + * CALL instrument_afl_persistent_loop + * TEST EAX, EAX + * JZ end: + * call hook (optionally) + * RESTORE REGS + * call original + * jmp loop: + * + * end: + * JMP SAVED RET + * + * original: + * INSTRUMENTED PERSISTENT FUNC + */ + + GumX86Writer *cw = output->writer.x86; + + gconstpointer loop = cw->code + 1; + + /* Stack must be 16-byte aligned per ABI */ + instrument_persitent_save_regs(cw, &saved_regs); + + /* Stash and pop the return value */ + instrument_save_ret(cw, &saved_return); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4)); + + /* loop: */ + gum_x86_writer_put_label(cw, loop); + + /* call instrument_prologue_func */ + instrument_afl_persistent_loop(cw); + + /* jz done */ + gconstpointer done = cw->code + 1; + gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY); + + /* Optionally call the persistent hook */ + persistent_prologue_hook(cw, &saved_regs); + + instrument_persitent_restore_regs(cw, &saved_regs); + gconstpointer original = cw->code + 1; + /* call original */ + gum_x86_writer_put_call_near_label(cw, original); + /* jmp loop */ + gum_x86_writer_put_jmp_near_label(cw, loop); + + /* done: */ + gum_x86_writer_put_label(cw, done); + + instrument_jump_ret(cw, &saved_return); + + /* original: */ + gum_x86_writer_put_label(cw, original); + + gum_x86_writer_flush(cw); } diff --git a/frida_mode/test/cmplog/GNUmakefile b/frida_mode/test/cmplog/GNUmakefile index 37c7450c..40de6a09 100644 --- a/frida_mode/test/cmplog/GNUmakefile +++ b/frida_mode/test/cmplog/GNUmakefile @@ -2,8 +2,8 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../../)/ BUILD_DIR:=$(PWD)build/ -TEST_CMPLOG_DIR:=$(ROOT)qemu_mode/libcompcov/ -TEST_CMPLOG_OBJ=$(TEST_CMPLOG_DIR)compcovtest +TEST_CMPLOG_SRC=$(PWD)cmplog.c +TEST_CMPLOG_OBJ=$(BUILD_DIR)compcovtest TEST_BIN:=$(PWD)../../build/test @@ -13,20 +13,14 @@ CMP_LOG_INPUT:=$(TEST_DATA_DIR)in QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -ARCH=$(shell uname -m) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_INST_RANGES=$(shell $(PWD)get_section_addrs.py -f $(TEST_CMPLOG_OBJ) -s .text -b 0x0000aaaaaaaaa000) -endif +.PHONY: all 32 clean qemu frida format -ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_INST_RANGES=$(shell $(PWD)get_section_addrs.py -f $(TEST_CMPLOG_OBJ) -s .text -b 0x0000555555554000) -endif - -.PHONY: all clean qemu frida - -all: +all: $(TEST_CMPLOG_OBJ) make -C $(ROOT)frida_mode/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -34,10 +28,10 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(CMP_LOG_INPUT): | $(TEST_DATA_DIR) - truncate -s 64 $@ + echo -n "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" > $@ -$(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_DIR)compcovtest.cc - make -C $(TEST_CMPLOG_DIR) compcovtest +$(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_SRC) | $(BUILD_DIR) + $(CXX) -std=c++11 -g $(CFLAGS) $(LDFLAGS) $< -o $@ qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) $(ROOT)afl-fuzz \ @@ -51,7 +45,6 @@ qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) $(TEST_CMPLOG_OBJ) @@ frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) - XAFL_FRIDA_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \ $(ROOT)afl-fuzz \ -O \ -i $(TEST_DATA_DIR) \ @@ -62,5 +55,15 @@ frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) -- \ $(TEST_CMPLOG_OBJ) @@ +debug: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --ex 'r $(CMP_LOG_INPUT)' \ + --args $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) + clean: rm -rf $(BUILD_DIR) + +format: + cd $(ROOT) && echo $(TEST_CMPLOG_SRC) | xargs -L1 ./.custom-format.py -i diff --git a/frida_mode/test/cmplog/Makefile b/frida_mode/test/cmplog/Makefile index f322d1f5..606b43a5 100644 --- a/frida_mode/test/cmplog/Makefile +++ b/frida_mode/test/cmplog/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -9,4 +13,10 @@ qemu: @gmake qemu frida: - @gmake frida \ No newline at end of file + @gmake frida + +format: + @gmake format + +debug: + @gmake debug diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c new file mode 100644 index 00000000..99010645 --- /dev/null +++ b/frida_mode/test/cmplog/cmplog.c @@ -0,0 +1,100 @@ +///////////////////////////////////////////////////////////////////////// +// +// Author: Mateusz Jurczyk (mjurczyk@google.com) +// +// Copyright 2019-2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// solution: echo -ne 'The quick brown fox jumps over the lazy +// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc, char **argv) { + + char buffer[44] = {/* zero padding */}; + + FILE *file = stdin; + + if (argc > 1) { + + if ((file = fopen(argv[1], "r")) == NULL) { + + perror(argv[1]); + exit(-1); + + } + + } + + fread(buffer, 1, sizeof(buffer) - 1, file); + + if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 || + strncmp(&buffer[20], "jumps over ", 11) != 0 || + strcmp(&buffer[31], "the lazy dog") != 0) { + + if (argc > 1) { fclose(file); } + return 1; + + } + +#if defined(__x86_64__) + uint64_t x = 0; + fread(&x, sizeof(x), 1, file); + if (x != 0xCAFEBABECAFEBABE) { + + if (argc > 1) { fclose(file); } + return 2; + + } + +#endif + + uint32_t y = 0; + fread(&y, sizeof(y), 1, file); + + if (y != 0xDEADC0DE) { + + if (argc > 1) { fclose(file); } + return 3; + + } + + uint16_t z = 0; + fread(&z, sizeof(z), 1, file); + + switch (z) { + + case 0xBEEF: + break; + + default: + if (argc > 1) { fclose(file); } + return 4; + + } + + printf("Puzzle solved, congrats!\n"); + abort(); + + if (argc > 1) { fclose(file); } + + return 0; + +} + diff --git a/frida_mode/test/entry_point/GNUmakefile b/frida_mode/test/entry_point/GNUmakefile index 891827eb..c99bcecb 100644 --- a/frida_mode/test/entry_point/GNUmakefile +++ b/frida_mode/test/entry_point/GNUmakefile @@ -12,6 +12,18 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000) @@ -21,11 +33,18 @@ ifeq "$(ARCH)" "x86_64" AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000) endif +ifeq "$(ARCH)" "x86" + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000) +endif + .PHONY: all clean qemu frida all: $(TESTINSTBIN) make -C $(ROOT)frida_mode/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -36,7 +55,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean: rm -rf $(BUILD_DIR) @@ -58,4 +77,4 @@ frida_entry: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) -i $(TESTINSTR_DATA_DIR) \ -o $(FRIDA_OUT) \ -- \ - $(TESTINSTBIN) @@ \ No newline at end of file + $(TESTINSTBIN) @@ diff --git a/frida_mode/test/entry_point/Makefile b/frida_mode/test/entry_point/Makefile index 3b41b94e..75c57e66 100644 --- a/frida_mode/test/entry_point/Makefile +++ b/frida_mode/test/entry_point/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -9,4 +13,4 @@ frida: @gmake frida frida_entry: - @gmake frida \ No newline at end of file + @gmake frida diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index a6c655f9..bd605c52 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -106,7 +106,9 @@ int run(char *file) { } void slow() { + usleep(100000); + } int main(int argc, char **argv) { diff --git a/frida_mode/test/exe/GNUmakefile b/frida_mode/test/exe/GNUmakefile index c543cca8..86e5a461 100644 --- a/frida_mode/test/exe/GNUmakefile +++ b/frida_mode/test/exe/GNUmakefile @@ -10,11 +10,14 @@ TESTINSTSRC:=$(PWD)testinstr.c QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -.PHONY: all clean qemu frida +.PHONY: all 32 clean qemu frida all: $(TESTINSTBIN) make -C $(ROOT)frida_mode/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -25,7 +28,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) -o $@ $< -no-pie + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -no-pie clean: rm -rf $(BUILD_DIR) @@ -47,4 +50,4 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) -i $(TESTINSTR_DATA_DIR) \ -o $(FRIDA_OUT) \ -- \ - $(TESTINSTBIN) @@ \ No newline at end of file + $(TESTINSTBIN) @@ diff --git a/frida_mode/test/exe/Makefile b/frida_mode/test/exe/Makefile index f322d1f5..4bef1ccb 100644 --- a/frida_mode/test/exe/Makefile +++ b/frida_mode/test/exe/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -9,4 +13,4 @@ qemu: @gmake qemu frida: - @gmake frida \ No newline at end of file + @gmake frida diff --git a/frida_mode/test/fasan/GNUmakefile b/frida_mode/test/fasan/GNUmakefile index 22689395..08b271de 100644 --- a/frida_mode/test/fasan/GNUmakefile +++ b/frida_mode/test/fasan/GNUmakefile @@ -42,7 +42,7 @@ ifeq "$(ARCH)" "x86" LIBASAN_FILE:=libclang_rt.asan-i386.so endif -ifeq "$(ARCH)" "x64" +ifeq "$(ARCH)" "x86_64" LIBASAN_FILE:=libclang_rt.asan-x86_64.so endif @@ -85,12 +85,15 @@ else endif -.PHONY: all clean format frida-noasan frida debug run +.PHONY: all 32 clean format frida-noasan frida debug run ############################## ALL ############################################# all: $(TEST_BIN) +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(TEST_BIN): $(TEST_SRC) GNUmakefile | $(BUILD_DIR) $(CC) \ $(CFLAGS) \ @@ -120,7 +123,7 @@ frida-noasan: $(TEST_BIN) $(TEST_DATA_FILE) frida: $(TEST_BIN) $(TEST_DATA_FILE) - AFL_PRELOAD=/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.so \ + AFL_PRELOAD=$(LIBASAN) \ AFL_USE_FASAN=1 \ $(ROOT)afl-fuzz \ -D \ diff --git a/frida_mode/test/fasan/Makefile b/frida_mode/test/fasan/Makefile index a7bf44c7..3b4c71db 100644 --- a/frida_mode/test/fasan/Makefile +++ b/frida_mode/test/fasan/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -15,4 +19,4 @@ debug: @gmake debug run: - @gmake run \ No newline at end of file + @gmake run diff --git a/frida_mode/test/fasan/test.c b/frida_mode/test/fasan/test.c index a7d03017..b9a119e6 100644 --- a/frida_mode/test/fasan/test.c +++ b/frida_mode/test/fasan/test.c @@ -5,6 +5,8 @@ #include <string.h> #include <unistd.h> +#define UNUSED_PARAMETER(x) (void)(x) + #define LOG(x) \ do { \ \ @@ -67,6 +69,9 @@ void test(char data) { int main(int argc, char **argv) { + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + char input = '\0'; if (read(STDIN_FILENO, &input, 1) < 0) { diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index 515728c4..e05bade2 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -35,6 +35,9 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out all: $(TEST_BIN) make -C $(ROOT)frida_mode/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -46,7 +49,7 @@ $(HARNESS_FILE): | $(HARNESS_BUILD_DIR) wget -O $@ $(HARNESS_URL) $(HARNESS_OBJ): $(HARNESS_FILE) - $(CC) -o $@ -c $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -c $< ######### PNGTEST ######## @@ -57,7 +60,7 @@ $(PNGTEST_FILE): | $(PNGTEST_BUILD_DIR) wget -O $@ $(PNGTEST_URL) $(PNGTEST_OBJ): $(PNGTEST_FILE) | $(LIBPNG_DIR) - $(CXX) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $< + $(CXX) $(CFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $< ######### LIBPNG ######## @@ -80,6 +83,8 @@ $(LIBPNG_LIB): $(LIBPNG_MAKEFILE) $(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) $(CXX) \ + $(CFLAGS) \ + $(LDFLAGS) \ -o $@ \ $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \ -lz \ diff --git a/frida_mode/test/png/Makefile b/frida_mode/test/png/Makefile index f322d1f5..4bef1ccb 100644 --- a/frida_mode/test/png/Makefile +++ b/frida_mode/test/png/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -9,4 +13,4 @@ qemu: @gmake qemu frida: - @gmake frida \ No newline at end of file + @gmake frida diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile index 531f9bce..ca6f0ff2 100644 --- a/frida_mode/test/png/persistent/GNUmakefile +++ b/frida_mode/test/png/persistent/GNUmakefile @@ -8,6 +8,18 @@ TEST_DATA_DIR:=../build/libpng/libpng-1.2.56/contrib/pngsuite/ QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x4000000000) ARCH=$(shell uname -m) @@ -19,11 +31,18 @@ ifeq "$(ARCH)" "x86_64" AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000555555554000) endif -.PHONY: all clean qemu qemu_entry frida frida_entry +ifeq "$(ARCH)" "x86" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x56555000) +endif + +.PHONY: all 32 clean qemu qemu_entry frida frida_entry all: make -C $(ROOT)frida_mode/test/png/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -76,4 +95,4 @@ frida_entry: | $(BUILD_DIR) $(TEST_BIN) @@ clean: - rm -rf $(BUILD_DIR) \ No newline at end of file + rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/png/persistent/Makefile b/frida_mode/test/png/persistent/Makefile index 5fde63c2..cde0cf30 100644 --- a/frida_mode/test/png/persistent/Makefile +++ b/frida_mode/test/png/persistent/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -15,4 +19,4 @@ frida: @gmake frida frida_entry: - @gmake frida_entry \ No newline at end of file + @gmake frida_entry diff --git a/frida_mode/test/png/persistent/get_symbol_addr.py b/frida_mode/test/png/persistent/get_symbol_addr.py index 6458c212..1c46e010 100755 --- a/frida_mode/test/png/persistent/get_symbol_addr.py +++ b/frida_mode/test/png/persistent/get_symbol_addr.py @@ -33,4 +33,4 @@ def main(): if __name__ == "__main__": ret = main() - exit(ret) \ No newline at end of file + exit(ret) diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile index 4f55fe98..3eee4c2b 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -2,8 +2,16 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_DRIVER_HOOK_DIR=$(ROOT)utils/aflpp_driver/ -AFLPP_DRIVER_HOOK_OBJ=$(AFLPP_DRIVER_HOOK_DIR)aflpp_qemu_driver_hook.so +AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c +AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so + +CFLAGS+=-O3 \ + -funroll-loops \ + -g \ + -fPIC \ + -funroll-loops \ + +LDFLAGS+=-shared \ TEST_BIN:=$(PWD)../../build/test TEST_DATA_DIR:=../../build/libpng/libpng-1.2.56/contrib/pngsuite/ @@ -12,10 +20,21 @@ AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)in QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000) +ifndef ARCH ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + +AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000) + +ifeq "$(ARCH)" "aarch64" AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000) endif @@ -23,11 +42,18 @@ ifeq "$(ARCH)" "x86_64" AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000) endif -.PHONY: all clean qemu qemu_entry frida frida_entry +ifeq "$(ARCH)" "x86" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000) +endif + +.PHONY: all 32 clean format qemu qemu_entry frida frida_entry debug -all: +all: $(AFLPP_DRIVER_HOOK_OBJ) make -C $(ROOT)frida_mode/test/png/persistent/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -37,8 +63,8 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) truncate -s 1M $@ -$(AFLPP_DRIVER_HOOK_OBJ): | $(AFLPP_DRIVER_HOOK_DIR) - make -C $(AFLPP_DRIVER_HOOK_DIR) +$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ @@ -93,6 +119,18 @@ frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) +debug: + echo $(AFL_FRIDA_PERSISTENT_ADDR) + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ)' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \ + --ex 'set disassembly-flavor intel' \ + --args $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + clean: rm -rf $(BUILD_DIR) +format: + cd $(ROOT) && echo $(AFLPP_DRIVER_HOOK_SRC) | xargs -L1 ./.custom-format.py -i + diff --git a/frida_mode/test/png/persistent/hook/Makefile b/frida_mode/test/png/persistent/hook/Makefile index 5fde63c2..983d009e 100644 --- a/frida_mode/test/png/persistent/hook/Makefile +++ b/frida_mode/test/png/persistent/hook/Makefile @@ -2,9 +2,16 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean +format: + @gmake format + qemu: @gmake qemu @@ -15,4 +22,7 @@ frida: @gmake frida frida_entry: - @gmake frida_entry \ No newline at end of file + @gmake frida_entry + +debug: + @gmake debug diff --git a/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c b/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c new file mode 100644 index 00000000..059d438d --- /dev/null +++ b/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c @@ -0,0 +1,97 @@ +#include <stdint.h> +#include <string.h> + +#if defined(__x86_64__) + +struct x86_64_regs { + + uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, + r15; + + union { + + uint64_t rip; + uint64_t pc; + + }; + + union { + + uint64_t rsp; + uint64_t sp; + + }; + + union { + + uint64_t rflags; + uint64_t flags; + + }; + + uint8_t zmm_regs[32][64]; + +}; + +void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, + uint8_t *input_buf, uint32_t input_buf_len) { + + memcpy((void *)regs->rdi, input_buf, input_buf_len); + regs->rsi = input_buf_len; + +} + +#elif defined(__i386__) + +struct x86_regs { + + uint32_t eax, ebx, ecx, edx, edi, esi, ebp; + + union { + + uint32_t eip; + uint32_t pc; + + }; + + union { + + uint32_t esp; + uint32_t sp; + + }; + + union { + + uint32_t eflags; + uint32_t flags; + + }; + + uint8_t xmm_regs[8][16]; + +}; + +void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base, + uint8_t *input_buf, uint32_t input_buf_len) { + + void **esp = (void **)regs->esp; + void * arg1 = esp[1]; + void **arg2 = &esp[2]; + memcpy(arg1, input_buf, input_buf_len); + *arg2 = (void *)input_buf_len; + +} + +#else + #pragma error "Unsupported architecture" +#endif + +int afl_persistent_hook_init(void) { + + // 1 for shared memory input (faster), 0 for normal input (you have to use + // read(), input_buf will be NULL) + return 1; + +} + diff --git a/frida_mode/test/testinstr/GNUmakefile b/frida_mode/test/testinstr/GNUmakefile index 4addbad8..a35073ab 100644 --- a/frida_mode/test/testinstr/GNUmakefile +++ b/frida_mode/test/testinstr/GNUmakefile @@ -10,11 +10,14 @@ TESTINSTSRC:=$(PWD)testinstr.c QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -.PHONY: all clean qemu frida +.PHONY: all 32 clean qemu frida all: $(TESTINSTBIN) make -C $(ROOT)frida_mode/ +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + $(BUILD_DIR): mkdir -p $@ @@ -25,7 +28,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean: rm -rf $(BUILD_DIR) @@ -47,4 +50,10 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) -i $(TESTINSTR_DATA_DIR) \ -o $(FRIDA_OUT) \ -- \ - $(TESTINSTBIN) @@ \ No newline at end of file + $(TESTINSTBIN) @@ + +debug: + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) diff --git a/frida_mode/test/testinstr/Makefile b/frida_mode/test/testinstr/Makefile index f322d1f5..f843af19 100644 --- a/frida_mode/test/testinstr/Makefile +++ b/frida_mode/test/testinstr/Makefile @@ -2,6 +2,10 @@ all: @echo trying to use GNU make... @gmake all || echo please install GNUmake +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + clean: @gmake clean @@ -9,4 +13,7 @@ qemu: @gmake qemu frida: - @gmake frida \ No newline at end of file + @gmake frida + +debug: + @gmake debug |