Fishhook
As we all know, Method Swizzle is the preferred hook solution for Objective-C, so everyone expressed that the core content should be written in C.
Next, let's talk about the hook solution for C functions in iOS. First, let's introduce the first solution-fishhook.
What is fishhook?
Fishhook is an open-source tool provided by facebook to dynamically modify the Mach-O symbol table.
What is Mach-OMach-O, short for the Mach Object file format, is also used for iOS executable files, target code, dynamic library, and kernel dump file format.
Mach-O has its own dylib specification.
For more information about the principles of fishhook, see How it works. Here is a brief description.
Dyld links have two types of symbols: lazy and non-lazy. fishhook can be used to re-link or replace local symbols.
, __Data has two sections related to dynamic Symbolic Links: __nl_symbol_ptr and _ la_symbol_ptr. _ Nl_symbol_ptr is a pointer array that directly binds data to non-lazy. _ La_symbol_ptr is also a pointer array, which is linked via dyld_stub_binder. The section header of <mach-o/loader. h> provides the offset of the symbol table.
In the figure, 1061 is the offset of the indirect symbol table. * (Offset + indirect symbol address) = 16343, that is, the offset of the symbol table. Each structure in the symbol table is an nlist struct, which contains the offsets of the two tables. The function pointer is determined based on the offsets of the tables Table.
Fishhook is the offset of the indirect symbol table. It provides a false nlist struct to hook the table.
Fishhook replacement symbol function:
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { int retval = prepend_rebindings(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;}
The key function is _ dyld_register_func_for_add_image. This function is used to register the callback. When the dyld link symbol is used, this callback function is called. Rebind_symbols_for_image is replaced and filled.
Example of replacing the Core Foundation function with fishhook
The following is an officially provided instance code to replace the open and close functions in Core Foundation:
# Import <dlfcn. h> # import <UIKit/UIKit. h> # import "AppDelegate. h "# import" fishhook. h "static int (* orig_close) (int); static int (* orig_open) (const char *, int ,...); void save_original_symbols () {orig_close = dlsym (RTLD_DEFAULT, "close"); orig_open = dlsym (RTLD_DEFAULT, "open");} int my_close (int fd) {printf ("Calling real close (% d) \ n", fd); return orig_close (fd);} int my_open (const char * path, int oflag ,...) {Va_list ap = {0}; mode_t mode = 0; if (oflag & O_CREAT )! = 0) {// mode only applies to O_CREAT va_start (ap, oflag); mode = va_arg (ap, int); va_end (ap ); printf ("Calling real open ('% s', % d, % d) \ n", path, oflag, mode); return orig_open (path, oflag, mode );} else {printf ("Calling real open ('% s', % d) \ n", path, oflag); return orig_open (path, oflag, mode );}} int main (int argc, char * argv []) {@ autoreleasepool {save_original_symbols (); // fishhook usage rebind_symbols (struct rebinding [2]) {"close ", my_close}, {"open", my_open}, 2 ); // Open our own binary and print out first 4 bytes (which is the same // for all Mach-O binaries on a given architecture) int fd = open (argv [0], o_RDONLY); uint32_t magic_number = 0; read (fd, & magic_number, 4); printf ("Mach-O Magic Number: % x \ n", magic_number ); close (fd); return UIApplicationMain (argc, argv, nil, NSStringFromClass ([AppDelegate class]);}
Comments // fishhook usage
rebind_symbols((struct rebinding[2]){{"close", my_close}, {"open", my_open}}, 2);
The first parameter passed in rebind_symbols is a struct array, which contains the corresponding array content.
I have to say that facebook is NB.