These are some of the existing methods to implement IPC on iOS

简介: These are some of the existing methods to implement IPC on iOS

前言

These are some of the existing methods to implement IPC on iOS:

image.png

  • Universal Links、URL Scheme

https://kunnan.blog.csdn.net/article/details/119773640

  • Keychain

https://blog.csdn.net/z929118967/article/details/78195794

  • UIDocumentInteractionController
  • 利用socket进行本地通信

https://blog.csdn.net/z929118967/article/details/109616038

  • Mach Ports
  • Pasteboard

iOS 逆向:Tweak的开发例子【发红包】使用tweak和lua脚本结合进行实现https://blog.csdn.net/z929118967/article/details/76914272

UIPasteboard* pasteboard = [UIPasteboard generalPasteboard]; 
 [pasteboard setString:@"A1"];
//使用tweak和lua脚本结合进行实现
//1、tweak侧的功能是hookapp的原生功能
//2、lua 是实现模拟用户点击
//3、通信通过剪切板:tweak 通过剪切板和lua脚本进行通信
//其实后面我继续研究,把lua侧的功能全部用tweak实现了。 这里分享的是一个思路。
  • AppleEvents & AppleScript
  • Distributed Objects
  • XPC

https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html

  • Notifications

http://iphonedevwiki.net/index.php/Notifications

  • libobjcipc

http://iphonedevwiki.net/index.php/Libobjcipc

  • LightMessaging

https://github.com/rpetrich/LightMessaging

Community Libraries

  • 1、RocketBootstrap:Service registration and lookup system for iOS
  • 2、OBJCIPC :High-level API for hosting services inside apps (by Alan Yip/a1anyip)
  • 3、LightMessaging:Header-only library for simple IPC

本文重点讲解RocketBootstrap的两种包装方式:CFMessagePort、CPDistributedMessagingCenter

I 、librocketbootstrap

  • RocketBootstrap4Inter_process_Communication
  • feature

1、Uses iOS7’s security model: Privileged processes can register, any process can look up 2、Works with existing mach-based IPC mechanisms 3、Similar to Apple’s bootstrap APIs: bootstrap_look_up becomes rocketbootstrap_look_up bootstrap_register becomes rocketbootstrap_register 4、Easy to use wrappers for CFMessagePort and CPDistributedMessagingCenter(todo: XPC) 5、Bring your own security model by using audit_token_to_au32 to know who’s calling 6、Requires package dependency, commonly installed on users’ devices

1.0 获取librocketbootstrap :

-Install this from Cydia 直接搜索rocketbootstrap安装即可

iPhone:/var/log root# ls -l /usr/lib/librocketbootstrap.dylib
-rwxr-xr-x 1 root wheel 221776 Feb  6  2017 /usr/lib/librocketbootstrap.dylib*
/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist
/usr/libexec/rocketd
launchctl load  /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist
launchctl unload /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist

1.1 CFMessagePort

  • registerMsgCenter 基本可以解决双向通信;例子:避免重启其他进程从sb获取源地址信息的变更。守护进行都可以注册成为服务
+ (kern_return_t)rockettest_messageport_server
{
    static CFMessagePortRef messagePort;//
    if (messagePort)
        return 0;
    messagePort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("rockettest_messageport"), messagePortCallback, NULL, NULL);//CFSTR("rockettest_messageport")即server key,
    CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, messagePort, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, (CFStringRef)UITrackingRunLoopMode);
    return rocketbootstrap_cfmessageportexposelocal(messagePort);
}
typedef CFDataRef (*CFMessagePortCallBack)(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info);
//回调的定义
static CFDataRef messagePortCallback(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info)
{
    NSLog(@"rockettest_messageport_server: received %@", data);
    return CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"bootstrap", 9);
}
  • CFMessagePort: Only supports synchronous use
#import <UIKit/UIKit.h>
#include "log.h"
#import "rocketbootstrap.h"
@implementation NSObject (rocketbootstrap)
+ (kern_return_t)rocketbootstrap_unlock:(NSString *)name
{
 return rocketbootstrap_unlock([name UTF8String]);
}
static CFDataRef messagePortCallback(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info)
{
 NSLog(@"rockettest_messageport_server: received %@", data);
 return CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"bootstrap", 9);
}
/**
registerMsgCenter 基本可以解决双向通信;
例子:避免重启其他进程从sb获取源地址信息的变更。 守护进行都可以注册成为服务
*/
+ (kern_return_t)rockettest_messageport_server
{
 static CFMessagePortRef messagePort;
 if (messagePort)
  return 0;
 messagePort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("rockettest_messageport"), messagePortCallback, NULL, NULL);
 CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, messagePort, 0);
 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, (CFStringRef)UITrackingRunLoopMode);
 return rocketbootstrap_cfmessageportexposelocal(messagePort);
}
+ (NSData *)rockettest_messageport_client
{
 CFMessagePortRef remote = rocketbootstrap_cfmessageportcreateremote(kCFAllocatorDefault, CFSTR("rockettest_messageport"));
 if (!remote)
  return nil;
 CFDataRef request = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"rocket", 6);
 CFDataRef response = NULL;
 CFMessagePortSendRequest(remote, 0, request, 10, 10, CFSTR("rocketboostrap_wait"), &response);
 CFRelease(remote);
 CFRelease(request);
 return [(NSData *)response autorelease];
}

