OSX dynamic library to implement function Interception
In OS X systems, only a few processes can be completed by the kernel loader. Almost all programs are dynamically connected. Generally,/usr/lib/dyld is used as the dynamic linker.
As a private loader, dyld provides some unique features, such as function interception. The DYLD_INTERPOSE macro definition allows a library to replace its function implementation with another function implementation. The following code is taken from the source code of dyld and demonstrates this function.
#if !defined(_DYLD_INTERPOSING_H_)#define _DYLD_INTERPOSING_H_#define DYLD_INTERPOSE(_replacment,_replacee) \ __attribute__((used)) static strut{const void* replacment;const void* replacee;}_interpose_##_replace \ __attribute__((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee};#endif
The function blocking function of dyld provides a new _ DATA zone named _ interpose. in this zone, replace functions and replaced functions are listed in sequence, other tasks are handled by dyld.
The following experiment shows how to track the malloc () function through the function interception mechanism.
# Include # Include # Include # Include # Include // Standard interpose Data Structure typedef struct interpose_s {void * new_func; void * orig_fnc;} interpose_t; // our prototype void * my_malloc (int size ); // corresponds to the real malloc function void my_free (void *); // corresponds to the real free function static const interpose_t interposing_functions [] \__ attribute _ (section ("_ DATA ,__ interpose") ={{ (void *) my_free, (void *) free}, {(void *) my_malloc, (void *) malloc}; void * my_malloc (int size) {// in our function, to access the real malloc () function, because you do not want The entire Heap has been managed, so the original malloc () void * returned = malloc (size) is called; // malloc_printf is called because malloc () is called in printf (), generates infinite recursive calls. Malloc_printf ("+ % p % d \ n", returned, size); return (returned);} void my_free (void * freed) {malloc_printf ("-% p \ n", freed); free (freed);} int main (int argc, const char * argv []) {// release the memory -- print out the address and then call the real free () printf ("Hello, World! \ N "); return 0 ;}
Execute the following code in the terminal to compile to dylib and forcibly insert to ls
cc -dynamiclib 1.c -o libMTrace.dylib -WallDYLD_INSERT_LIBRARIES=libMTrace.dylib ls
In the end, we will find that the location where malloc is called will print such information.
ls(24346) malloc: + 0x100100020 88ls(24346) malloc: + 0x100800000 4096ls(24346) malloc: + 0x100801000 2160ls(24346) malloc: - 0x100800000ls(24346) malloc: + 0x100801a00 3312