diff options
Diffstat (limited to 'frida_mode/src/persistent')
-rw-r--r-- | frida_mode/src/persistent/persistent.c | 80 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_arm32.c | 6 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_arm64.c | 385 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_x64.c | 235 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_x86.c | 157 |
5 files changed, 571 insertions, 292 deletions
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c index 2ec5b9cc..639a694e 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -1,30 +1,31 @@ #include <dlfcn.h> -#include "frida-gum.h" +#include "frida-gumjs.h" #include "config.h" #include "debug.h" +#include "entry.h" #include "persistent.h" +#include "ranges.h" +#include "stalker.h" #include "util.h" -int __afl_sharedmem_fuzzing = 0; -afl_persistent_hook_fn hook = NULL; +int __afl_sharedmem_fuzzing = 0; +static char *hook_name = NULL; + +afl_persistent_hook_fn persistent_hook = NULL; guint64 persistent_start = 0; guint64 persistent_count = 0; guint64 persistent_ret = 0; -guint64 persistent_ret_offset = 0; gboolean persistent_debug = FALSE; -void persistent_init(void) { - - char *hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK"); +void persistent_config(void) { + hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK"); persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR"); persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT"); persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET"); - persistent_ret_offset = - util_read_address("AFL_FRIDA_PERSISTENT_RETADDR_OFFSET"); if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; } @@ -36,6 +37,11 @@ void persistent_init(void) { } + if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000; + + if (persistent_start != 0 && !persistent_is_supported()) + FATAL("Persistent mode not supported on this architecture"); + if (persistent_ret != 0 && persistent_start == 0) { FATAL( @@ -44,21 +50,28 @@ void persistent_init(void) { } - if (persistent_ret_offset != 0 && persistent_ret == 0) { + if (hook_name == NULL) { return; } - FATAL( - "AFL_FRIDA_PERSISTENT_RET must be specified if " - "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is"); + void *hook_obj = dlopen(hook_name, RTLD_NOW); + if (hook_obj == NULL) + FATAL("Failed to load AFL_FRIDA_PERSISTENT_HOOK (%s)", hook_name); - } + int (*afl_persistent_hook_init_ptr)(void) = + dlsym(hook_obj, "afl_persistent_hook_init"); + if (afl_persistent_hook_init_ptr == NULL) + FATAL("Failed to find afl_persistent_hook_init in %s", hook_name); - if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000; + if (afl_persistent_hook_init_ptr() == 0) + FATAL("afl_persistent_hook_init returned a failure"); - if (persistent_count != 0 && persistent_count < 100) - WARNF("Persistent count out of recommended range (<100)"); + persistent_hook = + (afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook"); + if (persistent_hook == NULL) + FATAL("Failed to find afl_persistent_hook in %s", hook_name); - if (persistent_start != 0 && !persistent_is_supported()) - FATAL("Persistent mode not supported on this architecture"); +} + +void persistent_init(void) { OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)", persistent_start == 0 ? ' ' : 'X', persistent_start); @@ -68,30 +81,25 @@ void persistent_init(void) { OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)", persistent_ret == 0 ? ' ' : 'X', persistent_ret); - OKF("Instrumentation - persistent ret offset [%c] (%" G_GINT64_MODIFIER "d)", - persistent_ret_offset == 0 ? ' ' : 'X', persistent_ret_offset); - if (hook_name != NULL) { + if (persistent_hook != NULL) { __afl_sharedmem_fuzzing = 1; } - void *hook_obj = dlopen(hook_name, RTLD_NOW); - if (hook_obj == NULL) - FATAL("Failed to load AFL_FRIDA_PERSISTENT_HOOK (%s)", hook_name); +} - int (*afl_persistent_hook_init_ptr)(void) = - dlsym(hook_obj, "afl_persistent_hook_init"); - if (afl_persistent_hook_init_ptr == NULL) - FATAL("Failed to find afl_persistent_hook_init in %s", hook_name); +void persistent_prologue(GumStalkerOutput *output) { - if (afl_persistent_hook_init_ptr() == 0) - FATAL("afl_persistent_hook_init returned a failure"); + OKF("AFL_FRIDA_PERSISTENT_ADDR reached"); + entry_reached = TRUE; + ranges_exclude(); + stalker_trust(); + persistent_prologue_arch(output); - hook = (afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook"); - if (hook == NULL) - FATAL("Failed to find afl_persistent_hook in %s", hook_name); +} - __afl_sharedmem_fuzzing = 1; +void persistent_epilogue(GumStalkerOutput *output) { - } + OKF("AFL_FRIDA_PERSISTENT_RET reached"); + persistent_epilogue_arch(output); } diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index 6a3c06fa..769f1505 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -1,4 +1,4 @@ -#include "frida-gum.h" +#include "frida-gumjs.h" #include "debug.h" @@ -61,14 +61,14 @@ gboolean persistent_is_supported(void) { } -void persistent_prologue(GumStalkerOutput *output) { +void persistent_prologue_arch(GumStalkerOutput *output) { UNUSED_PARAMETER(output); FATAL("Persistent mode not supported on this architecture"); } -void persistent_epilogue(GumStalkerOutput *output) { +void persistent_epilogue_arch(GumStalkerOutput *output) { UNUSED_PARAMETER(output); FATAL("Persistent mode not supported on this architecture"); diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index 1215d8da..3cd61cd5 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -1,120 +1,383 @@ -#include "frida-gum.h" +#include <unistd.h> +#include "frida-gumjs.h" #include "config.h" #include "debug.h" #include "instrument.h" +#include "persistent.h" #include "util.h" #if defined(__aarch64__) +typedef struct { -struct arm64_regs { + GumCpuContext ctx; + uint64_t rflags; - uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; +} persistent_ctx_t; - union { +static persistent_ctx_t saved_regs = {0}; +static gpointer saved_lr = NULL; - uint64_t x11; - uint32_t fp_32; +gboolean persistent_is_supported(void) { - }; + return true; - union { +} - uint64_t x12; - uint32_t ip_32; +static void instrument_persitent_save_regs(GumArm64Writer * cw, + persistent_ctx_t *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + const guint32 mrs_x1_nzcv = 0xd53b4201; + + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), + GUM_INDEX_PRE_ADJUST); + gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, + ARM64_REG_SP, -(16), + GUM_INDEX_PRE_ADJUST); + + gum_arm64_writer_put_instruction(cw, mrs_x1_nzcv); + + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, + GUM_ADDRESS(regs_address)); + + /* Skip x0 & x1 we'll do that later */ + + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, + offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, + offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, + offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, + offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, + offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, + offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, + offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, + offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, + offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, + offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, + offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, + offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, + offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); + + /* LR (x30) */ + gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, + offsetof(GumCpuContext, x[30])); + + /* PC & Adjusted SP (31) */ + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, + GUM_ADDRESS(persistent_start)); + gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_X3, ARM64_REG_SP, + (GUM_RED_ZONE_SIZE + 32)); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, offsetof(GumCpuContext, pc), + GUM_INDEX_SIGNED_OFFSET); + + /* CPSR */ + gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(persistent_ctx_t, rflags)); + + /* Q */ + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, + offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, + offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, + offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, + offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); + + /* x0 & x1 */ + gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, + ARM64_REG_SP, 16, + GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); + + /* Pop the saved values */ + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_SP, 16, GUM_INDEX_POST_ADJUST); + + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, + GUM_INDEX_POST_ADJUST); - }; +} - union { +static void instrument_persitent_restore_regs(GumArm64Writer * cw, + persistent_ctx_t *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + const guint32 msr_nzcv_x1 = 0xd51b4201; + + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, + GUM_ADDRESS(regs_address)); + + /* Skip x0 - x3 we'll do that last */ + + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, + offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, + offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, + offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, + offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, + offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, + offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, + offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, + offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, + offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, + offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, + offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, + offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, + offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); + + /* LR (x30) */ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, + offsetof(GumCpuContext, x[30])); + + /* Adjusted SP (31) (use x1 as clobber)*/ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(GumCpuContext, sp)); + gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_SP, ARM64_REG_X1); + + /* CPSR */ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(persistent_ctx_t, rflags)); + gum_arm64_writer_put_instruction(cw, msr_nzcv_x1); + + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, + offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, + offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, + offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, + offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); + + /* x2 & x3 */ + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); + /* x0 & x1 */ + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_X0, + offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); - uint64_t x13; - uint32_t sp_32; +} - }; +static void instrument_exit(GumArm64Writer *cw) { - union { + gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); + gum_arm64_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0); - uint64_t x14; - uint32_t lr_32; +} - }; +static int instrument_afl_persistent_loop_func(void) { - union { + int ret = __afl_persistent_loop(persistent_count); + instrument_previous_pc = instrument_hash_zero; + return ret; - uint64_t x15; - uint32_t pc_32; +} - }; +static void instrument_afl_persistent_loop(GumArm64Writer *cw) { - union { + gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm64_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); + gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, + GUM_RED_ZONE_SIZE); - uint64_t x16; - uint64_t ip0; +} - }; +static void persistent_prologue_hook(GumArm64Writer * cw, + persistent_ctx_t *regs) { - union { + if (persistent_hook == NULL) return; - uint64_t x17; - uint64_t ip1; + gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, + GUM_ADDRESS(&__afl_fuzz_len)); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); - }; + gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_X2, + G_MAXULONG); - uint64_t x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28; + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X1, + GUM_ADDRESS(&__afl_fuzz_ptr)); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X1, 0); - union { + gum_arm64_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, ARM64_REG_X1, GUM_ARG_REGISTER, + ARM64_REG_X2); - uint64_t x29; - uint64_t fp; + gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, + GUM_RED_ZONE_SIZE); - }; +} - union { +static void instrument_persitent_save_lr(GumArm64Writer *cw) { - uint64_t x30; - uint64_t lr; + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), + GUM_INDEX_PRE_ADJUST); - }; + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, + GUM_ADDRESS(&saved_lr)); - union { + gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0); - uint64_t x31; - uint64_t sp; + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, + GUM_INDEX_POST_ADJUST); - }; +} - // the zero register is not saved here ofc +void persistent_prologue_arch(GumStalkerOutput *output) { - uint64_t pc; + /* + * 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 + */ - uint32_t cpsr; + GumArm64Writer *cw = output->writer.arm64; - uint8_t vfp_zregs[32][16 * 16]; - uint8_t vfp_pregs[17][32]; - uint32_t vfp_xregs[16]; + gconstpointer loop = cw->code + 1; -}; + OKF("Persistent loop reached"); -typedef struct arm64_regs arch_api_regs; + instrument_persitent_save_regs(cw, &saved_regs); -gboolean persistent_is_supported(void) { + /* loop: */ + gum_arm64_writer_put_label(cw, loop); - return false; + /* call instrument_prologue_func */ + instrument_afl_persistent_loop(cw); -} + /* jz done */ + gconstpointer done = cw->code + 1; + gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); + gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done); -void persistent_prologue(GumStalkerOutput *output) { + /* Optionally call the persistent hook */ + persistent_prologue_hook(cw, &saved_regs); - UNUSED_PARAMETER(output); - FATAL("Persistent mode not supported on this architecture"); + instrument_persitent_restore_regs(cw, &saved_regs); + gconstpointer original = cw->code + 1; + /* call original */ + + gum_arm64_writer_put_bl_label(cw, original); + + /* jmp loop */ + gum_arm64_writer_put_b_label(cw, loop); + + /* done: */ + gum_arm64_writer_put_label(cw, done); + + instrument_exit(cw); + + /* original: */ + gum_arm64_writer_put_label(cw, original); + + instrument_persitent_save_lr(cw); + + if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } } -void persistent_epilogue(GumStalkerOutput *output) { +void persistent_epilogue_arch(GumStalkerOutput *output) { + + GumArm64Writer *cw = output->writer.arm64; + + if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } + + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, + GUM_ADDRESS(&saved_lr)); + + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0); - UNUSED_PARAMETER(output); - FATAL("Persistent mode not supported on this architecture"); + gum_arm64_writer_put_br_reg(cw, ARM64_REG_X0); } diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 4cb960fc..c0bd9a09 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -1,5 +1,5 @@ #include <unistd.h> -#include "frida-gum.h" +#include "frida-gumjs.h" #include "config.h" #include "debug.h" @@ -10,39 +10,15 @@ #if defined(__x86_64__) -struct x86_64_regs { +typedef struct { - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, - r15; + GumCpuContext ctx; + uint64_t rflags; - union { +} persistent_ctx_t; - 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]; - -}; - -typedef struct x86_64_regs arch_api_regs; - -static arch_api_regs saved_regs = {0}; +static persistent_ctx_t saved_regs = {0}; +static gpointer saved_ret = NULL; gboolean persistent_is_supported(void) { @@ -50,8 +26,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void instrument_persitent_save_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, @@ -63,60 +39,60 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 1), - GUM_REG_RBX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 2), - GUM_REG_RCX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 3), - GUM_REG_RDX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 4), - GUM_REG_RDI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 5), - GUM_REG_RSI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 6), - GUM_REG_RBP); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 7), - GUM_REG_R8); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 8), - GUM_REG_R9); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 9), - GUM_REG_R10); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 10), - GUM_REG_R11); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 11), - GUM_REG_R12); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 12), - GUM_REG_R13); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 13), - GUM_REG_R14); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 14), - GUM_REG_R15); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rbx), GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rcx), GUM_REG_RCX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rdx), GUM_REG_RDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rdi), GUM_REG_RDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rsi), GUM_REG_RSI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rbp), GUM_REG_RBP); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r8), GUM_REG_R8); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r9), GUM_REG_R9); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r10), GUM_REG_R10); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r11), GUM_REG_R11); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r12), GUM_REG_R12); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r13), GUM_REG_R13); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r14), GUM_REG_R14); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r15), GUM_REG_R15); /* Store RIP */ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RBX, GUM_ADDRESS(persistent_start)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 15), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rip), GUM_REG_RBX); /* Store adjusted RSP */ gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_RBX, GUM_REG_RSP); /* RED_ZONE + Saved flags, RAX, alignment */ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX, - GUM_RED_ZONE_SIZE + (0x8 * 3)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16), - GUM_REG_RBX); + GUM_RED_ZONE_SIZE + (0x8 * 2)); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rsp), GUM_REG_RBX); /* Save the flags */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x8); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 17), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(persistent_ctx_t, rflags), GUM_REG_RBX); /* Save the RAX */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x0); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 0), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rax), GUM_REG_RBX); /* Pop the saved values */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 0x10); @@ -126,54 +102,56 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, } -static void instrument_persitent_restore_regs(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void instrument_persitent_restore_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RAX, - (0x8 * 2)); + offsetof(GumCpuContext, rcx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX, - (0x8 * 3)); + offsetof(GumCpuContext, rdx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX, - (0x8 * 4)); + offsetof(GumCpuContext, rdi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX, - (0x8 * 5)); + offsetof(GumCpuContext, rsi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX, - (0x8 * 6)); + offsetof(GumCpuContext, rbp)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX, - (0x8 * 7)); + offsetof(GumCpuContext, r8)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX, - (0x8 * 8)); + offsetof(GumCpuContext, r9)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX, - (0x8 * 9)); + offsetof(GumCpuContext, r10)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX, - (0x8 * 10)); + offsetof(GumCpuContext, r11)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX, - (0x8 * 11)); + offsetof(GumCpuContext, r12)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX, - (0x8 * 12)); + offsetof(GumCpuContext, r13)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX, - (0x8 * 13)); + offsetof(GumCpuContext, r14)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX, - (0x8 * 14)); + offsetof(GumCpuContext, r15)); - /* Don't restore RIP or RSP */ + /* Don't restore RIP */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX, + offsetof(GumCpuContext, rsp)); /* Restore RBX, RAX & Flags */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -(GUM_RED_ZONE_SIZE)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 1)); + offsetof(GumCpuContext, rbx)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 0)); + offsetof(GumCpuContext, rax)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 17)); + offsetof(persistent_ctx_t, rflags)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_popfx(cw); @@ -196,7 +174,7 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - previous_pc = 0; + instrument_previous_pc = instrument_hash_zero; return ret; } @@ -214,35 +192,59 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { - if (hook == NULL) return; + if (persistent_hook == NULL) return; gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -(GUM_RED_ZONE_SIZE)); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RCX, + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX, GUM_ADDRESS(&__afl_fuzz_len)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff); - gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RDX, GUM_REG_RDI); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX, + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RSI, GUM_ADDRESS(&__afl_fuzz_ptr)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RSI, 0); gum_x86_writer_put_call_address_with_arguments( - cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS, - GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER, - GUM_REG_RDX, GUM_ARG_REGISTER, GUM_REG_RCX); + cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_RSI, GUM_ARG_REGISTER, + GUM_REG_RDX); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (GUM_RED_ZONE_SIZE)); } -void persistent_prologue(GumStalkerOutput *output) { +static void instrument_persitent_save_ret(GumX86Writer *cw) { + + /* Stack usage by this function */ + gssize offset = GUM_RED_ZONE_SIZE + (3 * 8); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + + gum_x86_writer_put_pushfx(cw); + gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, + offset); + gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_RAX, GUM_REG_RBX); + + gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_popfx(cw); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +void persistent_prologue_arch(GumStalkerOutput *output) { /* * SAVE REGS @@ -268,11 +270,12 @@ void persistent_prologue(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - /* Stack must be 16-byte aligned per ABI */ - instrument_persitent_save_regs(cw, &saved_regs); + OKF("Persistent loop reached"); + + /* Pop the return value */ + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8); - /* pop the return value */ - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8)); + instrument_persitent_save_regs(cw, &saved_regs); /* loop: */ gum_x86_writer_put_label(cw, loop); @@ -304,21 +307,27 @@ void persistent_prologue(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); - if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + instrument_persitent_save_ret(cw); - gum_x86_writer_flush(cw); + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } } -void persistent_epilogue(GumStalkerOutput *output) { +void persistent_epilogue_arch(GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - persistent_ret_offset); - gum_x86_writer_put_ret(cw); + /* The stack should be aligned when we re-enter our loop */ + gconstpointer zero = cw->code + 1; + gum_x86_writer_put_test_reg_u32(cw, GUM_REG_RSP, 0xF); + gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, zero, GUM_NO_HINT); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -8); + gum_x86_writer_put_label(cw, zero); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_RAX); } diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index b30dfadf..b911676a 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -1,44 +1,23 @@ -#include "frida-gum.h" +#include "frida-gumjs.h" #include "config.h" +#include "debug.h" #include "instrument.h" #include "persistent.h" #if defined(__i386__) -struct x86_regs { +typedef struct { - uint32_t eax, ebx, ecx, edx, edi, esi, ebp; + GumCpuContext ctx; + uint32_t eflags; - union { +} persistent_ctx_t; - uint32_t eip; - uint32_t pc; +static persistent_ctx_t saved_regs = {0}; - }; - - union { - - uint32_t esp; - uint32_t sp; - - }; - - union { - - uint32_t eflags; - uint32_t flags; - - }; - - uint8_t xmm_regs[8][16]; - -}; - -typedef struct x86_regs arch_api_regs; - -static arch_api_regs saved_regs = {0}; +static gpointer saved_ret = NULL; gboolean persistent_is_supported(void) { @@ -46,8 +25,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - struct x86_regs *regs) { +static void instrument_persitent_save_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); @@ -57,78 +36,80 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, 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); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ebx), GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ecx), GUM_REG_ECX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, edx), GUM_REG_EDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, edi), GUM_REG_EDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, esi), GUM_REG_ESI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ebp), 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); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, eip), 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); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, esp), 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); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(persistent_ctx_t, eflags), 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); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, eax), 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) { +static void instrument_persitent_restore_regs(GumX86Writer * cw, + persistent_ctx_t *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)); + offsetof(GumCpuContext, ecx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX, - (0x4 * 3)); + offsetof(GumCpuContext, edx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX, - (0x4 * 4)); + offsetof(GumCpuContext, edi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX, - (0x4 * 5)); + offsetof(GumCpuContext, esi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX, - (0x4 * 6)); + offsetof(GumCpuContext, ebp)); - /* Don't restore RIP or RSP */ + /* Don't restore RIP */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX, + offsetof(GumCpuContext, esp)); /* Restore RBX, RAX & Flags */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, - (0x4 * 1)); + offsetof(GumCpuContext, ebx)); 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)); + offsetof(GumCpuContext, eax)); 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)); + offsetof(persistent_ctx_t, eflags)); gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); gum_x86_writer_put_popfx(cw); @@ -149,7 +130,7 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - previous_pc = 0; + instrument_previous_pc = instrument_hash_zero; return ret; } @@ -162,9 +143,9 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { +static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { - if (hook == NULL) return; + if (persistent_hook == NULL) return; gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, GUM_ADDRESS(&__afl_fuzz_len)); @@ -177,14 +158,33 @@ static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { /* 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, + cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER, GUM_REG_ECX); } -void persistent_prologue(GumStalkerOutput *output) { +static void instrument_persitent_save_ret(GumX86Writer *cw) { + + /* Stack usage by this function */ + gssize offset = (3 * 4); + + gum_x86_writer_put_pushfx(cw); + 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, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, + offset); + gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_EAX, GUM_REG_EBX); + + gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); + gum_x86_writer_put_popfx(cw); + +} + +void persistent_prologue_arch(GumStalkerOutput *output) { /* * SAVE REGS @@ -210,11 +210,12 @@ void persistent_prologue(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - /* Stack must be 16-byte aligned per ABI */ - instrument_persitent_save_regs(cw, &saved_regs); + OKF("Persistent loop reached"); /* Pop the return value */ - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4)); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4); + + instrument_persitent_save_regs(cw, &saved_regs); /* loop: */ gum_x86_writer_put_label(cw, loop); @@ -244,22 +245,20 @@ void persistent_prologue(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); - if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + instrument_persitent_save_ret(cw); - gum_x86_writer_flush(cw); + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } } -void persistent_epilogue(GumStalkerOutput *output) { +void persistent_epilogue_arch(GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, - persistent_ret_offset); - - gum_x86_writer_put_ret(cw); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_EAX); } |