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
115
116
117
118
119
|
#include "frida-gumjs.h"
#include "config.h"
#include "instrument.h"
#if defined(__x86_64__)
static GumAddress current_log_impl = GUM_ADDRESS(0);
static const guint8 afl_log_code[] = {
0x9c, /* pushfq */
0x51, /* push rcx */
0x52, /* push rdx */
0x48, 0x8b, 0x0d, 0x26,
0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */
0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */
0x48, 0x31, 0xfa, /* xor rdx, rdi */
0x48, 0x03, 0x15, 0x11,
0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */
0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */
0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */
0x66, 0xd1, 0xcf, /* ror di, 1 */
0x48, 0x89, 0x39, /* mov qword [rcx], rdi */
0x5a, /* pop rdx */
0x59, /* pop rcx */
0x9d, /* popfq */
0xc3, /* ret */
0x90
/* Read-only data goes here: */
/* uint8_t* __afl_area_ptr */
/* uint64_t* &previous_pc */
};
gboolean instrument_is_coverage_optimize_supported(void) {
return true;
}
static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
static void instrument_coverate_write_function(GumStalkerOutput *output) {
guint64 misalign = 0;
GumX86Writer *cw = output->writer.x86;
if (current_log_impl == 0 ||
!gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
!gum_x86_writer_can_branch_directly_between(cw->pc + 128,
current_log_impl)) {
gconstpointer after_log_impl = cw->code + 1;
gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
misalign = (cw->pc & 0x7);
if (misalign != 0) {
gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign);
}
current_log_impl = cw->pc;
gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr,
sizeof(__afl_area_ptr));
gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
sizeof(afl_prev_loc_ptr));
gum_x86_writer_put_label(cw, after_log_impl);
}
}
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
instrument_coverate_write_function(output);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-GUM_RED_ZONE_SIZE);
gum_x86_writer_put_push_reg(cw, GUM_REG_RDI);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset);
gum_x86_writer_put_call_address(cw, current_log_impl);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
GUM_RED_ZONE_SIZE);
}
void instrument_flush(GumStalkerOutput *output) {
gum_x86_writer_flush(output->writer.x86);
}
gpointer instrument_cur(GumStalkerOutput *output) {
return gum_x86_writer_cur(output->writer.x86);
}
#endif
|