1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "frida-gumjs.h"
#include "config.h"
#include "instrument.h"
#if defined(__aarch64__)
static GumAddress current_log_impl = GUM_ADDRESS(0);
static const guint8 afl_log_code[] = {
// __afl_area_ptr[current_pc ^ previous_pc]++;
// previous_pc = current_pc ROR 1;
0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]!
0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]!
// x0 = current_pc
0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr
0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr)
0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc
0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc)
// __afl_area_ptr[current_pc ^ previous_pc]++;
0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0
0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2]
0x63, 0x04, 0x00, 0x91, // add x3, x3, #1
0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr
0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2]
// previous_pc = current_pc ROR 1;
0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1
0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63
0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48
0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc
0x40, 0x00, 0x00, 0xf9, // str x0, [x2]
0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10
0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10
0xC0, 0x03, 0x5F, 0xD6, // ret
// &afl_area_ptr_ptr
// &afl_prev_loc_ptr
};
gboolean instrument_is_coverage_optimize_supported(void) {
return true;
}
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) {
guint64 current_pc = instr->address;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
GumArm64Writer *cw = output->writer.arm64;
if (current_log_impl == 0 ||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc,
current_log_impl) ||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128,
current_log_impl)) {
gconstpointer after_log_impl = cw->code + 1;
gum_arm64_writer_put_b_label(cw, after_log_impl);
current_log_impl = cw->pc;
gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
sizeof(afl_area_ptr_ptr));
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
sizeof(afl_prev_loc_ptr));
gum_arm64_writer_put_label(cw, after_log_impl);
}
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE),
GUM_INDEX_PRE_ADJUST);
gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset);
gum_arm64_writer_put_bl_imm(cw, current_log_impl);
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE,
GUM_INDEX_POST_ADJUST);
}
void instrument_coverage_optimize_init(void) {
}
void instrument_flush(GumStalkerOutput *output) {
gum_arm64_writer_flush(output->writer.arm64);
}
gpointer instrument_cur(GumStalkerOutput *output) {
return gum_arm64_writer_cur(output->writer.arm64);
}
#endif
|