├── 0000CrossOverIPC.plist ├── 0000CrossOverIPC.xm ├── CrossOverIPC.h ├── LICENSE ├── Makefile ├── PlistManager.h ├── PlistManager.m ├── README.md ├── Test_Tweaks ├── CrossOverIPC_Apps.plist ├── CrossOverIPC_Apps.xm ├── CrossOverIPC_SB.plist ├── CrossOverIPC_SB.xm ├── Makefile ├── control └── layout │ └── DEBIAN │ └── postinst ├── control ├── ent.plist ├── layout └── DEBIAN │ └── postinst ├── libCrossOverIPC.h └── libCrossOverIPC ├── Makefile └── libCrossOverIPC.mm /0000CrossOverIPC.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.Foundation" 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /0000CrossOverIPC.xm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | %ctor { dlopen("/var/jb/usr/lib/libCrossOverIPC.dylib", RTLD_LAZY); } -------------------------------------------------------------------------------- /CrossOverIPC.h: -------------------------------------------------------------------------------- 1 | @import CoreFoundation; 2 | @import Foundation; 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #import 9 | 10 | 11 | typedef enum CrossOverIPCServiceType : CFIndex { 12 | 13 | SERVICE_TYPE_SENDER, 14 | SERVICE_TYPE_LISTENER 15 | 16 | } CrossOverIPCServiceType; 17 | 18 | 19 | @interface CrossOverIPC : NSObject 20 | 21 | + (instancetype) centerNamed:(NSString *)serviceName type:(CrossOverIPCServiceType)type; 22 | - (void) sendMessageName:(NSString *)msgName userInfo:(NSDictionary *)userInfo; 23 | - (NSDictionary *) sendMessageAndReceiveReplyName:(NSString *)msgName userInfo:(NSDictionary *)userInfo; 24 | - (void) registerForMessageName:(NSString *)msgName target:(id)target selector:(SEL)sel; 25 | 26 | 27 | @end 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 CrazyMind 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | 3 | export TARGET = iphone:14.5 4 | export SDKVERSION = 14.5 5 | 6 | export THEOS_PACKAGE_SCHEME = rootless 7 | 8 | export iP = 192.168.1.102 9 | export Port = 22 10 | export Pass = alpine 11 | export Bundle = com.apple.springboard 12 | 13 | export DEBUG = 1 14 | 15 | include $(THEOS)/makefiles/common.mk 16 | 17 | 18 | export TWEAK_NAME = 0000CrossOverIPC 19 | 20 | 0000CrossOverIPC_FILES = 0000CrossOverIPC.xm 21 | 0000CrossOverIPC_CFLAGS = -std=c++11 22 | 0000CrossOverIPC_CODESIGN_FLAGS = -Sent.plist 23 | 24 | 25 | ADDITIONAL_CFLAGS += -DTHEOS_LEAN_AND_MEAN -Wno-shorten-64-to-32 26 | 27 | 28 | include $(THEOS_MAKE_PATH)/tweak.mk 29 | 30 | 31 | SUBPROJECTS += libCrossOverIPC 32 | # SUBPROJECTS += Test_Tweaks 33 | 34 | 35 | 36 | 37 | include $(THEOS_MAKE_PATH)/aggregate.mk 38 | 39 | before-package:: 40 | $(ECHO_NOTHING) chmod 755 $(CURDIR)/.theos/_/DEBIAN/* $(ECHO_END) 41 | $(ECHO_NOTHING) chmod 755 $(CURDIR)/.theos/_/DEBIAN $(ECHO_END) 42 | 43 | 44 | install6:: 45 | install6.exec -------------------------------------------------------------------------------- /PlistManager.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | 6 | 7 | 8 | @interface PlistManager : NSObject 9 | 10 | @property (nonatomic, strong) NSString *plistPath; 11 | 12 | + (instancetype)shared; 13 | 14 | - (NSMutableDictionary *)loadPlist; 15 | 16 | - (void)removeAllObjects; 17 | - (void)removeObjectForKey:(NSString *)key; 18 | 19 | - (void)setObject:(id)obj forKey:(NSString *)key; 20 | - (id)objectForKey:(NSString *)key; 21 | 22 | - (void)setBool:(BOOL)value forKey:(NSString *)key; 23 | - (BOOL)boolForKey:(NSString *)key; 24 | 25 | - (void)setInt:(NSInteger)value forKey:(NSString *)key; 26 | - (NSInteger)intForKey:(NSString *)key; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /PlistManager.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "PlistManager.h" 4 | 5 | 6 | 7 | 8 | @implementation PlistManager 9 | 10 | + (instancetype)shared { 11 | static PlistManager *sharedInstance = nil; 12 | static dispatch_once_t onceToken; 13 | dispatch_once(&onceToken, ^{ 14 | sharedInstance = [[self alloc] init]; 15 | sharedInstance.plistPath = @"/var/jb/var/mobile/Library/Preferences/libCrossOverIPC.plist"; 16 | 17 | NSFileManager *fileManager = [NSFileManager defaultManager]; 18 | 19 | if (![fileManager fileExistsAtPath:sharedInstance.plistPath]) 20 | [@{} writeToFile:sharedInstance.plistPath atomically:YES]; 21 | 22 | }); 23 | return sharedInstance; 24 | } 25 | 26 | - (NSMutableDictionary *)loadPlist { 27 | if (self.plistPath == nil) { 28 | return nil; 29 | } 30 | if (![[NSFileManager defaultManager] fileExistsAtPath:self.plistPath]) { 31 | return nil; 32 | } 33 | return [NSMutableDictionary dictionaryWithContentsOfFile:self.plistPath]; 34 | } 35 | 36 | - (void)removeAllObjects { 37 | if (self.plistPath == nil) { 38 | return; 39 | } 40 | 41 | NSMutableDictionary *plist = [self loadPlist]; 42 | if (plist == nil) return; 43 | 44 | [plist removeAllObjects]; 45 | [self savePlist:plist]; 46 | } 47 | 48 | 49 | - (void)savePlist:(NSDictionary *)plist { 50 | if (self.plistPath == nil) { 51 | return; 52 | } 53 | if (![plist writeToFile:self.plistPath atomically:YES]) { 54 | } 55 | } 56 | 57 | - (void)removeObjectForKey:(NSString *)key { 58 | if (self.plistPath == nil) { 59 | return; 60 | } 61 | if (key == nil) { 62 | return; 63 | } 64 | 65 | NSMutableDictionary *plist = [self loadPlist]; 66 | if (plist == nil) return; 67 | [plist removeObjectForKey:key]; 68 | [self savePlist:plist]; 69 | } 70 | 71 | - (void)setObject:(id)obj forKey:(NSString *)key { 72 | if (self.plistPath == nil) { 73 | return; 74 | } 75 | if (key == nil) { 76 | return; 77 | } 78 | if (obj == nil) { 79 | return; 80 | } 81 | 82 | NSMutableDictionary *plist = [self loadPlist]; 83 | if (plist == nil) return; 84 | plist[key] = obj; 85 | [self savePlist:plist]; 86 | } 87 | 88 | 89 | - (id)objectForKey:(NSString *)key { 90 | if (self.plistPath == nil) { 91 | return nil; 92 | } 93 | if (key == nil) { 94 | return nil; 95 | } 96 | 97 | NSMutableDictionary *plist = [self loadPlist]; 98 | if (plist == nil) return nil; 99 | return plist[key]; 100 | } 101 | 102 | - (void)setBool:(BOOL)value forKey:(NSString *)key { 103 | [self setObject:@(value) forKey:key]; 104 | } 105 | 106 | - (BOOL)boolForKey:(NSString *)key { 107 | id obj = [self objectForKey:key]; 108 | return [obj boolValue]; 109 | } 110 | 111 | - (void)setInt:(NSInteger)value forKey:(NSString *)key { 112 | [self setObject:@(value) forKey:key]; 113 | } 114 | 115 | - (NSInteger)intForKey:(NSString *)key { 116 | id obj = [self objectForKey:key]; 117 | return [obj integerValue]; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | High Voltage 4 |

