int main() { void *handle = 0; //handle to store hook-related info mach_substitution original; //original data for restoration Dl_info info; if (!dladdr((void const *)libtest, &info)) //gets an address and a path of a target library { fprintf(stderr, "Failed to get the base address of a library at `%s`!\n", info.dli_fname); goto end; } handle = mach_hook_init(info.dli_fname, info.dli_fbase); if (!handle) { fprintf(stderr, "Redirection init failed!\n"); goto end; } libtest(); //calls puts() from libSystem.B.dylib puts("-----------------------------"); original = mach_hook(handle, "puts", (mach_substitution)hooked_puts); if (!original) { fprintf(stderr, "Redirection failed!\n"); goto end; } libtest(); //calls hooked_puts() puts("-----------------------------"); original = mach_hook(handle, "puts", original); //restores the original relocation if (!original) { fprintf(stderr, "Restoration failed!\n"); goto end; } libtest(); //again calls puts() from libSystem.B.dylib end: mach_hook_free(handle); handle = 0; //no effect here, but just a good advice to prevent double freeing return 0; }
static void * elf_hook(char const *libpath, void const *unused, char const *name, void const *func) { #if 1 return NULL; #else void *libaddr, *handle, *first; char *ptr; Dl_info info; FILE *fp; char cmd[1024]; // find one function from libpath snprintf(cmd, sizeof(cmd), "nm %s | grep ' T ' | head -n 2", libpath); if((fp = popen(cmd, "r")) == NULL) return NULL; if(fgets(cmd, sizeof(cmd), fp) == NULL) { pclose(fp); return NULL; } pclose(fp); // move to end for(ptr = cmd; *ptr; ptr++) ; // seek for the last ' ' or '\t' for(--ptr; ptr >= cmd; ptr--) { if(*ptr==0x0d || *ptr==0x0a) { *ptr = '\0'; } if(*ptr==' ' || *ptr=='\t') { *ptr++ = '\0'; if(*ptr == '_') *ptr++ = '\0'; break; } } // get the function address ga_error("Retrieve base address via function '%s' from %s\n", ptr, libpath); if((handle = dlopen(libpath, RTLD_LAZY)) == NULL) return NULL; if((first = dlsym(handle, ptr)) == NULL) return NULL; // if(dladdr((void const *) first, &info) == 0) return NULL; libaddr = mach_hook_init(libpath, info.dli_fbase); if(libaddr == NULL) return NULL; return (void*) mach_hook(libaddr, name, (mach_substitution) func); #endif }