Skip to content

Instantly share code, notes, and snippets.

@NSExceptional
Last active November 2, 2022 17:27
Show Gist options
  • Select an option

  • Save NSExceptional/225d87bad2457eecc79dac3a9ace359c to your computer and use it in GitHub Desktop.

Select an option

Save NSExceptional/225d87bad2457eecc79dac3a9ace359c to your computer and use it in GitHub Desktop.

Revisions

  1. NSExceptional revised this gist Jul 25, 2022. No changes.
  2. NSExceptional created this gist Jul 25, 2022.
    53 changes: 53 additions & 0 deletions HookUIApplicationMain.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    // UIApplicationMain accepts Swift.String in Swift apps; a C forward declaration is needed
    struct SwiftString {
    uint8_t reserved[16];
    };
    typedef struct SwiftString SwiftString;

    int (*orig_UIApplicationMain_objc)(int argc, char *argv[], NSString *_, NSString *delegateClassName) = nil;
    int (*orig_UIApplicationMain_swift)(int argc, char *argv[], SwiftString _, SwiftString delegateClassName) = nil;
    NSString *(*FoundationBridgeSwiftStringToObjC)(SwiftString str) = nil;

    // Our hooks //

    static int UIApplicationMain_objc(int argc, char *argv[], NSString *_, NSString *delegateClassName) {
    Class appDelegateClass = NSClassFromString(delegateClassName)];
    // ...
    return orig_UIApplicationMain_objc(argc, argv, _, delegateClassName);
    }

    static int UIApplicationMain_swift(int argc, char *argv[], SwiftString _, SwiftString delegate) {
    NSString *delegateClassName = FoundationBridgeSwiftStringToObjC(delegate);
    Class appDelegateClass = NSClassFromString(delegateClassName)];
    // ...
    return orig_UIApplicationMain_swift(argc, argv, _, delegate);
    }

    // Hooking logic //

    void ctor() {
    // UIApplicationMain objc
    __unused BOOL didHookObjcMain = flex_rebind_symbols((struct rebinding[1]) {{
    "UIApplicationMain",
    (void *)UIApplicationMain_objc,
    (void **)&orig_UIApplicationMain_objc
    }}, 1) == 0;

    // UIApplicationMain Swift shim
    void *mainBinary = dlopen(NSBundle.mainBundle.executablePath.UTF8String, RTLD_LAZY);
    void *swiftmain = dlsym(mainBinary, "$s5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF");
    // For convering Swift.String (a struct) to an NSString
    void *stringBridge = dlsym(mainBinary, "$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF");

    // If the shim exists, hook it as well. Only one will be called when using Fishhook
    if (swiftmain && stringBridge) {
    // For convering Swift.String (a struct) to an NSString
    FoundationBridgeSwiftStringToObjC = stringBridge;
    // Hook UIApplicationMain(Int32, UnsafeMutablePointer<…>?, Swift.String?, Swift.String?) -> Int32
    __unused BOOL didHookSwiftMain = rebind_symbols((struct rebinding[1]) {{
    "$s5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF",
    (void *)UIApplicationMain_swift,
    (void **)&orig_UIApplicationMain_swift
    }}, 1) == 0;
    }
    }