Skip to content

Commit a87b89b

Browse files
committed
added call/jmp handling for x86_64
1 parent 7ec131a commit a87b89b

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

src/tinyhook.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include "fde64/fde64.h"
1212
#endif
1313

14+
int32_t sign_extend(uint32_t x, int N) {
15+
return (int32_t)(x << (32 - N)) >> (32 - N);
16+
}
17+
1418
bool need_far_jump(const void *src, const void *dst) {
1519
long long distance = dst > src ? dst - src : src - dst;
1620
#ifdef __aarch64__
@@ -78,7 +82,8 @@ static inline void save_header(void **src, void **dst, int min_len) {
7882
insn = *(uint32_t *)*src;
7983
if (((insn ^ 0x90000000) & 0x9f000000) == 0) {
8084
// adrp
81-
int64_t addr = ((int64_t)*src >> 12) + ((insn >> 29 & 0x3) | ((insn >> 3) & 0x1ffffc));
85+
int32_t imm21 = sign_extend((insn >> 29 & 0x3) | (insn >> 3 & 0x1ffffc), 21);
86+
int64_t addr = ((int64_t)*src >> 12) + imm21;
8287
int64_t len = addr - ((int64_t)*dst >> 12);
8388
if ((len << 12) < 4 * GB) {
8489
// modify the immediate (len: 4 -> 4)
@@ -105,7 +110,7 @@ static inline void save_header(void **src, void **dst, int min_len) {
105110
else if (((insn ^ 0x14000000) & 0xfc000000) == 0 || ((insn ^ 0x94000000) & 0xfc000000) == 0) {
106111
// b or bl
107112
bool link = insn >> 31;
108-
int32_t imm26 = (int32_t)(insn << 6) >> 6; // sign extend
113+
int32_t imm26 = sign_extend(insn, 26);
109114
void *addr = *src + (imm26 << 2);
110115
*dst += calc_jump(*dst, *dst, addr, link);
111116
}
@@ -136,7 +141,7 @@ static inline void save_header(void **src, void **dst, int min_len) {
136141
*dst += sizeof(uint8_t);
137142
}
138143
else if ((insn.opcode & 0xf0) == 0x70) {
139-
// Jcc (short)
144+
// jcc (short)
140145
// revert the condition and insert a jump (len: 2 -> 2+14)
141146
void *jmp_dst = *src + insn.len + insn.imm8;
142147
int jmp_len = calc_jump(*dst + 2, *dst + 2, jmp_dst, false);
@@ -145,13 +150,19 @@ static inline void save_header(void **src, void **dst, int min_len) {
145150
*dst += 2 + jmp_len;
146151
}
147152
else if (insn.opcode_len == 2 && insn.opcode == 0x0f && (insn.opcode2 & 0xf0) == 0x80) {
148-
// Jcc (near) (len: 6 -> 2+14)
153+
// jcc (near) (len: 6 -> 2+14)
149154
void *jmp_dst = *src + insn.len + insn.imm32;
150155
int jmp_len = calc_jump(*dst + 2, *dst + 2, jmp_dst, false);
151156
*(uint8_t *)*dst = (0x70 | (insn.opcode2 & 0xf)) ^ 1; // invert the condition
152157
*(int8_t *)(*dst + 1) = jmp_len;
153158
*dst += 2 + jmp_len;
154159
}
160+
else if (insn.opcode == 0xe8 || insn.opcode == 0xe9) {
161+
// call or jmp (rel32) (len: 5 -> 5/14)
162+
bool link = (insn.opcode == 0xe8);
163+
void *jmp_dst = *src + insn.len + insn.imm32;
164+
*dst += calc_jump(*dst, *dst, jmp_dst, link);
165+
}
155166
else {
156167
memcpy(*dst, *src, insn.len);
157168
*dst += insn.len;

test/hook/example.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ __attribute__((constructor(0))) int load() {
5050
// hook a function by symbol (in the SYMTAB)
5151
void *func_add = symtbl_solve(0, "_add");
5252
fprintf(stderr, "=== add() address: %p\n", func_add);
53-
tiny_hook(func_add, fake_add, &orig_add);
53+
tiny_hook(func_add, fake_add, (void **)&orig_add);
5454

5555
// hook system function
5656
fprintf(stderr, "=== Hooking printf\n");

test/hook/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ __attribute__((naked)) int add(int a, int b) {
88
#ifdef __arm64__
99
asm volatile("b _add2");
1010
#elif __x86_64__
11-
asm volatile("call _add2");
11+
asm volatile("jmp _add2");
1212
#endif
1313
}
1414

0 commit comments

Comments
 (0)