Instantly share code, notes, and snippets.
Last activeNovember 2, 2022 17:27
Save NSExceptional/225d87bad2457eecc79dac3a9ace359c to your computer and use it in GitHub Desktop.
Hooking UIApplicationMain in Swift or Objc apps with Fishhook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| // UIApplicationMain accepts Swift.String in Swift apps; a C forward declaration is needed | |
| struct SwiftString { | |
| uint8_t reserved[16]; | |
| }; | |
| typedefstruct 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 // | |
| staticintUIApplicationMain_objc(int argc,char *argv[],NSString *_,NSString *delegateClassName) { | |
| Class appDelegateClass =NSClassFromString(delegateClassName)]; | |
| // ... | |
| returnorig_UIApplicationMain_objc(argc, argv, _, delegateClassName); | |
| } | |
| staticintUIApplicationMain_swift(int argc,char *argv[], SwiftString _, SwiftString delegate) { | |
| NSString *delegateClassName =FoundationBridgeSwiftStringToObjC(delegate); | |
| Class appDelegateClass =NSClassFromString(delegateClassName)]; | |
| // ... | |
| returnorig_UIApplicationMain_swift(argc, argv, _, delegate); | |
| } | |
| // Hooking logic // | |
| voidctor() { | |
| // UIApplicationMain objc | |
| __unusedBOOL 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 | |
| __unusedBOOL didHookSwiftMain =rebind_symbols((struct rebinding[1]) {{ | |
| "$s5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF", | |
| (void *)UIApplicationMain_swift, | |
| (void **)&orig_UIApplicationMain_swift | |
| }},1) ==0; | |
| } | |
| } |
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment