diff --git a/fishhook.c b/fishhook.c index a048442..564f66d 100644 --- a/fishhook.c +++ b/fishhook.c @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -78,6 +81,27 @@ static int prepend_rebindings(struct rebindings_entry **rebindings_head, return 0; } +static vm_prot_t get_protection(void *sectionStart) { + mach_port_t task = mach_task_self(); + vm_size_t size = 0; + vm_address_t address = (vm_address_t)sectionStart; + memory_object_name_t object; +#if __LP64__ + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; + vm_region_basic_info_data_64_t info; + kern_return_t info_ret = vm_region_64( + task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_64_t)&info, &count, &object); +#else + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; + vm_region_basic_info_data_t info; + kern_return_t info_ret = vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object); +#endif + if (info_ret == KERN_SUCCESS) { + return info.protection; + } else { + return VM_PROT_READ; + } +} static void perform_rebinding_with_section(struct rebindings_entry *rebindings, section_t *section, intptr_t slide, @@ -87,7 +111,9 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, const bool isDataConst = strcmp(section->segname, "__DATA_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) { + oldProtection = get_protection(rebindings); mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); } for (uint i = 0; i < section->size / sizeof(void *); i++) { @@ -117,7 +143,17 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, symbol_loop:; } if (isDataConst) { - mprotect(indirect_symbol_bindings, section->size, PROT_READ); + int protection = 0; + if (oldProtection & VM_PROT_READ) { + protection |= PROT_READ; + } + if (oldProtection & VM_PROT_WRITE) { + protection |= PROT_WRITE; + } + if (oldProtection & VM_PROT_EXECUTE) { + protection |= PROT_EXEC; + } + mprotect(indirect_symbol_bindings, section->size, protection); } }