Overriding library functions in Mac OS X, the easy way: DYLD_INSERT_LIBRARIES

Back at MacHack 2003 Jonathan Rentzsch talked about how to override functions and inject code in Mac OS X using [several neat tricks](http://rentzsch.com/papers/overridingMacOSX). He also released a framework called [mach_star](http://rentzsch.com/mach_star/) which has two components: mach_override and mach_inject. These are great, but overkill for some simple cases.

A much easier way of doing library function overrides is using the DYLD_INSERT_LIBRARIES environment variable (analogous to LD_PRELOAD on Linux). The concept is simple: at load time the dynamic linker (dyld) will load any dynamic libraries specified in DYLD_INSERT_LIBRARIES before any libraries the executable wants loaded. By naming a function the same as one in a library function it will override any calls to the original.

The original function is also loaded, and can be retrieved using the dlsym(RTLD_NEXT, “function_name”); function. This allows a simple method of wrapping existing library functions.

Here’s a simple example which prints out the path of every file opened using the “fopen” function (lib_overrides.c):

#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>

// for caching the original fopen implementation
FILE * (*original_fopen) (const char *, const char *) = NULL;

// our fopen override implmentation
FILE * fopen(const char * filename, const char * mode)
{
    // if we haven’t already, retrieve the original fopen implementation
    if (!original_fopen)
        original_fopen = dlsym(RTLD_NEXT, "fopen");

    // do our own processing; in this case just print the parameters
    printf("== fopen: {%s,%s} ==\n", filename, mode);
    
    // call the original fopen with the same arugments
    FILE* f = original_fopen(filename, mode);
    
    // return the result
    return f;
}

And a simple test program (overrides_test.c):

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    char hello[] = "hello world";
    
    FILE *fp = fopen("hello.txt", "w");
   
    if (fp) {
        fwrite(hello, 1, strlen(hello), fp);
        fclose(fp);
    }

    return 0;
}

Compiled and tested:

tlrobinson$ gcc -Wall -o lib_overrides.dylib -dynamiclib lib_overrides.c
tlrobinson$ gcc -Wall -o overrides_test overrides_test.c
tlrobinson$ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=lib_overrides.dylib overrides_test
== fopen: {hello.txt,w} ==
tlrobinson$

There are certainly scenarios far more interesting than this, though!

  • http://security-wire.com/09/how-to-remove-antivirus-8-rogue-anti-spyware.html remove antivirus 8

    Wow, thanks so much! I’m searching for such information!

  • Johan

    Should this also work for methodes which are already dynamically loaded? I’m trying to override a methode which is already dynamically loaded from a library. 
    (Loading methode)void * lib_handle = dlopen(“libmyLib.dylib”, RTLD_GLOBAL);
            if(!lib_handle)
            {
                    printf(“Unable to load libn”);
                    return 1;
            }
            printf(“Dynamic lib loadedn”);
            //Create function;
            addNumbers* newAdder = (addNumbers*)dlsym(lib_handle, “addNumbers”);
            if(!newAdder)
            {
                    printf(“Unable to load functionn”);
                    return 1;
            }
            printf(“Function dynamiclly loadedn”);(override dylib)and then I’m trying to overwrite this methode int (*original_addNumbers) (int a, int b) = NULL;

    // our fopen override implmentation
    int addNumbers(int a, int b)
    {}I compiled and tired you example and it works, but overriding an existing lib doesn’t seem to work for me…