aboutsummaryrefslogtreecommitdiff
path: root/frida_mode/src/instrument
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2023-06-05 14:12:56 +0300
committerGitHub <noreply@github.com>2023-06-05 14:12:56 +0300
commitf9b72b6f2f9a6545143ad2efa40ea0b527a5bf5c (patch)
tree82620ccfd9079b2e4fd0f7a6176b20508d4b68ca /frida_mode/src/instrument
parented73c632a5791ca740fe64770b6d238206033ec4 (diff)
parentb644e48f36485c645cbc0dadf0fddb2aa14cc079 (diff)
downloadafl++-f9b72b6f2f9a6545143ad2efa40ea0b527a5bf5c.tar.gz
Merge pull request #1755 from AFLplusplus/dev
push to stable
Diffstat (limited to 'frida_mode/src/instrument')
-rw-r--r--frida_mode/src/instrument/instrument.c1
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c231
2 files changed, 193 insertions, 39 deletions
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index a6aac666..db73d845 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -169,7 +169,6 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
if (unlikely(begin)) { instrument_debug_start(instr->address, output); }
- if (instr->address == entry_point) { entry_prologue(iterator, output); }
if (instr->address == persistent_start) { persistent_prologue(output); }
if (instr->address == persistent_ret) { persistent_epilogue(output); }
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 4372861d..131eb4c5 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -76,6 +76,45 @@ typedef struct {
} afl_log_code_asm_t;
+typedef struct {
+
+ uint32_t b_imm8; /* br #XX (end) */
+
+ uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */
+
+ uint32_t stp_x0_x1; /* stp x0, x1, [sp, #-0xa0] */
+
+ uint32_t ldr_x0_p_prev_loc_1; /* ldr x0, #0xXXXX */
+ uint32_t ldr_x1_ptr_x0; /* ldr x1, [x0] */
+
+ uint32_t ldr_x0_p_area_offset; /* ldr x0, #0xXXXX */
+ uint32_t eor_x0_x1_x0; /* eor x0, x1, x0 */
+ uint32_t ldr_x1_p_area_ptr; /* ldr x1, #0xXXXX */
+ uint32_t add_x0_x1_x0; /* add x0, x1, x0 */
+
+ uint32_t ldrb_w1_x0; /* ldrb w1, [x0] */
+ uint32_t add_w1_w1_1; /* add w1, w1, #1 */
+ uint32_t add_w1_w1_w1_lsr_8; /* add x1, x1, x1, lsr #8 */
+
+ uint32_t strb_w1_ptr_x0; /* strb w1, [x0] */
+
+ uint32_t ldr_x0_p_prev_loc_2; /* ldr x0, #0xXXXX */
+ uint32_t ldr_x1_p_area_offset_ror; /* ldr x1, #0xXXXX */
+ uint32_t str_x1_ptr_x0; /* str x1, [x0] */
+
+ uint32_t ldp_x0_x1; /* ldp x0, x1, [sp, #-0xa0] */
+
+ uint32_t b_end; /* skip the data */
+
+ uint64_t area_ptr;
+ uint64_t prev_loc_ptr;
+ uint64_t area_offset;
+ uint64_t area_offset_ror;
+
+ uint8_t end[0];
+
+} afl_log_code_asm_long_t;
+
#pragma pack(pop)
typedef union {
@@ -85,6 +124,13 @@ typedef union {
} afl_log_code;
+typedef union {
+
+ afl_log_code_asm_long_t code;
+ uint8_t bytes[0];
+
+} afl_log_code_long;
+
static const afl_log_code_asm_t template =
{
@@ -119,6 +165,46 @@ static const afl_log_code_asm_t template =
;
+static const afl_log_code_asm_long_t template_long =
+ {.b_imm8 = 0x1400001a,
+
+ .restoration_prolog = 0xa8c947f0, /* ldp x16, x17, [sp], #0x90 */
+
+ .stp_x0_x1 = 0xa93607e0, /* stp x0, x1, [sp, #-0xa0] */
+
+ .ldr_x0_p_prev_loc_1 = 0x58000220, /* ldr x0, #0xXXXX */
+ .ldr_x1_ptr_x0 = 0xf9400001, /* ldr x1, [x0] */
+
+ .ldr_x0_p_area_offset = 0x58000220, /* ldr x0, #0xXXXX */
+ .eor_x0_x1_x0 = 0xca000020, /* eor x0, x1, x0 */
+ .ldr_x1_p_area_ptr = 0x58000161, /* ldr x1, #0xXXXX */
+ .add_x0_x1_x0 = 0x8b000020, /* add x0, x1, x0 */
+
+ .ldrb_w1_x0 = 0x39400001, /* ldrb w1, [x0] */
+ .add_w1_w1_1 = 0x11000421, /* add w1, w1, #1 */
+ .add_w1_w1_w1_lsr_8 = 0x8b412021, /* add x1, x1, x1, lsr #8 */
+
+ .strb_w1_ptr_x0 = 0x39000001, /* strb w1, [x0] */
+
+ .ldr_x0_p_prev_loc_2 = 0x580000e0, /* ldr x0, #0xXXXX */
+ .ldr_x1_p_area_offset_ror = 0x58000141, /* ldr x1, #0xXXXX */
+ .str_x1_ptr_x0 = 0xf9000001, /* str x1, [x0] */
+
+ .ldp_x0_x1 = 0xa97607e0, /* ldp x0, x1, [sp, #-0xa0] */
+
+ .b_end = 0x14000009, /* skip the data */
+
+ .area_ptr = 0x0,
+ .prev_loc_ptr = 0x0,
+ .area_offset = 0x0,
+ .area_offset_ror = 0x0,
+
+ .end = {}
+
+}
+
+;
+
gboolean instrument_is_coverage_optimize_supported(void) {
return true;
@@ -266,16 +352,22 @@ static gboolean instrument_coverage_in_range(gssize offset) {
}
-static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
+static bool instrument_patch_ardp(guint32 *patch, GumAddress insn,
GumAddress target) {
- if (!PAGE_ALIGNED(target)) { FATAL("Target not page aligned"); }
+ if (!PAGE_ALIGNED(target)) {
+
+ FWARNF("Target not page aligned");
+ return false;
+
+ }
gssize distance = target - (GUM_ADDRESS(insn) & PAGE_MASK);
if (!instrument_coverage_in_range(distance)) {
- FATAL("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
- distance);
+ FVERBOSE("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
+ distance);
+ return false;
}
@@ -283,6 +375,95 @@ static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
guint32 imm_high = ((distance >> 14) & 0x7FFFF) << 5;
*patch |= imm_low;
*patch |= imm_high;
+ return true;
+
+}
+
+bool instrument_write_inline(GumArm64Writer *cw, GumAddress code_addr,
+ guint64 area_offset, gsize area_offset_ror) {
+
+ afl_log_code code = {0};
+ code.code = template;
+
+ /*
+ * Given our map is allocated on a 64KB boundary and our map is a multiple of
+ * 64KB in size, then it should also end on a 64 KB boundary. It is followed
+ * by our previous_pc, so this too should be 64KB aligned.
+ */
+ g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
+ g_assert(PAGE_ALIGNED(__afl_area_ptr));
+
+ if (!instrument_patch_ardp(
+ &code.code.adrp_x0_prev_loc1,
+ code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
+ GUM_ADDRESS(instrument_previous_pc_addr))) {
+
+ return false;
+
+ }
+
+ code.code.mov_x0_curr_loc |= area_offset << 5;
+
+ if (!instrument_patch_ardp(
+ &code.code.adrp_x1_area_ptr,
+ code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
+ GUM_ADDRESS(__afl_area_ptr))) {
+
+ return false;
+
+ }
+
+ if (!instrument_patch_ardp(
+ &code.code.adrp_x0_prev_loc2,
+ code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
+ GUM_ADDRESS(instrument_previous_pc_addr))) {
+
+ return false;
+
+ }
+
+ code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
+
+ if (instrument_suppress) {
+
+ gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
+
+ } else {
+
+ size_t offset = offsetof(afl_log_code, code.stp_x0_x1);
+ gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
+ sizeof(afl_log_code) - offset);
+
+ }
+
+ return true;
+
+}
+
+bool instrument_write_inline_long(GumArm64Writer *cw, GumAddress code_addr,
+ guint64 area_offset, gsize area_offset_ror) {
+
+ afl_log_code_long code = {0};
+ code.code = template_long;
+
+ code.code.area_ptr = GUM_ADDRESS(__afl_area_ptr);
+ code.code.prev_loc_ptr = GUM_ADDRESS(instrument_previous_pc_addr);
+ code.code.area_offset = area_offset;
+ code.code.area_offset_ror = GUM_ADDRESS(area_offset_ror);
+
+ if (instrument_suppress) {
+
+ gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code_long));
+
+ } else {
+
+ size_t offset = offsetof(afl_log_code_long, code.stp_x0_x1);
+ gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
+ sizeof(afl_log_code_long) - offset);
+
+ }
+
+ return true;
}
@@ -312,6 +493,8 @@ void instrument_coverage_optimize(const cs_insn *instr,
}
// gum_arm64_writer_put_brk_imm(cw, 0x0);
+ // uint32_t jmp_dot = 0x14000000;
+ // gum_arm64_writer_put_bytes(cw, (guint8 *)&jmp_dot, sizeof(jmp_dot));
if (instrument_suppress) { instrument_coverage_suppress_init(); }
@@ -343,47 +526,19 @@ void instrument_coverage_optimize(const cs_insn *instr,
}
- code.code = template;
-
- /*
- * Given our map is allocated on a 64KB boundary and our map is a multiple of
- * 64KB in size, then it should also end on a 64 KB boundary. It is followed
- * by our previous_pc, so this too should be 64KB aligned.
- */
- g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
- g_assert(PAGE_ALIGNED(__afl_area_ptr));
-
- instrument_patch_ardp(
- &code.code.adrp_x0_prev_loc1,
- code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
- GUM_ADDRESS(instrument_previous_pc_addr));
-
- code.code.mov_x0_curr_loc |= area_offset << 5;
-
- instrument_patch_ardp(
- &code.code.adrp_x1_area_ptr,
- code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
- GUM_ADDRESS(__afl_area_ptr));
-
map_size_pow2 = util_log2(__afl_map_size);
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
- instrument_patch_ardp(
- &code.code.adrp_x0_prev_loc2,
- code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
- GUM_ADDRESS(instrument_previous_pc_addr));
-
- code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
+ code.code = template;
- if (instrument_suppress) {
+ if (!instrument_write_inline(cw, code_addr, area_offset, area_offset_ror)) {
- gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
+ if (!instrument_write_inline_long(cw, code_addr, area_offset,
+ area_offset_ror)) {
- } else {
+ FATAL("Failed to write inline instrumentation");
- size_t offset = offsetof(afl_log_code, code.stp_x0_x1);
- gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
- sizeof(afl_log_code) - offset);
+ }
}