Skip to content

Instantly share code, notes, and snippets.

@NSExceptional
Last active November 2, 2022 17:27
Show Gist options
  • Save NSExceptional/225d87bad2457eecc79dac3a9ace359c to your computer and use it in GitHub Desktop.
Save NSExceptional/225d87bad2457eecc79dac3a9ace359c to your computer and use it in GitHub Desktop.
Hooking UIApplicationMain in Swift or Objc apps with Fishhook
// 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