CrossOverIPC

5 |
6 | Dopamine 7 | Roothide 8 | Architecture 9 | 10 | Releases 11 | 12 |
13 | 14 |
15 | 16 | 17 | ## Description : 18 | *A lightweight cross-process communication tool for sending and receiving messages on iOS 15 & 16 for rootless jailbreaks* 19 | 20 | ## What does it do ? 21 | 22 | * **Send Messages :** *Send a message with a value to another process .* 23 | * **Send Messages With Reply :** *Send a message with a value to other processes and get an instant reply from those processes .* 24 | 25 | ## How does it work ? 26 | 27 | *This tool relies on the ```CFNotificationCenterGetDistributedCenter()``` function from macOS. It is also compatible with iOS. The primary functionality of this func is to send cross-process notifications.* 28 | 29 | *Given the restrictions on ```CPDistributedMessagingCenter```, I have implemented its methods using the ```CFNotificationCenterGetDistributedCenter()``` function. This approach ensures that cross-process communication is possible even under the limitations imposed by the platform.* 30 | 31 | *By leveraging this functionality, developers can efficiently send notifications across different processes, enhancing the ```IPC``` capabilities of their tweaks.* 32 | 33 | 34 | ## Header file : 35 | 36 | ```objective-c 37 | typedef enum CrossOverIPCServiceType : CFIndex { 38 | 39 | SERVICE_TYPE_SENDER, 40 | SERVICE_TYPE_LISTENER 41 | 42 | } CrossOverIPCServiceType; 43 | 44 | 45 | @interface CrossOverIPC : NSObject 46 | 47 | + (instancetype) centerNamed:(NSString *)serviceName type:(CrossOverIPCServiceType)type; 48 | - (void) registerForMessageName:(NSString *)msgName target:(id)target selector:(SEL)sel; 49 | - (void) sendMessageName:(NSString *)msgName userInfo:(NSDictionary *)userInfo; 50 | - (NSDictionary *) sendMessageAndReceiveReplyName:(NSString *)msgName userInfo:(NSDictionary *)userInfo; 51 | 52 | @end 53 | 54 | ``` 55 | ## How to use it ? 56 | 57 | #### For example ~ Getting UDID from SpringBoard to App .. 58 | 59 | * Add `CrossOverIPC.h` to your project . 60 | ```objective-c 61 | #import "CrossOverIPC.h" 62 | ``` 63 | 64 | 65 | ## ~ SpringBoard : 66 | ```objective-c 67 | #define _serviceName @"com.cm90.crossOverIPC" 68 | 69 | CrossOverIPC *crossOver = [objc_getClass("CrossOverIPC") centerNamed:_serviceName type:SERVICE_TYPE_LISTENER]; 70 | [crossOver registerForMessageName:@"UDID_Getter" target:self selector:@selector(handleMSG:userInfo:)]; 71 | ``` 72 | 73 | #### Target method : 74 | ```objective-c 75 | -(NSDictionary *) handleMSG:(NSString *)msgId userInfo:(NSDictionary *)userInfo { 76 | 77 | if ([(NSString *)userInfo[@"action"] isEqual:@"getUDID"]) 78 | return @{@"UDID":[UIDevice.currentDevice sf_udidString] ?: @"No udid"}; 79 | 80 | return @{}; 81 | } 82 | 83 | ``` 84 | 85 | ## ~ App : 86 | ```objective-c 87 | #define _serviceName @"com.cm90.crossOverIPC" 88 | 89 | CrossOverIPC *crossOver = [objc_getClass("CrossOverIPC") centerNamed:_serviceName type:SERVICE_TYPE_SENDER]; 90 | NSDictionary *dict = [crossOver sendMessageAndReceiveReplyName:@"UDID_Getter" userInfo:@{@"action":@"getUDID"}]; 91 | CLog(@"[+] UDID : %@",dict[@"UDID"]); 92 | ``` 93 | 94 | 95 | 96 | ## Important : 97 | * `ServiceName` must be the same in [Poster] and [Client] . 98 | 99 | 100 | 101 | 102 | ## License : 103 | 104 | This tool is licensed under the MIT License. 105 | Feel free to use, modify, and distribute this software in accordance with the MIT License terms. I hope this tool brings value to your projects and endeavors. For more details, please refer to the [MIT License documentation](https://opensource.org/licenses/MIT). 106 | 107 | © 2024 @CrazyMind90. All rights reserved. 108 | 109 | 110 | -------------------------------------------------------------------------------- /Test_Tweaks/CrossOverIPC_Apps.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.bestli.cpumax", 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /Test_Tweaks/CrossOverIPC_Apps.xm: -------------------------------------------------------------------------------- 1 | // Created by CrazyMind90 ~ 2024. 2 | 3 | 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #include 11 | 12 | 13 | 14 | #pragma GCC diagnostic ignored "-Wunused-variable" 15 | #pragma GCC diagnostic ignored "-Wprotocol" 16 | #pragma GCC diagnostic ignored "-Wmacro-redefined" 17 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 18 | #pragma GCC diagnostic ignored "-Wincomplete-implementation" 19 | #pragma GCC diagnostic ignored "-Wunknown-pragmas" 20 | #pragma GCC diagnostic ignored "-Wformat" 21 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" 22 | #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" 23 | #pragma GCC diagnostic ignored "-Wunused-value" 24 | #pragma GCC diagnostic ignored "-Wunused-function" 25 | #pragma GCC diagnostic ignored "-Wunused-variable" 26 | 27 | 28 | 29 | 30 | #define rgbValue 31 | #define UIColorFromHEX(rgbValue) [UIColor \ 32 | colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 33 | green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ 34 | blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 35 | 36 | 37 | static UIViewController *_topMostController(UIViewController *cont) { 38 | UIViewController *topController = cont; 39 | while (topController.presentedViewController) { 40 | topController = topController.presentedViewController; 41 | } 42 | if ([topController isKindOfClass:[UINavigationController class]]) { 43 | UIViewController *visible = ((UINavigationController *)topController).visibleViewController; 44 | if (visible) { 45 | topController = visible; 46 | } 47 | } 48 | return (topController != cont ? topController : nil); 49 | } 50 | static UIViewController *topMostController() { 51 | UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; 52 | UIViewController *next = nil; 53 | while ((next = _topMostController(topController)) != nil) { 54 | topController = next; 55 | } 56 | return topController; 57 | } 58 | 59 | 60 | 61 | static void Alert(float Timer,id Message, ...) { 62 | 63 | va_list args; 64 | va_start(args, Message); 65 | NSString *Formated = [[NSString alloc] initWithFormat:Message arguments:args]; 66 | va_end(args); 67 | 68 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Timer * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 69 | 70 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Hola" message:Formated preferredStyle:UIAlertControllerStyleAlert]; 71 | 72 | UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 73 | }]; 74 | 75 | [alert addAction:action]; 76 | 77 | [topMostController() presentViewController:alert animated:true completion:nil]; 78 | 79 | }); 80 | 81 | 82 | } 83 | 84 | 85 | 86 | 87 | 88 | // inAppTweak.xm 89 | 90 | #import 91 | #include 92 | #import "CrossOverIPC.h" 93 | 94 | #define CLog(format, ...) NSLog(@"CM90~[inApp] : " format, ##__VA_ARGS__) 95 | 96 | 97 | @interface SBServer : NSObject 98 | 99 | -(void) handleMSG:(NSString *)msgId userInfo:(NSDictionary *)userInfo; 100 | 101 | @end 102 | 103 | @implementation SBServer 104 | 105 | -(id)init { 106 | 107 | if ((self = [super init])){ 108 | 109 | CLog(@"[+] In_App "); 110 | 111 | #define _serviceName @"com.cm90.crossOverIPC" 112 | 113 | CrossOverIPC *crossOver = [objc_getClass("CrossOverIPC") centerNamed:_serviceName type:SERVICE_TYPE_SENDER]; 114 | 115 | CLog(@"[+] Sending to SB ..."); 116 | 117 | [crossOver sendMessageName:@"111" userInfo:@{@"key_111":@"value_111"}]; 118 | [crossOver sendMessageName:@"222" userInfo:@{@"key_222":@"value222"}]; 119 | 120 | NSDictionary *dict = [crossOver sendMessageAndReceiveReplyName:@"UDID_Getter" userInfo:@{@"action":@"getUDID"}]; 121 | CLog(@"[+] UDID : %@",dict[@"UDID"]); 122 | 123 | } 124 | return self; 125 | } 126 | 127 | 128 | 129 | -(void) handleMSG:(NSString *)msgId userInfo:(NSDictionary *)userInfo { 130 | 131 | CLog(@"[+] handleMSG:userInfo: %@",userInfo); 132 | // Alert(1,@"Got UDID : %@",userInfo[@"UDID"]); 133 | } 134 | 135 | 136 | 137 | @end 138 | 139 | 140 | 141 | 142 | %ctor 143 | { 144 | [SBServer new]; 145 | } -------------------------------------------------------------------------------- /Test_Tweaks/CrossOverIPC_SB.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.springboard" 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /Test_Tweaks/CrossOverIPC_SB.xm: -------------------------------------------------------------------------------- 1 | // Created by CrazyMind90 ~ 2024. 2 | 3 | 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #include 11 | 12 | 13 | // %config(generator=internal) 14 | 15 | #pragma GCC diagnostic ignored "-Wunused-variable" 16 | #pragma GCC diagnostic ignored "-Wprotocol" 17 | #pragma GCC diagnostic ignored "-Wmacro-redefined" 18 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 19 | #pragma GCC diagnostic ignored "-Wincomplete-implementation" 20 | #pragma GCC diagnostic ignored "-Wunknown-pragmas" 21 | #pragma GCC diagnostic ignored "-Wformat" 22 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" 23 | #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" 24 | #pragma GCC diagnostic ignored "-Wunused-value" 25 | #pragma GCC diagnostic ignored "-Wunused-function" 26 | #pragma GCC diagnostic ignored "-Wunused-variable" 27 | 28 | 29 | 30 | #define rgbValue 31 | #define UIColorFromHEX(rgbValue) [UIColor \ 32 | colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 33 | green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ 34 | blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 35 | 36 | 37 | static UIViewController *_topMostController(UIViewController *cont) { 38 | UIViewController *topController = cont; 39 | while (topController.presentedViewController) { 40 | topController = topController.presentedViewController; 41 | } 42 | if ([topController isKindOfClass:[UINavigationController class]]) { 43 | UIViewController *visible = ((UINavigationController *)topController).visibleViewController; 44 | if (visible) { 45 | topController = visible; 46 | } 47 | } 48 | return (topController != cont ? topController : nil); 49 | } 50 | static UIViewController *topMostController() { 51 | UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; 52 | UIViewController *next = nil; 53 | while ((next = _topMostController(topController)) != nil) { 54 | topController = next; 55 | } 56 | return topController; 57 | } 58 | 59 | 60 | 61 | static void Alert(float Timer,id Message, ...) { 62 | 63 | va_list args; 64 | va_start(args, Message); 65 | NSString *Formated = [[NSString alloc] initWithFormat:Message arguments:args]; 66 | va_end(args); 67 | 68 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Timer * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 69 | 70 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Hola" message:Formated preferredStyle:UIAlertControllerStyleAlert]; 71 | 72 | UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 73 | }]; 74 | 75 | [alert addAction:action]; 76 | 77 | [topMostController() presentViewController:alert animated:true completion:nil]; 78 | 79 | }); 80 | 81 | 82 | } 83 | 84 | 85 | 86 | @import CoreFoundation; 87 | @import Foundation; 88 | 89 | 90 | #include 91 | #include 92 | #include 93 | #import 94 | #import "CrossOverIPC.h" 95 | 96 | 97 | 98 | #define CLog(format, ...) NSLog(@"CM90~[SpringBoard] : " format, ##__VA_ARGS__) 99 | 100 | 101 | @interface UIDevice (_xpc) 102 | - (NSString *) sf_udidString; 103 | @end 104 | 105 | @interface SBServer : NSObject 106 | 107 | -(NSDictionary *) handleMSG:(NSString *)msgId userInfo:(NSDictionary *)userInfo; 108 | @end 109 | 110 | @implementation SBServer 111 | 112 | 113 | static NSDictionary *ret_dict = nil; 114 | -(id)init { 115 | 116 | if ((self = [super init])){ 117 | 118 | CLog(@"[+] SB_ctor "); 119 | 120 | 121 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 122 | 123 | 124 | #define _serviceName @"com.cm90.crossOverIPC" 125 | 126 | CrossOverIPC *crossOver = [objc_getClass("CrossOverIPC") centerNamed:_serviceName type:SERVICE_TYPE_LISTENER]; 127 | 128 | [crossOver registerForMessageName:@"UDID_Getter" target:self selector:@selector(handleMSG:userInfo:)]; 129 | [crossOver registerForMessageName:@"111" target:self selector:@selector(handleMSG_111:userInfo:)]; 130 | [crossOver registerForMessageName:@"222" target:self selector:@selector(handleMSG_222:userInfo:)]; 131 | 132 | 133 | }); 134 | 135 | } 136 | 137 | return self; 138 | } 139 | 140 | -(void) handleMSG_111:(NSString *)msgName userInfo:(NSDictionary *)userInfo { 141 | CLog(@"[+] handleMSG_111: %@ | userInfo: %@",msgName,userInfo); 142 | } 143 | 144 | -(void) handleMSG_222:(NSString *)msgName userInfo:(NSDictionary *)userInfo { 145 | 146 | CLog(@"[+] handleMSG_222: %@ | userInfo: %@",msgName,userInfo); 147 | } 148 | 149 | -(NSDictionary *) handleMSG:(NSString *)msgName userInfo:(NSDictionary *)userInfo { 150 | 151 | CLog(@"[+] handleMSG: %@ | userInfo: %@",msgName,userInfo); 152 | if ([(NSString *)userInfo[@"action"] isEqual:@"getUDID"]) 153 | return @{@"UDID":[UIDevice.currentDevice sf_udidString] ?: @"No udid"}; 154 | 155 | return @{@"no":@"null"}; 156 | } 157 | 158 | 159 | 160 | @end 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | %ctor 176 | { 177 | [SBServer new]; 178 | } 179 | -------------------------------------------------------------------------------- /Test_Tweaks/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | 3 | export TARGET = iphone:14.5 4 | export SDKVERSION = 14.5 5 | 6 | export THEOS_PACKAGE_SCHEME = rootless 7 | 8 | export iP = 192.168.1.102 9 | export Port = 22 10 | export Pass = alpine 11 | export Bundle = com.apple.springboard 12 | 13 | 14 | export DEBUG = 1 15 | 16 | 17 | include $(THEOS)/makefiles/common.mk 18 | 19 | export TWEAK_NAME = CrossOverIPC_Apps CrossOverIPC_SB 20 | 21 | CrossOverIPC_Apps_FILES = CrossOverIPC_Apps.xm 22 | CrossOverIPC_Apps_CFLAGS = -std=c++11 23 | CrossOverIPC_Apps_LDFLAGS += -framework CoreServices 24 | CrossOverIPC_Apps_CODESIGN_FLAGS = -S../ent.plist 25 | 26 | 27 | CrossOverIPC_SB_FILES = CrossOverIPC_SB.xm 28 | CrossOverIPC_SB_CFLAGS = -std=c++11 29 | CrossOverIPC_SB_LDFLAGS += -framework CoreServices 30 | CrossOverIPC_SB_CODESIGN_FLAGS = -S../ent.plist 31 | 32 | ADDITIONAL_CFLAGS += -DTHEOS_LEAN_AND_MEAN -Wno-shorten-64-to-32 33 | 34 | 35 | include $(THEOS_MAKE_PATH)/tweak.mk 36 | 37 | 38 | before-package:: 39 | $(ECHO_NOTHING) chmod 755 $(CURDIR)/.theos/_/DEBIAN/* $(ECHO_END) 40 | $(ECHO_NOTHING) chmod 755 $(CURDIR)/.theos/_/DEBIAN $(ECHO_END) 41 | 42 | 43 | install6:: 44 | install6.exec -------------------------------------------------------------------------------- /Test_Tweaks/control: -------------------------------------------------------------------------------- 1 | Package: cm90.crossoveripctest 2 | Name: CrossOverIPC_Test 3 | Depends: mobilesubstrate, com.opa334.libsandy, ldid 4 | Version: 1.1 5 | Architecture: iphoneos-arm64 6 | Description: A cross-process communication tool for sending and receiving messages on iOS 15 & 16 for rootless JBs 7 | Maintainer: @CrazyMind90 8 | Author: @CrazyMind90 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /Test_Tweaks/layout/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | 5 | echo "Signing ..." 6 | ldid -s /var/jb/usr/local/libexec/xpcToolStrapd /var/jb/Library/MobileSubstrate/DynamicLibraries/CrossOverIPC_Apps.dylib 7 | ldid -s /var/jb/usr/local/libexec/xpcToolStrapd /var/jb/Library/MobileSubstrate/DynamicLibraries/CrossOverIPC_SB.dylib -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: cm90.crossoveripc 2 | Name: CrossOverIPC 3 | Depends: mobilesubstrate 4 | Version: 1.1 5 | Architecture: iphoneos-arm64 6 | Description: A cross-process communication tool for sending and receiving messages on iOS 15 & 16 for rootless JBs 7 | Maintainer: @CrazyMind90 8 | Author: @CrazyMind90 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /ent.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.container-required 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /layout/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | echo "Signing ..." 5 | ldid -s /var/jb/usr/lib/libCrossOverIPC.dylib /var/jb/usr/lib/libCrossOverIPC.dylib 6 | ldid -s /var/jb/usr/lib/libCrossOverIPC.dylib /var/jb/Library/MobileSubstrate/DynamicLibraries/0000CrossOverIPC.dylib 7 | echo "Done!" 8 | exit 0 -------------------------------------------------------------------------------- /libCrossOverIPC.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | #import "PlistManager.h" 8 | 9 | 10 | #pragma GCC diagnostic ignored "-Wunused-function" 11 | #pragma GCC diagnostic ignored "-Wobjc-property-no-attribute" 12 | 13 | 14 | #define CLogLib(format, ...) NSLog(@"CM90~[CrossOverIPC] : " format, ##__VA_ARGS__) 15 | 16 | 17 | extern "C" CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void); 18 | 19 | 20 | static NSString *SWF(id Value, ...) { 21 | va_list args; 22 | va_start(args, Value); 23 | NSString *Formated = [[NSString alloc] initWithFormat:Value arguments:args]; 24 | va_end(args); 25 | return Formated; 26 | } 27 | 28 | 29 | static CFMutableDictionaryRef convertNSDictToCFDict(NSDictionary *nsDictionary) { 30 | 31 | CFMutableDictionaryRef cfDictionary = CFDictionaryCreateMutable( 32 | kCFAllocatorDefault, 33 | [nsDictionary count], 34 | &kCFTypeDictionaryKeyCallBacks, 35 | &kCFTypeDictionaryValueCallBacks 36 | ); 37 | 38 | for (id key in nsDictionary) { 39 | CFDictionarySetValue(cfDictionary, (__bridge const void *)(key), (__bridge const void *)(nsDictionary[key])); 40 | } 41 | 42 | return cfDictionary; 43 | } -------------------------------------------------------------------------------- /libCrossOverIPC/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64e arm64 2 | 3 | THEOS_PACKAGE_SCHEME=rootless 4 | 5 | export SDKVERSION = 14.5 6 | 7 | include $(THEOS)/makefiles/common.mk 8 | 9 | export LIBRARY_NAME = libCrossOverIPC 10 | 11 | libCrossOverIPC_FILES = libCrossOverIPC.mm ../PlistManager.m 12 | libCrossOverIPC_CFLAGS = -Wno-objc-designated-initializers 13 | libCrossOverIPC_CODESIGN_FLAGS = -S../ent.plist 14 | libCrossOverIPC_INSTALL_PATH = /usr/lib 15 | libCrossOverIPC_CFLAGS += -DXINA_SUPPORT 16 | 17 | include $(THEOS_MAKE_PATH)/library.mk 18 | 19 | include $(THEOS_MAKE_PATH)/aggregate.mk 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /libCrossOverIPC/libCrossOverIPC.mm: -------------------------------------------------------------------------------- 1 | // Created by CrazyMind90 ~ 2024. 2 | 3 | 4 | #import "../CrossOverIPC.h" 5 | #import "../libCrossOverIPC.h" 6 | #import 7 | #include 8 | 9 | 10 | #pragma GCC diagnostic ignored "-Wunused-variable" 11 | #pragma GCC diagnostic ignored "-Wprotocol" 12 | #pragma GCC diagnostic ignored "-Wmacro-redefined" 13 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 14 | #pragma GCC diagnostic ignored "-Wincomplete-implementation" 15 | #pragma GCC diagnostic ignored "-Wunknown-pragmas" 16 | #pragma GCC diagnostic ignored "-Wformat" 17 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" 18 | #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" 19 | #pragma GCC diagnostic ignored "-Wunused-value" 20 | #pragma GCC diagnostic ignored "-Wunused-function" 21 | #pragma GCC diagnostic ignored "-Wignored-attributes" 22 | #pragma GCC diagnostic ignored "-Wunused-result" 23 | 24 | 25 | 26 | #define CLog(format, ...) NSLog(@"CM90~[libCrossOverIPC] : " format, ##__VA_ARGS__) 27 | 28 | 29 | @interface CrossOverIPC (CFImp) 30 | 31 | @property (nonatomic, strong) NSMutableDictionary *registeredTargets; 32 | @property (nonatomic, strong) NSString *serviceName; 33 | @property (nonatomic, strong) NSString *origServiceName; 34 | @property (nonatomic, strong) NSString *senderServiceName; 35 | @property (nonatomic, strong) NSString *clientServiceName; 36 | 37 | + (instancetype) shared; 38 | 39 | @end 40 | 41 | @implementation CrossOverIPC 42 | 43 | 44 | 45 | #pragma --------------------------------------------- Main event ---------------------------------------------------- 46 | 47 | static void distributedCenterEvent(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 48 | 49 | CrossOverIPC.shared.origServiceName = [CrossOverIPC.shared purifySenderName:[CrossOverIPC.shared purifyClientName:(__bridge NSString *)name]]; 50 | CrossOverIPC.shared.senderServiceName = SWF(@"%@-CROSS_OVER_SENDER",[CrossOverIPC.shared purifyClientName:(__bridge NSString *)name]); 51 | CrossOverIPC.shared.clientServiceName = (__bridge NSString *)name; 52 | CrossOverIPC.shared.serviceName = CrossOverIPC.shared.clientServiceName; 53 | 54 | if ([CrossOverIPC.shared isSender]) { 55 | #pragma mark - Sender 56 | [CrossOverIPC.shared senderHandler:(__bridge NSDictionary *)userInfo]; 57 | } else { 58 | #pragma mark - Client 59 | [CrossOverIPC.shared clientHandler:(__bridge NSDictionary *)userInfo]; 60 | } 61 | } 62 | 63 | 64 | #pragma --------------------------------------------- Allocates ---------------------------------------------------- 65 | 66 | +(instancetype) shared { 67 | static dispatch_once_t once = 0; 68 | __strong static CrossOverIPC *shared = nil; 69 | dispatch_once(&once, ^{ 70 | shared = [[self alloc] init]; 71 | shared.registeredTargets = NSMutableDictionary.alloc.init; 72 | }); 73 | return shared; 74 | } 75 | 76 | 77 | -(instancetype) initWithServiceNamed:(NSString *)serviceName type:(CrossOverIPCServiceType)type { 78 | 79 | self.origServiceName = serviceName; 80 | self.senderServiceName = SWF(@"%@-CROSS_OVER_SENDER",serviceName); 81 | self.clientServiceName = SWF(@"%@-CROSS_OVER_CLIENT",serviceName); 82 | 83 | switch(type){ 84 | case SERVICE_TYPE_SENDER: 85 | serviceName = self.senderServiceName; 86 | break; 87 | case SERVICE_TYPE_LISTENER: 88 | serviceName = self.clientServiceName; 89 | break; 90 | } 91 | 92 | self.serviceName = serviceName; 93 | 94 | CFNotificationCenterAddObserver( 95 | CFNotificationCenterGetDistributedCenter(), 96 | (__bridge const void *)self, 97 | distributedCenterEvent, 98 | (CFStringRef)serviceName, 99 | NULL, 100 | CFNotificationSuspensionBehaviorDeliverImmediately); 101 | 102 | return self; 103 | } 104 | 105 | 106 | + (instancetype) centerNamed:(NSString *)serviceName type:(CrossOverIPCServiceType)type { 107 | return [CrossOverIPC.shared initWithServiceNamed:serviceName type:type]; 108 | } 109 | 110 | 111 | #pragma --------------------------------------------- Senders ---------------------------------------------------- 112 | 113 | 114 | -(void) sendMessageName:(NSString *)msgName userInfo:(NSDictionary *)userInfo { 115 | 116 | if (!userInfo) 117 | userInfo = @{}; 118 | 119 | NSString *serviceName = [self isSender] ? self.clientServiceName : self.senderServiceName; 120 | 121 | CFMutableDictionaryRef dictionary = convertNSDictToCFDict(@{msgName:userInfo, 122 | @"msgName":msgName, 123 | @"isWithReply":@"NO", 124 | @"clientServiceName":self.clientServiceName, 125 | }); 126 | CFNotificationCenterPostNotificationWithOptions( 127 | CFNotificationCenterGetDistributedCenter(), 128 | (CFStringRef)self.clientServiceName, 129 | NULL, 130 | dictionary, 131 | kCFNotificationPostToAllSessions | kCFNotificationDeliverImmediately); 132 | 133 | CFRelease(dictionary); 134 | 135 | } 136 | 137 | 138 | -(NSDictionary *) sendMessageAndReceiveReplyName:(NSString *)msgName userInfo:(NSDictionary *)userInfo { 139 | 140 | if (!userInfo) 141 | userInfo = @{}; 142 | 143 | 144 | NSString *serviceName = [self isSender] ? self.clientServiceName : self.senderServiceName; 145 | 146 | CFMutableDictionaryRef dictionary = convertNSDictToCFDict(@{msgName:userInfo, 147 | @"isWithReply":@"YES", 148 | @"msgName":msgName, 149 | @"clientServiceName":self.clientServiceName, 150 | }); 151 | CFNotificationCenterPostNotificationWithOptions( 152 | CFNotificationCenterGetDistributedCenter(), 153 | (CFStringRef)self.clientServiceName, 154 | NULL, 155 | dictionary, 156 | kCFNotificationPostToAllSessions | kCFNotificationDeliverImmediately); 157 | 158 | CFRelease(dictionary); 159 | 160 | NSString *dictKey = SWF(@"%@~%@",self.origServiceName,msgName); 161 | NSDate *startTime = NSDate.date; 162 | 163 | do { 164 | if ([PlistManager.shared objectForKey:dictKey]) { 165 | break; 166 | } 167 | if ([NSDate.date timeIntervalSinceDate:startTime] >= 0.5) { 168 | break; 169 | } 170 | } while (![PlistManager.shared objectForKey:dictKey]); 171 | 172 | NSDictionary *ret = [PlistManager.shared objectForKey:dictKey]; 173 | [PlistManager.shared removeObjectForKey:dictKey]; 174 | 175 | return ret; 176 | } 177 | 178 | 179 | #pragma --------------------------------------------- Handlers ---------------------------------------------------- 180 | 181 | 182 | 183 | - (void) senderHandler:(NSDictionary *)userInfo { 184 | 185 | if (userInfo) { 186 | 187 | } else { 188 | // CLog(@"~[Sender]~ No userInfo received."); 189 | } 190 | } 191 | 192 | - (void) clientHandler:(NSDictionary *)userInfo { 193 | 194 | if (userInfo) { 195 | 196 | NSDictionary *infoDict = (__bridge NSDictionary *)userInfo; 197 | 198 | NSString *msgName = infoDict[@"msgName"]; 199 | NSString *fullKey = SWF(@"%@~%@",self.clientServiceName,msgName); 200 | 201 | if ([self isValidTargetForServiceName:fullKey]) { 202 | 203 | BOOL isWithReply = [infoDict[@"isWithReply"] isEqual:@"YES"]; 204 | if (isWithReply) { 205 | NSDictionary *dict = [self callServiceNameTarget:fullKey userInfo:infoDict[msgName]]; 206 | if (!dict) 207 | dict = @{}; 208 | 209 | [PlistManager.shared setObject:dict forKey:SWF(@"%@~%@",self.origServiceName,msgName)]; 210 | 211 | } else { 212 | [self callServiceNameTarget:fullKey userInfo:infoDict[msgName]]; 213 | } 214 | } else { 215 | } 216 | 217 | } else { 218 | // CLog(@"~[Client]~ No userInfo received."); 219 | } 220 | } 221 | 222 | 223 | 224 | #pragma --------------------------------------------- Extras ---------------------------------------------------- 225 | 226 | 227 | -(void) registerForMessageName:(NSString *)msgName target:(id)target selector:(SEL)sel { 228 | [self.registeredTargets setObject:@[target,NSStringFromSelector(sel)] forKey:SWF(@"%@~%@",self.serviceName,msgName)]; 229 | } 230 | 231 | -(NSDictionary *) callServiceNameTarget:(NSString *)serviceKey userInfo:(NSDictionary *)dict { 232 | id target = self.registeredTargets[serviceKey][0]; 233 | SEL selector = NSSelectorFromString(self.registeredTargets[serviceKey][1]); 234 | return [target performSelector:selector withObject:[self purifyClientName:serviceKey] withObject:dict]; 235 | } 236 | 237 | -(BOOL) isValidTargetForServiceName:(NSString *)serviceKey { 238 | if ([self.registeredTargets objectForKey:serviceKey]) return YES; 239 | return NO; 240 | } 241 | 242 | - (BOOL) isSender { 243 | return [self.serviceName containsString:@"-CROSS_OVER_SENDER"]; 244 | } 245 | 246 | - (NSString *) purifySenderName:(NSString *)senderName { 247 | return [senderName stringByReplacingOccurrencesOfString:@"-CROSS_OVER_SENDER" withString:@""]; 248 | } 249 | 250 | - (NSString *) purifyClientName:(NSString *)clientName { 251 | return [clientName stringByReplacingOccurrencesOfString:@"-CROSS_OVER_CLIENT" withString:@""]; 252 | } 253 | 254 | 255 | 256 | #pragma --------------------------------------------- Properties ---------------------------------------------------- 257 | 258 | 259 | - (NSString *)senderServiceName { 260 | return objc_getAssociatedObject(self, @selector(senderServiceName)); 261 | } 262 | 263 | - (void)setSenderServiceName:(NSString *)senderServiceName { 264 | objc_setAssociatedObject(self, @selector(senderServiceName), senderServiceName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 265 | } 266 | 267 | - (NSString *)clientServiceName { 268 | return objc_getAssociatedObject(self, @selector(clientServiceName)); 269 | } 270 | 271 | - (void)setClientServiceName:(NSString *)clientServiceName { 272 | objc_setAssociatedObject(self, @selector(clientServiceName), clientServiceName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 273 | } 274 | 275 | - (NSString *)origServiceName { 276 | return objc_getAssociatedObject(self, @selector(origServiceName)); 277 | } 278 | 279 | - (void)setOrigServiceName:(NSString *)origServiceName { 280 | objc_setAssociatedObject(self, @selector(origServiceName), origServiceName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 281 | } 282 | 283 | - (NSString *)serviceName { 284 | return objc_getAssociatedObject(self, @selector(serviceName)); 285 | } 286 | 287 | - (void)setServiceName:(NSString *)serviceName { 288 | objc_setAssociatedObject(self, @selector(serviceName), serviceName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 289 | } 290 | 291 | - (NSMutableDictionary *)registeredTargets { 292 | return objc_getAssociatedObject(self, @selector(registeredTargets)); 293 | } 294 | 295 | - (void)setRegisteredTargets:(NSMutableDictionary *)registeredTargets { 296 | objc_setAssociatedObject(self, @selector(registeredTargets), registeredTargets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 297 | } 298 | 299 | @end 300 | 301 | 302 | 303 | 304 | 305 | 306 | --------------------------------------------------------------------------------