在macOS上,我如何拦截对dlsym的调用?

时间:2017-10-21 04:41:03

标签: macos dlopen

我正在尝试检查调用dlopendlsym的程序的行为:最终目标是插入一个小函数,将函数记录到通过dlsym获得的函数。

通常情况下,对于要用foo包装的某些函数DYLD_INSERT_LIBRARIES,可以这样写:

void (*real_foo)(void);

void init() __attribute__((constructor)) {
    real_foo = dlsym(RTLD_NEXT, "foo");
}

void foo(void) {
    puts("foo was called");
    real_foo();
}

问题在于,当你试图包裹dlsym时,你最终得到了这个:

void* (*real_dlsym)(void* handle, const char* symbol);

void init() __attribute__((constructor)) {
    real_dlsym = dlsym(RTLD_NEXT, "dlsym");
}

void* dlsym(void* handle, const char* symbol) {
    return real_dlsym(handle, symbol);
}

init最终会调用您自己的dlsym实现,这无济于事。

当我导出另一个时,如何获得“真正的”dlsym?或者有更好的方法来拦截对dlsym的调用吗?

1 个答案:

答案 0 :(得分:0)

至少在10.12系统上,dlsym实际上是在/usr/lib/system/libdyld.dylib中实现的。它应该适用于dlopen()该文件,然后使用返回的句柄调用dlsym()以获得真正的dlsym()实现。您可能需要额外modedlopen()标记,例如RTLD_FIRST和/或RTLD_LOCAL。排序如下:

    void *libdyld_handle = dlopen("/usr/lib/system/libdyld.dylib", RTLD_LAZY);
    void *dlsym_funcptr = dlsym(libdyld_handle, "dlsym");
相关问题