From 2559bcc87aab945011c18970bcd58accb808a077 Mon Sep 17 00:00:00 2001 From: wukaikai Date: Sun, 28 Feb 2021 18:39:40 +0800 Subject: [PATCH 1/2] If hooking in __DATA_CONST/__AUTH_CONST, promise writable before trying to write --- fishhook.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/fishhook.c b/fishhook.c index 026a5c0..eecd438 100644 --- a/fishhook.c +++ b/fishhook.c @@ -54,6 +54,10 @@ typedef struct nlist nlist_t; #define SEG_DATA_CONST "__DATA_CONST" #endif +#ifndef SEG_AUTH_CONST +#define SEG_AUTH_CONST "__AUTH_CONST" +#endif + struct rebindings_entry { struct rebinding *rebindings; size_t rebindings_nel; @@ -109,17 +113,22 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, char *strtab, uint32_t *indirect_symtab) { const bool isDataConst = strcmp(section->segname, SEG_DATA_CONST) == 0; + const bool isAuthConst = strcmp(section->segname, SEG_AUTH_CONST) == 0; uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); vm_prot_t oldProtection = VM_PROT_READ; - if (isDataConst) { + vm_size_t trunc_address = (vm_size_t)indirect_symbol_bindings; + vm_size_t trunc_size = 0; + if (isDataConst || isAuthConst) { oldProtection = get_protection(rebindings); - mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); + trunc_address = trunc_page((vm_size_t)indirect_symbol_bindings); + trunc_size =(vm_size_t)indirect_symbol_bindings -trunc_address; + mprotect((void *)trunc_address, section->size+trunc_size, PROT_READ | PROT_WRITE); } for (uint i = 0; i < section->size / sizeof(void *); i++) { uint32_t symtab_index = indirect_symbol_indices[i]; if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || - symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { + symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { continue; } uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; @@ -142,7 +151,7 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, } symbol_loop:; } - if (isDataConst) { + if (isDataConst || isAuthConst) { int protection = 0; if (oldProtection & VM_PROT_READ) { protection |= PROT_READ; @@ -153,7 +162,7 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, if (oldProtection & VM_PROT_EXECUTE) { protection |= PROT_EXEC; } - mprotect(indirect_symbol_bindings, section->size, protection); + mprotect((void *)trunc_address, section->size+trunc_size, protection); } } @@ -202,7 +211,8 @@ static void rebind_symbols_for_image(struct rebindings_entry *rebindings, cur_seg_cmd = (segment_command_t *)cur; if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && - strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { + strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0 && + strcmp(cur_seg_cmd->segname, SEG_AUTH_CONST) != 0) { continue; } for (uint j = 0; j < cur_seg_cmd->nsects; j++) { From 9000c7d91ea35f23f2c4bb7b2c84274647c5fdd7 Mon Sep 17 00:00:00 2001 From: wukaikai Date: Tue, 2 Mar 2021 21:25:49 +0800 Subject: [PATCH 2/2] set memory protection in multithread --- fishhook.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fishhook.c b/fishhook.c index eecd438..22cd1e3 100644 --- a/fishhook.c +++ b/fishhook.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef __LP64__ typedef struct mach_header_64 mach_header_t; @@ -65,6 +66,7 @@ struct rebindings_entry { }; static struct rebindings_entry *_rebindings_head; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int prepend_rebindings(struct rebindings_entry **rebindings_head, struct rebinding rebindings[], @@ -120,9 +122,10 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, vm_size_t trunc_address = (vm_size_t)indirect_symbol_bindings; vm_size_t trunc_size = 0; if (isDataConst || isAuthConst) { - oldProtection = get_protection(rebindings); trunc_address = trunc_page((vm_size_t)indirect_symbol_bindings); trunc_size =(vm_size_t)indirect_symbol_bindings -trunc_address; + pthread_mutex_lock(&mutex); + oldProtection = get_protection((void *)trunc_address); mprotect((void *)trunc_address, section->size+trunc_size, PROT_READ | PROT_WRITE); } for (uint i = 0; i < section->size / sizeof(void *); i++) { @@ -163,6 +166,7 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, protection |= PROT_EXEC; } mprotect((void *)trunc_address, section->size+trunc_size, protection); + pthread_mutex_unlock(&mutex); } }