diff options
| author | vanhauser-thc <vh@thc.org> | 2021-07-19 10:58:19 +0200 |
|---|---|---|
| committer | vanhauser-thc <vh@thc.org> | 2021-07-19 10:58:19 +0200 |
| commit | 32a0d6ac31554a47dca591f8978982758fb87677 (patch) | |
| tree | be2ffd03f136dbecd408c73e4bc250ae249a4180 /frida_mode/src/persistent/persistent_arm64.c | |
| parent | 815161827689c339d335233b7b232ac9b120b79b (diff) | |
| download | afl++-32a0d6ac31554a47dca591f8978982758fb87677.tar.gz | |
Revert "Merge branch 'release' into stable"
This reverts commit 815161827689c339d335233b7b232ac9b120b79b, reversing changes made to 9321a24e682b5c8bf6278961bd014cb883b87295.
Diffstat (limited to 'frida_mode/src/persistent/persistent_arm64.c')
| -rw-r--r-- | frida_mode/src/persistent/persistent_arm64.c | 385 |
1 files changed, 324 insertions, 61 deletions
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); } |
