Last active
November 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 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]; | |
}; | |
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment