◀ Back to NotesPublished on March 16, 2023

Injecting a DYLIB into a macOS app

Create a .c file:

injector.m

#include <stdio.h>

__attribute__((constructor))
static void customConstructor(int argc, const char **argv) {
    printf("DYLIB injection successful!\n");
}

Compile it with:

clang -ObjC -framework Foundation -framework Cocoa -target x86_64-apple-darwin-macho -dynamiclib injector.m -o injector-x86.dylib
clang -ObjC -framework Foundation -framework Cocoa -target arm64-apple-darwin20.1.0 -dynamiclib injector.m -o injector-arm64.dylib
lipo -create -output injector.dylib injector-*.dylib

Place it inside the app's resources folder:

cp injector.dylib MyApp.app/Contents/Resources/injector.dylib

Use insert_dylib to make the app binary load it:

insert_dylib --inplace @executable_path/../Resources/injector.dylib MyApp.app/Contents/MacOS/MyApp

Codesign the app:

codesign -fs $CODESIGN_CERT -o runtime --timestamp MyApp.app

After that, running the binary in the terminal should show the relevant message before anything else:

❯ MyApp.app/Contents/MacOS/MyApp
DYLIB injection successful!

Does the extension matter? seems not

cp injector.dylib MyApp.app/Contents/Resources/injector
insert_dylib --inplace @executable_path/../Resources/injector.dylib MyApp.app/Contents/MacOS/MyApp

❯ MyApp.app/Contents/MacOS/MyApp
DYLIB injection successful!