diff options
Diffstat (limited to 'frida_mode/src/persistent/persistent_arm32.c')
-rw-r--r-- | frida_mode/src/persistent/persistent_arm32.c | 285 |
1 files changed, 252 insertions, 33 deletions
diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index b4e50897..dbe51eb5 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -1,75 +1,294 @@ #include "frida-gumjs.h" +#include "instrument.h" #include "persistent.h" #include "util.h" #if defined(__arm__) -struct arm_regs { +// struct _GumArmCpuContext { - uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10; +// guint32 pc; +// guint32 sp; +// guint32 cpsr; - union { +// guint32 r8; +// guint32 r9; +// guint32 r10; +// guint32 r11; +// guint32 r12; - uint32_t r11; - uint32_t fp; +// GumArmVectorReg v[16]; - }; +// guint32 _padding; - union { +// guint32 r[8]; +// guint32 lr; +// }; - uint32_t r12; - uint32_t ip; +// r11 - fp +// r12 - ip +// r13 - sp +// r14 - lr +// r15 - pc - }; +static GumCpuContext saved_regs = {0}; +static gpointer saved_lr = NULL; - union { +gboolean persistent_is_supported(void) { - uint32_t r13; - uint32_t sp; + return true; - }; +} - union { +static void instrument_persitent_save_regs(GumArmWriter *cw, + GumCpuContext *regs) { + + /* Save Regs */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE + sizeof(guint32)); + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs)); + + /* Save r1-r7 */ + for (size_t i = ARM_REG_R1; i < ARM_REG_R8; i++) { + + gum_arm_writer_put_str_reg_reg_offset( + cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); + + } + + /* Save r8-r12 */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0, + offsetof(GumCpuContext, r8)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0, + offsetof(GumCpuContext, r9)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0, + offsetof(GumCpuContext, r10)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0, + offsetof(GumCpuContext, r11)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0, + offsetof(GumCpuContext, r12)); + + /* Save sp & lr */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0, + offsetof(GumCpuContext, sp)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, + offsetof(GumCpuContext, lr)); + + /* Save r0 (load from stack into r1) */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, r[0])); + + /* Save CPSR */ + gum_arm_writer_put_mov_reg_cpsr(cw, ARM_REG_R1); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, cpsr)); + + /* Save PC */ + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1, + GUM_ADDRESS(persistent_start)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, pc)); + + /* Restore Regs */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE + sizeof(guint32)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); - uint32_t r14; - uint32_t lr; +} - }; +static void instrument_persitent_restore_regs(GumArmWriter *cw, + GumCpuContext *regs) { - union { + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs)); - uint32_t r15; - uint32_t pc; + /* Restore CPSR */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, cpsr)); + gum_arm_writer_put_mov_cpsr_reg(cw, ARM_REG_R1); - }; + /* Restore sp & lr */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0, + offsetof(GumCpuContext, sp)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, + offsetof(GumCpuContext, lr)); - uint32_t cpsr; + /* Restore r8-r12 */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0, + offsetof(GumCpuContext, r8)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0, + offsetof(GumCpuContext, r9)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0, + offsetof(GumCpuContext, r10)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0, + offsetof(GumCpuContext, r11)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0, + offsetof(GumCpuContext, r12)); - uint8_t vfp_zregs[32][16]; - uint32_t vfp_xregs[16]; + /* Restore r7-r0 */ + for (size_t i = ARM_REG_R7; i >= ARM_REG_R0; i--) { -}; + gum_arm_writer_put_ldr_reg_reg_offset( + cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); -typedef struct arm_regs arch_api_regs; + } -gboolean persistent_is_supported(void) { +} + +static void instrument_exit(GumArmWriter *cw) { + + gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0); + gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1, + GUM_ARG_REGISTER, ARM_REG_R0); + +} + +static int instrument_afl_persistent_loop_func(void) { + + int ret = __afl_persistent_loop(persistent_count); + if (instrument_previous_pc_addr == NULL) { + + FATAL("instrument_previous_pc_addr uninitialized"); + + } - return false; + *instrument_previous_pc_addr = instrument_hash_zero; + return ret; + +} + +static void instrument_afl_persistent_loop(GumArmWriter *cw) { + + gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); + gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + +} + +static void persistent_prologue_hook(GumArmWriter *cw, GumCpuContext *regs) { + + if (persistent_hook == NULL) return; + + gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R2, + GUM_ADDRESS(&__afl_fuzz_len)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0); + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1, + GUM_ADDRESS(&__afl_fuzz_ptr)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R1, 0); + + gum_arm_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, GUM_ADDRESS(regs), + GUM_ARG_REGISTER, ARM_REG_R1, GUM_ARG_REGISTER, ARM_REG_R2); + + gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + +} + +static void instrument_persitent_save_lr(GumArmWriter *cw) { + + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0); + + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); } void persistent_prologue_arch(GumStalkerOutput *output) { - UNUSED_PARAMETER(output); - FFATAL("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 + */ + + GumArmWriter *cw = output->writer.arm; + + gconstpointer loop = cw->code + 1; + + FVERBOSE("Persistent loop reached"); + + instrument_persitent_save_regs(cw, &saved_regs); + + /* loop: */ + gum_arm_writer_put_label(cw, loop); + + /* call instrument_prologue_func */ + instrument_afl_persistent_loop(cw); + + /* jz done */ + gconstpointer done = cw->code + 1; + gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0); + gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done); + + /* 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_arm_writer_put_bl_label(cw, original); + + /* jmp loop */ + gum_arm_writer_put_b_label(cw, loop); + + /* done: */ + gum_arm_writer_put_label(cw, done); + + instrument_exit(cw); + + /* original: */ + gum_arm_writer_put_label(cw, original); + + instrument_persitent_save_lr(cw); + + if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } } void persistent_epilogue_arch(GumStalkerOutput *output) { - UNUSED_PARAMETER(output); - FFATAL("Persistent mode not supported on this architecture"); + GumArmWriter *cw = output->writer.arm; + + if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); + + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0); + + gum_arm_writer_put_bx_reg(cw, ARM_REG_R0); } |