#include <mach/host_info.h> #include <mach/mach_host.h> #include <mach/shared_region.h> #include <mach/mach.h> #include <mach-o/dyld.h> #include <stdlib.h> #include <stdio.h> #import <dlfcn.h> #include <assert.h> #include <errno.h> #include <sys/sysctl.h> #include <sys/mman.h> #pragma mark read and write /* Note : buffer must be free'd manually */ unsigned char * xnu_read (int pid, void* addr, size_t* size) { assert(*size != 0 || addr != 0); *size = _word_align(*size); unsigned char *rbuffer = (unsigned char*)malloc(*size); if (rbuffer == 0) printf("Allocation error : xnu_read \n"); mach_msg_type_number_t data_cnt; mach_port_t task; kern_return_t kernret = task_for_pid(mach_task_self(), pid, &task); if (kernret != KERN_SUCCESS) printf("Error : task_for_pid \n"); kernret = vm_read(task, (vm_address_t)addr, *size, (vm_offset_t*)&rbuffer, &data_cnt); if(kernret != KERN_SUCCESS) free(rbuffer); return rbuffer; } int xnu_write (int pid, void* addr, unsigned char* data, size_t dsize) { assert(dsize != 0); assert(addr != 0); assert(data != 0); dsize = _word_align(dsize); unsigned char * ptxt = (unsigned char*)malloc(dsize); assert(ptxt != 0); memcpy(ptxt, data, dsize); mach_port_t task; //vm_info_region_t regbackup; mach_msg_type_number_t dataCunt = dsize; kern_return_t kret = task_for_pid(mach_task_self(), pid, &task); //mach_vm_region_info(task, (vm_address_t)addr, ®backup,0 , 0); /* retrieve write permision */ vm_protect(task, (vm_address_t)addr, (vm_size_t)dsize, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_ALL); kret = vm_write(task, (vm_address_t)addr, (pointer_t)ptxt, dataCunt); return kret; } mach_error_t setpage_exec(void *address) { mach_error_t err = err_none; vm_size_t pageSize; host_page_size( mach_host_self(), &pageSize ); uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); int e = err_none; e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ); e |= msync((void *)page, pageSize, MS_INVALIDATE ); if (e) { printf("Cannot create executable page\n"); } return err; } size_t _word_align(size_t size) { size_t rsize = 0; rsize = ((size % sizeof(long)) > 0) ? (sizeof(long) - (size % sizeof(long))) : 0; rsize += size; return rsize; } /* Mach-O format related functions */ #pragma mark macho __uint64_t getAddressOfLibrary( char* libraryPath ) { const struct mach_header* mh; int n = _dyld_image_count(); int i = 0; for( i = 0; i < n; i++ ) { mh = _dyld_get_image_header(i); if( mh->filetype != MH_DYLIB ){ continue; } const char* imageName = _dyld_get_image_name(i); printf("%s\n",imageName); if( strcmp(imageName, libraryPath) == 0 ) { struct segment_command_64* seg; struct load_command* cmd; cmd = (struct load_command*)((char*)mh + sizeof(struct mach_header_64)); int j = 0; for( j = 0; j < mh->ncmds; j++ ) { if( cmd->cmd == LC_SEGMENT_64 ) { seg = (struct segment_command_64*)cmd; if( strcmp(seg->segname, SEG_TEXT) == 0 ) { return seg->vmaddr + (__uint64_t)_dyld_get_image_vmaddr_slide(i); } } cmd = (struct load_command*)((char*)cmd + cmd->cmdsize); } return _dyld_get_image_vmaddr_slide(i); } } return 0; } /* Retrieve symbol pointer at runtime */ __uint64_t getAddressOfSymbol(char* libpath, char * symbol) { void* hlib = dlopen(libpath, RTLD_NOW); void* funcaddr64 = dlsym(hlib, symbol); return (unsigned long long)funcaddr64; } #pragma mark processes int32_t procpid (char* procname) { pid_t pid; int j; kinfo_proc * proclist; size_t procCount; getprocessList(&proclist, &procCount); for (j = 0; j < procCount +1; j++) { if (strcmp(proclist[j].kp_proc.p_comm, procname) == 0 ) pid = proclist[j].kp_proc.p_pid; } free(proclist); return pid; } static int getprocessList(kinfo_proc **procList, size_t *procCount) { int err; kinfo_proc * result; int done; static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; size_t length; assert( procList != NULL); //assert(*procList == NULL); assert(procCount != NULL); *procCount = 0; result = NULL; done = 0; do { assert(result == NULL); length = 0; err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0); if (err == -1) { err = errno; } if (err == 0) { result = malloc(length); if (result == NULL) { err = ENOMEM; } } if (err == 0) { err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0); if (err == -1) { err = errno; } if (err == 0) { done = 1; } else if (err == ENOMEM) { assert(result != NULL); free(result); result = NULL; err = 0; } } } while (err == 0 && ! done); if (err != 0 && result != NULL) { free(result); result = NULL; } *procList = result; if (err == 0) { *procCount = length / sizeof(kinfo_proc); } assert( (err == 0) == (*procList != NULL) ); return err; }
发表评论