II CPDistributedMessagingCenter

Asynchronous, if you go through the trouble

2.1 CFMessagePort Example

  • Server
static CFDataRef Callback(CFMessagePortRef port,
                          SInt32 messageID,
                          CFDataRef data,
                          void *info)
{
    // ...
}
%ctor {
    static CFMessagePortRef localPort =
        CFMessagePortCreateLocal(nil,
                                 CFSTR("com.example.app.port.server"),
                                 Callback,
                                 nil,
                                 nil);
    CFRunLoopSourceRef runLoopSource =
        CFMessagePortCreateRunLoopSource(nil, localPort, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       runLoopSource,
                       kCFRunLoopCommonModes);
    rocketbootstrap_cfmessageportexposelocal(localPort);
}
  • Client
void doStuff() {
    CFDataRef data;
    SInt32 messageID = 0x1111; // Arbitrary
    CFTimeInterval timeout = 10.0;
    CFMessagePortRef remotePort =
        rocketbootstrap_cfmessageportcreateremote(nil,
                                  CFSTR("com.example.app.port.client"));
    SInt32 status =
        CFMessagePortSendRequest(remotePort,
                                 messageID,
                                 data,
                                 timeout,
                                 timeout,
                                 NULL,
                                 NULL);
    if (status == kCFMessagePortSuccess) {
        // ...
    }
}

2.2 CPDistributedMessagingCenter的例子

目前发现这种方式只能在SpringBoard   注册为服务端,处理消息,;

进程间其实是单向通信;

#TweakDemo.xm  SpringBoard  接受消息
#import "rocketbootstrap.h"
#define kXPCCenterNameKey  @"kXPCCenterNameKey_83641"
%hook SpringBoard
- (void)applicationDidFinishLaunching:(id)application {
   %orig;
   CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:kXPCCenterNameKey];
   rocketbootstrap_distributedmessagingcenter_apply(c);
   [c runServerOnCurrentThread];
   [c registerForMessageName:@"myMessageName" target:self selector:@selector(handleMessage:withUserInfo:)];
   NSLog(@"注册监听 start");
}
%new
- (void)handleMessage:(NSString *)name withUserInfo:(NSDictionary *)userInfo {
   NSLog(@"handleMessage withUserInfo:%@",userInfo);
   //TODO:something
}
%end
//在需要发送的地方(沙盒 app ),如此这般的写: 
%hook SomeClass
-(void)someMethod{
   %orig;
    NSMutableDictionary *userInfo = [@{} mutableCopy];
    [userInfo setObject:@"123" forKey:@"arg001"];
    [userInfo setObject:@"456" forKey:@"arg002"];
    NSLog(@"发送: %@=%@",kXPCCenterNameKey,userInfo);
    CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:kXPCCenterNameKey];
    rocketbootstrap_distributedmessagingcenter_apply(c);
    [c sendMessageName:@"myMessageName" userInfo:userInfo];
}
%end

III、  UIPasteboard/NSPasteboard

OpenUDID的使用例子

#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#import <UIKit/UIPasteboard.h>
#import <UIKit/UIKit.h>
#else
#import <AppKit/NSPasteboard.h>
#endif
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
        UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:slotPBid create:NO];
#else
        NSPasteboard* slotPB = [NSPasteboard pasteboardWithName:slotPBid];
#endif
  • 利用 pasteboardWithName 方法进行数据存储达到通信的目的
/**
 应用级别的,数据在属于自己的应用内部共享;
 (默认情况下是不会把数据写进沙盒的,也就是说(复制、剪切)粘贴内容会因为应用的退出而销毁掉,我们可以设置相关属性 persistent值为 YES让其进行数据的持久化存储起来)
 Ps:例如 persistent 是否进行数据持久化 还有 changeCount 改变次数(剪切板)系统重启方才重新计数
 */
- (NSObject *)model{
    if (_model == nil) {
        NSString *contentUserID =@"";
        UIPasteboard *pasteboardUserID = [UIPasteboard pasteboardWithName:KNpasteboardWithNameKeyUserID create:NO];
        if (pasteboardUserID){
            contentUserID = pasteboardUserID.string;////获取内容
        }
        _model = [[NSObject alloc]init];
//        _model.UserId =contentUserID;
    }
    return _model;
}

IV、LightMessaging

  • feature

1、Mid-level API, 2、Message-oriented 3、Zero copy, for certain message types 4、No additional cost over standard mach calls 5、Easy integration with RocketBootstrap 6、No package dependencies

  • using

1、Start services with LMStartService 2、Send messages with LMConnectionSendTwoWay (and friends) 3、Send replies with LMSendReply (and friends) 4、Bring your own security checks still :Community developers, your input on API please!

V 、IPC

allows processes to send each other messages and data

更多内容请看原文和关注公众号:iOS逆向

VI、libobjcipc

  • feature

