Skip to content

Instantly share code, notes, and snippets.

@jakobrs
Last active February 16, 2023 07:03
Show Gist options
  • Save jakobrs/1db07ca7e85c2cc25f18e617e3010c39 to your computer and use it in GitHub Desktop.
Save jakobrs/1db07ca7e85c2cc25f18e617e3010c39 to your computer and use it in GitHub Desktop.
#include <dlfcn.h>
#include <mach-o/dyld-interposing.h>
void dyld_func_lookup(const char *name, void **address);
void *dlopen_from(const char *file, int mode, void *caller) __attribute__((weak));
void dlopen_post_hook(const char *file, int mode, void *caller, void *result);
void *interposed_dlopen(const char *file, int mode) {
void *caller = __builtin_extract_return_addr(__builtin_return_address(0));
void *result;
if (Big_Sur) {
/* Big Sur literally gives us a function to do what we want. */
result = dlopen_from(file, mode, caller);
} else if (Catalina || Mojave) {
/* libdyld.dylib sets a "dyld3::ScopedTimer" before and after calling
* `__dyld_dlopen_internal`, but we don't have access to the timer and it's
* probably just for profiling anyway.
*/
void *(*dlopen_internal)(const char *, int, void *);
dyld_func_lookup("__dyld_dlopen_internal", (void **)&dlopen_internal);
result = dlopen_internal(file, mode, caller);
/* Unlike with High Sierra below, I'm not as confident that
* `__dyld_dlopen_internal` will always do what we want, so we call the
* real `dlopen` function as a backup strategy.
*/
if (result == NULL) {
result = dlopen(file, mode);
}
} else if (High_Sierra) {
/* Unlike the normal `dlopen` function, `__dyld_dlopen` uses the
* caller's *caller's* address rather than that of the caller itself. Note
* that this means that this hook must be compiled with
* `-fno-omit-frame-pointer`.
*
* The actual `dlopen` function also has some code to switch to dyld3 if
* the app uses dyld3, but according to what I could find on the internet,
* dyld3 is only enabled for system apps, and only from 2018 on.
*/
void *(*dlopen_internal)(const char *, int);
dyld_func_lookup("__dyld_dlopen", (void **)&dlopen_internal)
result = dlopen_internal(file, mode);
}
dlopen_post_hook(file, mode, caller, result);
return result;
}
DYLD_INTERPOSE(interposed_dlopen, dlopen)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment