Skip to content

Commit 864ba9d

Browse files
committed
simplified save_head() -> added x86_64
1 parent afd3d1e commit 864ba9d

File tree

1 file changed

+35
-48
lines changed

1 file changed

+35
-48
lines changed

src/tinyhook.c

Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -67,63 +67,56 @@ static int calc_jump(uint8_t *output, void *src, void *dst, bool link) {
6767
return calc_near_jump(output, src, dst, link);
6868
}
6969

70-
static void save_head(void **src, void **dst, int min_len) {
71-
// return header len (rewritten insns len to dst)
72-
// int skip_len = 0; // insns(to be overwritten) len from src
73-
// int head_len = 0; // rewritten insns len to dst
70+
static void *trampo;
71+
static mach_vm_address_t vmbase;
72+
73+
static inline void save_header(void **src, void **dst, int min_len) {
74+
mach_vm_protect(mach_task_self(), vmbase, PAGE_SIZE, FALSE, VM_PROT_DEFAULT);
7475
#ifdef __aarch64__
75-
// skip_len = min_len;
76-
// head_len = min_len;
77-
// uint8_t bytes_out[MAX_JUMP_SIZE];
78-
// read_mem(bytes_out, src, MAX_JUMP_SIZE);
76+
uint32_t insn;
7977
for (int i = 0; i < min_len; i += 4) {
80-
uint32_t cur = *(uint32_t *)*src;
81-
if (((cur ^ 0x90000000) & 0x9f000000) == 0) {
78+
insn = *(uint32_t *)*src;
79+
if (((insn ^ 0x90000000) & 0x9f000000) == 0) {
8280
// adrp
8381
// modify the immediate
8482
// TODO: improve this
85-
int32_t len = (cur >> 29 & 0x3) | ((cur >> 3) & 0x1ffffc);
83+
int32_t len = (insn >> 29 & 0x3) | ((insn >> 3) & 0x1ffffc);
8684
len += ((int64_t)*src >> 12) - ((int64_t)*dst >> 12);
87-
cur &= 0x9f00001f; // clean the immediate
88-
cur = ((len & 0x3) << 29) | (len >> 2 << 5) | cur;
85+
insn &= 0x9f00001f; // clean the immediate
86+
insn = ((len & 0x3) << 29) | (len >> 2 << 5) | insn;
8987
}
90-
*(uint32_t *)*dst = cur;
88+
*(uint32_t *)*dst = insn;
9189
*dst += 4;
9290
*src += 4;
9391
}
9492
#elif __x86_64__
9593
struct fde64s insn;
96-
uint8_t bytes_in[MAX_JUMP_SIZE * 2], bytes_out[MAX_JUMP_SIZE * 4];
97-
read_mem(bytes_in, src, MAX_JUMP_SIZE * 2);
98-
for (; skip_len < min_len; skip_len += insn.len) {
99-
uint64_t cur_addr = (uint64_t)src + skip_len;
100-
decode(bytes_in + skip_len, &insn);
94+
for (int i = 0; i < min_len; i += insn.len) {
95+
decode(*src, &insn);
10196
if (insn.opcode == 0x8b && insn.modrm_rm == RM_DISP32) {
10297
// mov r64, [rip+]
10398
// split it into 2 instructions
10499
// mov r64 $rip+(immediate)
100+
*(uint16_t *)*dst = X86_64_MOV_RI64;
101+
*dst += sizeof(uint16_t);
102+
*(uint8_t *)*dst = insn.modrm_reg;
103+
*dst += sizeof(uint8_t);
104+
*(uint64_t *)*dst = insn.disp32 + (uint64_t)*src + insn.len;
105+
*dst += sizeof(uint64_t);
105106
// mov r64 [r64]
106-
*(uint16_t *)(bytes_out + head_len++) = X86_64_MOV_RI64;
107-
bytes_out[head_len++] += insn.modrm_reg;
108-
*(uint64_t *)(bytes_out + head_len) = insn.disp32 + cur_addr + insn.len;
109-
head_len += 8;
110-
*(uint16_t *)(bytes_out + head_len) = X86_64_MOV_RM64;
111-
bytes_out[head_len + 2] = insn.modrm_reg << 3 | insn.modrm_reg;
112-
head_len += 3;
107+
*(uint16_t *)*dst = X86_64_MOV_RM64;
108+
*dst += sizeof(uint16_t);
109+
*(uint8_t *)*dst = insn.modrm_reg << 3 | insn.modrm_reg;
110+
*dst += sizeof(uint8_t);
113111
}
114112
else {
115-
memcpy(bytes_out + head_len, bytes_in + skip_len, insn.len);
116-
head_len += insn.len;
113+
memcpy(*dst, *src, insn.len);
114+
*dst += insn.len;
117115
}
116+
*src += insn.len;
118117
}
119118
#endif
120-
// *skip_lenp = skip_len;
121-
// *head_lenp = head_len;
122-
// int kr = write_mem(dst, bytes_out, head_len);
123-
// if (kr != 0) {
124-
// LOG_ERROR("save_head: write_mem failed");
125-
// }
126-
// return kr;
119+
mach_vm_protect(mach_task_self(), vmbase, PAGE_SIZE, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
127120
return;
128121
}
129122

@@ -136,29 +129,23 @@ int tiny_hook(void *src, void *dst, void **orig) {
136129
kr = write_mem(src, jump_insns, jump_size);
137130
}
138131
else {
139-
// static int position = 0;
140-
static mach_vm_address_t vmbase;
141-
static void *trampoline;
142-
if (!trampoline) {
132+
if (!trampo) {
143133
// alloc a vm to store headers and jumps
144134
kr = mach_vm_allocate(mach_task_self(), &vmbase, PAGE_SIZE, VM_FLAGS_ANYWHERE);
145135
if (kr != 0) {
146136
LOG_ERROR("mach_vm_allocate: %s", mach_error_string(kr));
147137
return kr;
148138
}
149-
trampoline = (void *)vmbase;
139+
trampo = (void *)vmbase;
150140
}
151-
// int skip_len, head_len;
152141
void *bak = src;
153-
*orig = trampoline;
142+
*orig = trampo;
154143
jump_size = calc_jump(jump_insns, src, dst, false);
155-
mach_vm_protect(mach_task_self(), vmbase, PAGE_SIZE, FALSE, VM_PROT_DEFAULT);
156-
save_head(&bak, &trampoline, jump_size);
157-
mach_vm_protect(mach_task_self(), vmbase, PAGE_SIZE, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
144+
save_header(&bak, &trampo, jump_size);
158145
kr |= write_mem(src, jump_insns, jump_size);
159-
jump_size += calc_jump(jump_insns, trampoline, bak, false);
160-
kr |= write_mem(trampoline, jump_insns, jump_size);
161-
trampoline += jump_size;
146+
jump_size += calc_jump(jump_insns, trampo, bak, false);
147+
kr |= write_mem(trampo, jump_insns, jump_size);
148+
trampo += jump_size;
162149
}
163150
return kr;
164151
}

0 commit comments

Comments
 (0)