• High level API provides service lookup and IPC, easy to use • Background-launches and fakes app lifecycle for you • Message-oriented • Mostly asynchronous • “Open” security model • Requires separate package dependency, but very small • Simple Objective-C APIs: Register using --registerIncomingMessageFromAppHandlerForMessageName:handler: Send using -- sendMessageToAppWithIdentifier:messageName:dictionary:replyHandler:

• Similar patterns for App to SpringBoard

VII XPC

XPC can be accessed through either the libxpc C API, or the NSXPCConnection Objective-C API.

  • feature

1、High level API, easy to use :One of Apple’s many wrappers for Mach messages;2、Message-oriented 3、Public API on OS X only 4、Asynchronous always, no synchronous versions 5、Service lookup is restricted on iOS 7+

VIII  Tweaks on a multi-process iOS

  • Inter-Process Communication
1、Mechanisms provided by the kernel to facilitate coordinated sharing of data and commands between processes
2、Used heavily in recent versions of iOS and OS X to implement system frameworks and APIs
  • Standard Techniques
1、Save to temp files:High level APIs, easy to use
2、Unix Domain Sockets:Low level API  ,Stream oriented, requires basic parsing to reconstruct
messages
  • Other standard techniques
• Shared Memory
• Signals
• Named pipes
• Network sockets
  • Apple/iOS-specific Techniques
1、Darwin Notifications:No data, only a simple “go” message,Any process can post or observe ,Always asynchronous
2、Mach Ports :seriously low level 
3、CPDistributedNotificationCenter:Private API, does change between iOS versions
4、CFMessagePort:Public API,Only supports synchronous use ,Service lookup is restricted on iOS 6+
5、XPC :High level API, easy to use �,One of Apple’s many wrappers for Mach messages ;
  • Creative Techniques
1、Relax existing service permissions
2、Repurpose existing iOS services’ IPC channels:Service internals are frequently rewritten in new iOS versions
3、Delegate to someone else
  • Libraries that use IPC under the hood
1、http://iphonedevwiki.net/index.php/AppList
2、http://iphonedevwiki.net/index.php/Flipswitch
3、http://iphonedevwiki.net/index.php/Libactivator
4、https://github.com/r-plus/libcanopenurl
  • Community Libraries to Help
1、RocketBootstrap:Service registration and lookup system for iOS
  • Be aware of potential deadlocks
1、 SpringBoard will block on backboardd—don’t call from backboardd to SpringBoard! 
2、Communicate with these processes using one-way IPC, asynchronous IPC, or two-way IPC with timeouts 
3、Avoid the pitfall of accidentally sending blocking API calls to one’s own process
4、SpringBoard is usually a good choice for coordinator as it often has much work to do anyway
5、Batch all of the operations for a single user action into one IPC call, if possible 
6、Filter to only the data required before sending

IV、 see also

目录
相关文章
|
1月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
92 3
|
3月前
|
存储 iOS开发
iOS 开发,如何进行应用的本地化(Localization)?
iOS 开发,如何进行应用的本地化(Localization)?
122 2
|
3月前
|
存储 数据建模 数据库
IOS开发数据存储:什么是 UserDefaults?有哪些替代方案?
IOS开发数据存储:什么是 UserDefaults?有哪些替代方案?
40 0
|
3月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
93 2
|
3月前
|
API 开发工具 iOS开发
iOS 开发高效率工具包:10 大必备工具
iOS 开发高效率工具包:10 大必备工具
48 1
|
3月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
54 1
|
10天前
|
API 定位技术 iOS开发
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
【4月更文挑战第18天】**Cocoa Touch** 是iOS和Mac OS X应用的核心框架,包含面向对象库、运行时系统和触摸优化工具。它提供Mac验证的开发模式,强调触控接口和性能,涵盖3D图形、音频、网络及设备访问API,如相机和GPS。是构建高效iOS应用的基础,对开发者至关重要。
12 0
|
25天前
|
开发工具 Swift iOS开发
利用SwiftUI构建动态用户界面:iOS开发新范式
【4月更文挑战第3天】 随着苹果不断推进其软件开发工具的边界,SwiftUI作为一种新兴的编程框架,已经逐渐成为iOS开发者的新宠。不同于传统的UIKit,SwiftUI通过声明式语法和强大的功能组合,为创建动态且响应式的用户界面提供了一种更加简洁高效的方式。本文将深入探讨如何利用SwiftUI技术构建具有高度自定义能力和响应性的用户界面,并展示其在现代iOS应用开发中的优势和潜力。
|
2月前
|
监控 API Swift
用Swift开发iOS平台上的上网行为管理监控软件
在当今数字化时代,随着智能手机的普及,人们对于网络的依赖日益增加。然而,对于一些特定场景,如家庭、学校或者企业,对于iOS设备上的网络行为进行管理和监控显得尤为重要。为了满足这一需求,我们可以利用Swift语言开发一款iOS平台上的上网行为管理监控软件。
202 2
|
3月前
|
数据可视化 iOS开发
iOS 开发,什么是 Interface Builder(IB)?如何使用 IB 构建用户界面?
iOS 开发,什么是 Interface Builder(IB)?如何使用 IB 构建用户界面?
40 4