text: Calling a C function from within a binary on OS X/iOSAugust 31, 2016 in
  If you like this and other posts of mine, then reach out to me at edgar.factorial@gmail.com, I’m looking for remote contract work.
  Let’s say we have a C binary given to us and there’s a C function in it that we want to call. For example, say we have this code, assume it is called
  inject_me.c:
  #include <stdio.h> int test_function(char *some_word) { return printf("Did say: %s\n", some_word); } int main (int argc, char **argv) { return test_function("Hello World"); }
  and we want to call the function
  test_function by ourselves. To do that we need to find the location of the function in the binary. We can do that by disassembling the binary, I used to use command line tools for that but now I’m using
  hopper. (Hopper is an AMAZING program). Once we disassemble it, we find the function in memory:
  Notice that I highlighted the actual location of:
  0x100000f20. Now we can inject it with this code, assume it is called
  inject.c
  #include <stdio.h> #include <string.h> #include <mach-o/dyld.h> #define SPOT 0x100000f20 typedef int pull_it(char *); static pull_it *pulled = NULL; __attribute__((constructor)) void example_injection() { char path[1024]; uint32_t size = sizeof(path); _NSGetExecutablePath(path, &size); for (uint32_t i = 0; i < _dyld_image_count(); i++) { if (strcmp(_dyld_get_image_name(i), path) == 0) { intptr_t slide = _dyld_get_image_vmaddr_slide(i); pulled = (pull_it*)(intptr_t)(slide + SPOT); printf("slide: %lu\n", slide); pulled("Please work\n"); } } printf("This ran before the actual program\n"); }
  The
  __attribute__((constructor))calls the wrapped function before
  maingoes off.
  The slide is needed because: (I found this on some Apple mailing list and don’t remember from where anymore)
  Q: Can someone enlighten me as to what the virtual memory slide amount is ? (this parameter is returned by _dyld_get_image_vmaddr_slide for instance) A: The shared libraries are prebound to an initial base address but when the shared library gets loaded dyld can "slide" the library to a new base address, this is where the virtual memory slide comes from.
  Build both with this
  Makefile
  osx_clang := $(shell xcrun --sdk macosx --find clang) osx_sdk := $(shell xcrun --sdk macosx --show-sdk-path) c_flags := -std=c11 inject_me:inject_me.c @${osx_clang} -isysroot ${osx_sdk} ${c_flags} $< -o $@ code_injection:inject_me @${osx_clang} -isysroot ${osx_sdk} ${c_flags} inject.c -dynamiclib -o $@.dylib
  Now we can invoke it like so:
  $ make code_injection $ DYLD_INSERT_LIBRARIES=code_injection.dylib ./inject_me slide: 125042688 Did say: Please work This ran before the actual program Did say: Hello World
  Yay, it works. BTW, this works for jailbroken iOS as well.