Skip to content

Commit 4933bda

Browse files
committed
fixed adrp imm overflow in save_header
1 parent 7f82b33 commit 4933bda

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

src/interpose.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
#include <mach-o/nlist.h>
77
#include <stdint.h>
88
#include <string.h>
9+
#ifndef COMPACT
10+
#include <mach/mach_error.h> // mach_error_string()
11+
#endif
912

1013
int tiny_interpose(uint32_t image_index, const char *symbol_name, void *replacement) {
1114
intptr_t image_slide = _dyld_get_image_vmaddr_slide(image_index);
1215
struct mach_header_64 *mh_header = (struct mach_header_64 *)_dyld_get_image_header(image_index);
1316
struct load_command *ld_command = (void *)mh_header + sizeof(struct mach_header_64);
14-
struct section_64 *sym_sects[2] = {NULL, NULL};
17+
struct section_64 *sym_sects[2] = {NULL, NULL}; // possible to have both!
1518
struct symtab_command *symtab_cmd = NULL;
1619
struct dysymtab_command *dysymtab_cmd = NULL;
1720
struct segment_command_64 *linkedit_cmd = NULL;
@@ -24,7 +27,6 @@ int tiny_interpose(uint32_t image_index, const char *symbol_name, void *replacem
2427
for (int j = 0; j < segment->nsects; j++) {
2528
if ((data_const_sect[j].flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) {
2629
sym_sects[0] = data_const_sect + j; // __nl_symbol_ptr
27-
break;
2830
}
2931
}
3032
}
@@ -34,7 +36,6 @@ int tiny_interpose(uint32_t image_index, const char *symbol_name, void *replacem
3436
for (int j = 0; j < segment->nsects; j++) {
3537
if ((data_sect[j].flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) {
3638
sym_sects[1] = data_sect + j; // __la_symbol_ptr
37-
break;
3839
}
3940
}
4041
}
@@ -78,15 +79,17 @@ int tiny_interpose(uint32_t image_index, const char *symbol_name, void *replacem
7879
if (i == 0) { // __nl_symbol_ptr in __DATA_CONST
7980
err = mach_vm_protect(mach_task_self(), (mach_vm_address_t)sym_ptrs, sym_sec->size, FALSE,
8081
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
81-
if (err != 0) goto exit;
82+
if (err != 0) {
83+
LOG_ERROR("mach_vm_protect: %s", mach_error_string(err));
84+
break;
85+
}
8286
}
8387
sym_ptrs[j] = replacement;
84-
goto exit;
88+
break;
8589
}
8690
}
8791
}
8892

89-
exit:
9093
if (!found) {
9194
err = -1;
9295
LOG_ERROR("tiny_interpose: no matching indirect symbol found!");

src/private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#define AARCH64_BLR 0xd63f0220 // blr x17
4242
#define AARCH64_ADD 0x91000231 // add x17, x17, 0
4343
#define AARCH64_SUB 0xd1000231 // sub x17, x17, 0
44+
#define AARCH64_MOVZ 0xd2800000 // movz xd, 0
45+
#define AARCH64_MOVK 0xf2800000 // movk xd, 0
4446
#elif __x86_64__
4547
#define X86_64_CALL 0xe8 // call
4648
#define X86_64_JMP 0xe9 // jmp

src/tinyhook.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,32 @@ static inline void save_header(void **src, void **dst, int min_len) {
7979
if (((insn ^ 0x90000000) & 0x9f000000) == 0) {
8080
// adrp
8181
// modify the immediate (len: 4 -> 4)
82-
int64_t len = (insn >> 29 & 0x3) | ((insn >> 3) & 0x1ffffc);
83-
len += ((int64_t)*src >> 12) - ((int64_t)*dst >> 12);
84-
insn &= 0x9f00001f; // clean the immediate
85-
insn = ((len & 0x3) << 29) | ((len & 0x1ffffc) << 3) | insn;
82+
int64_t addr = ((int64_t)*src >> 12) + ((insn >> 29 & 0x3) | ((insn >> 3) & 0x1ffffc));
83+
int64_t len = addr - ((int64_t)*dst >> 12);
84+
if ((len << 12) < 4 * GB) {
85+
insn &= 0x9f00001f; // clean the immediate
86+
insn = ((len & 0x3) << 29) | ((len & 0x1ffffc) << 3) | insn;
87+
*(uint32_t *)*dst = insn;
88+
*dst += 4;
89+
}
90+
else {
91+
int64_t imm64 = addr << 12;
92+
uint16_t rd = insn & 0b11111;
93+
bool cleaned = false;
94+
for (int j = 0; imm64; imm64 >>= 16, j++) {
95+
uint64_t cur_imm = imm64 & 0xffff;
96+
if (cur_imm) {
97+
*(uint32_t *)*dst = (j << 21) | (cur_imm << 5) | rd | (cleaned ? AARCH64_MOVK : AARCH64_MOVZ);
98+
*dst += 4;
99+
cleaned = true;
100+
}
101+
}
102+
}
103+
}
104+
else {
105+
*(uint32_t *)*dst = insn;
106+
*dst += 4;
86107
}
87-
*(uint32_t *)*dst = insn;
88-
*dst += 4;
89108
*src += 4;
90109
}
91110
#elif __x86_64__

0 commit comments

Comments
 (0)