int FakeAddrStart(unsigned char * addr, uint64 size) {
mach_vm_size_t region_size = (mach_vm_size_t)size;
mach_vm_address_t region = (vm_address_t)addr;
/* Change memory protections to rw- */
if (vm_protect(mach_task_self(), region, region_size, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY) != KERN_SUCCESS)
{
//_LineLog();
return 1;
}
return 0;
}
int FakeAddrEnd(unsigned char * addr, uint64 size) {
mach_vm_size_t region_size = (mach_vm_size_t)size;
mach_vm_address_t region = (vm_address_t)addr;
// /* Actually perform the write */
// *address = code;
//
// /* Flush CPU data cache to save write to RAM */
// sys_dcache_flush(address, sizeof(code));
//
// /* Invalidate instruction cache to make the CPU read patched instructions from RAM */
// sys_icache_invalidate(address, sizeof(code));
/* Change memory protections back to r-x */
vm_protect(mach_task_self(), region, region_size, 0, VM_PROT_EXECUTE | VM_PROT_READ);
return 0;
}
unsigned char * GetFuncAddr(const char *funcName) {
const struct mach_header_64 *header = (const struct mach_header_64 *)_dyld_get_image_header(0);
uintptr_t vm_slide = _dyld_get_image_vmaddr_slide(0);
if (header == NULL) {
return NULL;
}
struct symtab_command *symtab = NULL;
struct segment_command_64 *seg_linkedit = NULL;
struct segment_command_64 *seg_text = NULL;
struct segment_command_64 *command = (struct segment_command_64 *)(header+1);
for (uint32_t i = 0; i < header->ncmds; i++) {
if(command->cmd == LC_SEGMENT_64) {
if(strcmp( command->segname, SEG_TEXT) == 0) {
seg_text = (struct segment_command_64 *)command;
}
else if(strcmp( command->segname,SEG_LINKEDIT) == 0) {
seg_linkedit = (struct segment_command_64 *)command;
}
}
else if(command->cmd == LC_SYMTAB) {
symtab = (struct symtab_command *)command;
}
if(seg_text != NULL && seg_linkedit != NULL && symtab != NULL) {
break;
}
command = (struct segment_command_64 *)((unsigned char *)command + command->cmdsize);
}
if ((NULL == seg_text) || (NULL == seg_linkedit) || (NULL == symtab)) {
return NULL;
}
uintptr_t linkedit_addr = vm_slide + seg_linkedit->vmaddr - seg_linkedit->fileoff;
intptr_t string_table = linkedit_addr + symtab->stroff;
struct nlist_64 *nlist = (struct nlist_64 *)(linkedit_addr + symtab->symoff);
uintptr_t ptr = 0;
for (uint32_t i = 0; i < symtab->nsyms; i++, nlist++)
{
if (!nlist->n_value || !nlist->n_un.n_strx) continue;
const char *name =(const char *)string_table + nlist->n_un.n_strx;
ptr =nlist->n_value + vm_slide;
if(strcmp(name, funcName) == 0) {
break;;
}
}
return (unsigned char *)ptr;
}
void
__attribute__((__constructor__))
module_init() {
const char *funcName = "***"; //C++ __Z start,
unsigned char * ptr = (unsigned char *)GetFuncAddr(funcName);
FakeAddrStart(ptr, 6);
ptr[4] = 0x5d;
ptr[5] = 0xc3;
FakeAddrEnd(ptr, 6);
}