int main() { _dyld_register_func_for_add_image(¬ify); void* handle = dlopen("libfoo.dylib", RTLD_LAZY); if ( handle == NULL ) { FAIL("dlopen(\"%s\") failed with: %s", "libfoo.dylib", dlerror()); exit(0); } fooProc fooPtr = (fooProc)dlsym(handle, "foo"); if ( fooPtr == NULL ) { FAIL("dlsym(handle, \"foo\") failed"); exit(0); } void* foosMalloc = (*fooPtr)(); //fprintf(stderr, "foo says &malloc=%p\n", foosMalloc); //fprintf(stderr, "&malloc=%p\n", &malloc); dlclose(handle); if ( foosMalloc == &malloc ) PASS("dlopen-notify-bind"); else FAIL("dlopen-notify-bind libfoo.dylib double bound"); return EXIT_SUCCESS; }
void RegisterAlreadyLoadedClasses() { //for (uint32_t i = 0; i < _dyld_image_count(); i++) //{ // const struct mach_header* hdr = _dyld_get_image_header(i); // ProcessImageLoad(hdr, 0); //} _dyld_register_func_for_add_image(ProcessImageLoad); _dyld_register_func_for_remove_image(ProcessImageUnload); //std::cout << "Done registering\n"; }
void __darwin_gcc3_preregister_frame_info (void) { const _Tinfo_Node *info; _init_keymgr (); info = (_Tinfo_Node *)__keymgr_global[2]; if (info != NULL) { if (info->major_version >= KEYMGR_API_MAJOR_GCC3) return; /* Otherwise, use our own add_image_hooks. */ } _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook); _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook); }
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); if (retval < 0) { return retval; } // If this was the first call, register callback for image additions (which is also invoked for // existing images, otherwise, just run on existing images if (!_rebindings_head->next) { _dyld_register_func_for_add_image(_rebind_symbols_for_image); } else { uint32_t c = _dyld_image_count(); for (uint32_t i = 0; i < c; i++) { _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); } } return retval; }
void _d_osx_image_init() { _dyld_register_func_for_add_image( &on_add_image ); _dyld_register_func_for_remove_image( &on_remove_image ); }
const void* dlopen(const char* filename, int flags) { static char has_callback = 0; if (!has_callback) { _dyld_register_func_for_add_image(dlshim_image_callback); } if (!filename) { return &dl_self; } else { const struct mach_header* img = NULL; if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING); if (!img) { NSObjectFileImage fileImage; callback_count = 0; last_header = NULL; if (NSCreateObjectFileImageFromFile(filename, &fileImage) == NSObjectFileImageSuccess) { NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR); if (callback_count && last_header) img = last_header; } } if (!img) { NSObjectFileImage fileImage; int i, maxi; const char* prefixfilename; maxi = lib_path_count(); for (i = 0; i < maxi && !img; i++) { prefixfilename = lib_path_prefixify(i, filename); callback_count = 0; last_header = NULL; if (NSCreateObjectFileImageFromFile(prefixfilename, &fileImage) == NSObjectFileImageSuccess) { NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR); if (callback_count && last_header) img = last_header; } } } if (img) { if (flags & RTLD_NOW) { NSLookupSymbolInImage(img, "", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); } if (NSIsSymbolNameDefinedInImage(img, "__init")) { NSSymbol initsymbol; void (*initfunc) (void); initsymbol = NSLookupSymbolInImage(img, "__init", 0); initfunc = NSAddressOfSymbol(initsymbol); initfunc(); } } else last_error = DLOPEN_ERROR; return img; } }
__attribute__ ((constructor)) init(void) { /* load the target file into our buffer */ int fd = -1; if ((fd = open(TARGET, O_RDONLY)) == -1) { ERROR_MSG("Can't open target %s.", TARGET); return; } struct stat stat = {0}; if (fstat(fd, &stat) < 0) { ERROR_MSG("Can't fstat target %s.", TARGET); close(fd); return; } void *target_buf = NULL; kern_return_t kr = 0; /* allocate memory with mach_vm_allocate (requisite) and copy the file into it */ kr = mach_vm_allocate(mach_task_self(), (mach_vm_address_t*)&target_buf, stat.st_size, VM_FLAGS_ANYWHERE); if (kr != KERN_SUCCESS) { ERROR_MSG("Can't allocate buffer for target."); close(fd); return; } ssize_t bytes_read = 0; bytes_read = pread(fd, target_buf, stat.st_size, 0); if (bytes_read == -1 || bytes_read < stat.st_size) { ERROR_MSG("Failed to read target."); close(fd); return; } /* modify file type to MH_BUNDLE if necessary */ /* the file type must be MH_BUNDLE but we can convert it on the fly */ struct mach_header *mh = (struct mach_header*)target_buf; if (mh->magic != MH_MAGIC_64) { ERROR_MSG("Invalid Mach-O target."); close(fd); return; } if (mh->filetype != MH_BUNDLE) { mh->filetype = MH_BUNDLE; } /* now we are ready to call the dyld NS* stuff and get our binary executed */ NSObjectFileImageReturnCode dyld_err; NSObjectFileImage ofi; dyld_err = NSCreateObjectFileImageFromMemory(target_buf, stat.st_size, &ofi); if (dyld_err != NSObjectFileImageSuccess) { ERROR_MSG("Failed to create object file with error %d", dyld_err); } const char *moduleName; uint32_t options = NSLINKMODULE_OPTION_BINDNOW; NSModule m = NULL; /* a name for the module so it can be identified by the image observer */ moduleName = INJECTED_MODULE_NAME; /* finally link the module */ m = NSLinkModule(ofi, moduleName, options); if (m == NULL) { ERROR_MSG("Failed to link module!"); } else { /* register a dyld image observer * we need it because we don't know where the injected image was loaded at * it's not our allocated buffer but a new copy of it * so we can find that image via the name and execute it from there */ _dyld_register_func_for_add_image(image_observer); } close(fd); // /* we can deallocate memory because NSLinkModule will create its own copy */ // target_buf = NULL; // mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)target_buf, stat.st_size); }