diff options
author | Your Name <you@example.com> | 2022-08-04 18:46:29 +0100 |
---|---|---|
committer | Your Name <you@example.com> | 2022-08-04 18:46:29 +0100 |
commit | 1e524d1f43bba638b000da5fa6fb094ebcc9bb83 (patch) | |
tree | d087d407733ee2c0a1139c02e681192f7f9bfec3 | |
parent | 7c50ec5d055508ebb4220976fd54c553224a01eb (diff) | |
download | afl++-1e524d1f43bba638b000da5fa6fb094ebcc9bb83.tar.gz |
Added support for ARM32 inline assembly
-rw-r--r-- | frida_mode/src/instrument/instrument_arm32.c | 156 |
1 files changed, 148 insertions, 8 deletions
diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 4525e83d..0ff69952 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -5,22 +5,150 @@ #if defined(__arm__) + #define PAGE_MASK (~(GUM_ADDRESS(0xfff))) + #define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x)) + gboolean instrument_cache_enabled = FALSE; gsize instrument_cache_size = 0; -gboolean instrument_is_coverage_optimize_supported(void) { +extern __thread guint64 instrument_previous_pc; + +__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; + + #pragma pack(push, 1) +typedef struct { + // cur_location = (block_address >> 4) ^ (block_address << 8); + // shared_mem[cur_location ^ prev_location]++; + // prev_location = cur_location >> 1; + + /* We can remove this branch when we add support for branch suppression */ + uint32_t b_code; /* b imm */ + uint8_t * shared_mem; + uint64_t *prev_location; + + /* code */ + + /* save regs */ + uint32_t str_r0_sp_rz; /* str r0, [sp - RED_ZONE] */ + uint32_t str_r1_sp_rz_4; /* str r1, [sp - (RED_ZONE + 4)] */ + + /* load prev */ + uint32_t ldr_r0_pprev; /* ldr r0, [pc-x] */ + uint32_t ldrh_r1_r0; /* ldrh r1, [r0] */ + + /* load curr */ + uint32_t mov_r0_block_id; /* mov r0, #imm16 */ + + /* calculate new */ + uint32_t eor_r0_r0_r1; /* eor r0, r0, r1 */ + + /* load map */ + uint32_t ldr_r1_pmap; /* ldr r1, [pc-x] */ + + /* calculate offset */ + uint32_t add_r1_r1_r0; /* add r1, r1, r0 */ + + /* Load the value */ + uint32_t ldrb_r0_r1; /* ldrb r0, [r1] */ + + /* Increment the value */ + uint32_t add_r0_r0_1; /* add r0, r0, #1 */ + uint32_t add_r0_r0_r0_lsr_8; /* add r0, r0, r0, lsr #8 */ + + /* Save the value */ + uint32_t strb_r0_r1; /* strb r0, [r1] */ + + /* load curr shifted */ + uint32_t mov_r0_block_id_shr_1; /* mov r0, #imm16 >> 1*/ + + /* Update prev */ + uint32_t ldr_r1_pprev; /* ldr r1, [pc-x] */ + uint32_t strh_r0_r1; /* strh r0, [r1] */ + + /* restore regs */ + uint32_t ldr_r1_sp_rz_4; /* ldr r1, [sp - (RED_ZONE + 4)] */ + uint32_t ldr_r0_sp_rz; /* ldr r0, [sp - RED_ZONE] */ + +} afl_log_code_asm_t; + +typedef union { + afl_log_code_asm_t code; + uint8_t bytes[0]; + +} afl_log_code; - return false; + #pragma pack(pop) +static const afl_log_code_asm_t template = + { + .b_code = GUINT32_TO_LE(0xea000001), + .shared_mem = (uint8_t *)GUINT32_TO_LE(0xcefaadde), + .prev_location = (uint64_t *)GUINT32_TO_LE(0xadba0df0), + .str_r0_sp_rz = GUINT32_TO_LE(0xe50d0080), + .str_r1_sp_rz_4 = GUINT32_TO_LE(0xe50d1084), + .ldr_r0_pprev = GUINT32_TO_LE(0xe51f0014), + .ldrh_r1_r0 = GUINT32_TO_LE(0xe1d010b0), + .mov_r0_block_id = GUINT32_TO_LE(0xe3000000), + .eor_r0_r0_r1 = GUINT32_TO_LE(0xe0200001), + .ldr_r1_pmap = GUINT32_TO_LE(0xe51f1028), + .add_r1_r1_r0 = GUINT32_TO_LE(0xe0811000), + .ldrb_r0_r1 = GUINT32_TO_LE(0xe5d10000), + .add_r0_r0_1 = GUINT32_TO_LE(0xe2800001), + .add_r0_r0_r0_lsr_8 = GUINT32_TO_LE(0xe0800420), + .strb_r0_r1 = GUINT32_TO_LE(0xe5c10000), + .mov_r0_block_id_shr_1 = GUINT32_TO_LE(0xe3000000), + .ldr_r1_pprev = GUINT32_TO_LE(0xe51f1040), + .strh_r0_r1 = GUINT32_TO_LE(0xe1c100b0), + .ldr_r1_sp_rz_4 = GUINT32_TO_LE(0xe51d1084), + .ldr_r0_sp_rz = GUINT32_TO_LE(0xe51d0080), +} + +; + +gboolean instrument_is_coverage_optimize_supported(void) { + return true; +} + +static void patch_t3_insn(uint32_t *insn, uint16_t val) { + uint32_t orig = GUINT32_FROM_LE(*insn); + uint32_t imm12 = (val & 0xfff); + uint32_t imm4 = (val >> 12); + orig |= imm12; + orig |= (imm4 << 16); + *insn = GUINT32_TO_LE(orig); } void instrument_coverage_optimize(const cs_insn *instr, GumStalkerOutput *output) { + afl_log_code code = {0}; + GumArmWriter *cw = output->writer.arm; + gpointer block_start; + guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + gsize map_size_pow2; + gsize area_offset_ror; + GumAddress code_addr = 0; - UNUSED_PARAMETER(instr); - UNUSED_PARAMETER(output); - FFATAL("Optimized coverage not supported on this architecture"); + // gum_arm64_writer_put_brk_imm(cw, 0x0); + + code_addr = cw->pc; + + block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code)); + code.code = template; + + g_assert(PAGE_ALIGNED(__afl_area_ptr)); + + map_size_pow2 = util_log2(__afl_map_size); + area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); + + code.code.shared_mem = __afl_area_ptr; + code.code.prev_location = instrument_previous_pc_addr; + + patch_t3_insn(&code.code.mov_r0_block_id, (uint16_t)area_offset); + patch_t3_insn(&code.code.mov_r0_block_id_shr_1, (uint16_t)area_offset_ror); + + // gum_arm_writer_put_breakpoint(cw); + gum_arm_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); } void instrument_coverage_optimize_insn(const cs_insn *instr, @@ -28,14 +156,26 @@ void instrument_coverage_optimize_insn(const cs_insn *instr, UNUSED_PARAMETER(instr); UNUSED_PARAMETER(output); - FFATAL("Optimized coverage not supported on this architecture"); - } void instrument_coverage_optimize_init(void) { + char *shm_env = getenv(SHM_ENV_VAR); + FVERBOSE("SHM_ENV_VAR: %s", shm_env); + + if (shm_env == NULL) { + FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes"); - FWARNF("Optimized coverage not supported on this architecture"); + __afl_area_ptr = area_ptr_dummy; + memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy)); + } + FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); + + if (instrument_previous_pc_addr == NULL) { + instrument_previous_pc_addr = &instrument_previous_pc; + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + } } void instrument_flush(GumStalkerOutput *output) { |