ios – 黑客入侵MFMessageComposeViewController

我知道在真正的应用程序中不允许这样做,有利于用户的隐私和安全.但是出于纯粹的学术目的,我试图发送消息而不像这样呈现MessageComposer UI.
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];

if([MFMessageComposeViewController canSendText]) {
    picker.recipients = [NSArray arrayWithObject:@"1234"];
    picker.body = @"Hello";
    [picker performSelector:@selector(smsComposeControllerSendStarted:) withObject:[UIButton buttonWithType:UIButtonTypeCustom]];
}

结果没有任何结果.甚至在控制台上都没有失败异常.我都没有在短信应用上看到消息.我发送邮件的人也没有得到它.

可以在这里找到iMars和MFMessageComposeViewController方法的列表.

https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/MessageUI.framework/MFMessageComposeViewController.h

我写了一个快速代码来验证这些是否是MFMessageComposeViewController中实际存在的项目.

uint varCount = 0;
Class cls= [MFMessageComposeViewController class];
Ivar *vars =  class_copyIvarList(cls,&varCount);

for (uint i = 0; i < varCount; i++) {
   Ivar var = vars[i];
   const char* name = ivar_getName(var);
   const char* typeEncoding = ivar_getTypeEncoding(var);
   printf("iVar%i------------> %s\n",i+1,name);
}    
free(vars);

Method *imps = class_copyMethodList(cls,&varCount);
for (uint i = 0; i < varCount; i++) {
    SEL sel = method_getName(imps[i]);        
    printf("Method%i------------> %s\n",[(NsstringFromSelector(sel)) UTF8String]);
}

它产生以下输出

iVar1------------> _messageComposeDelegate
iVar2------------> _recipients
iVar3------------> _body
iVar4------------> _subject
iVar5------------> _mutableAttachmentURLs
iVar6------------> _currentAttachedVideoCount
iVar7------------> _currentAttachedAudioCount
iVar8------------> _currentAttachedImageCount
iVar9------------> _temporaryAttachmentURLs
iVar10------------> _attachments
Method1------------> disableuserAttachments
Method2------------> setCurrentAttachedVideoCount:
Method3------------> setCurrentAttachedAudioCount:
Method4------------> setCurrentAttachedImageCount:
Method5------------> _MIMETypeForURL:
Method6------------> _isVideoMIMEType:
Method7------------> _isAudioMIMEType:
Method8------------> _isImageMIMEType:
Method9------------> mutableAttachmentURLs
Method10------------> _contentTypeForMIMEType:
Method11------------> _updateAttachmentCountForAttachmentURL:
Method12------------> _buildAttachmentInfoForAttachmentURL:andAlternameFilename:
Method13------------> temporaryAttachmentURLs
Method14------------> canAddAttachmentURL:
Method15------------> addAttachmentData:withAlternateFilename:
Method16------------> _setCanEditRecipients:
Method17------------> messageComposeDelegate
Method18------------> setMutableAttachmentURLs:
Method19------------> currentAttachedVideoCount
Method20------------> currentAttachedAudioCount
Method21------------> currentAttachedImageCount
Method22------------> setTemporaryAttachmentURLs:
Method23------------> dealloc
Method24------------> viewWillAppear:
Method25------------> initWithNibName:bundle:
Method26------------> automaticallyForwardAppearanceAndRotationMethodstochildViewControllers
Method27------------> setModalPresentationStyle:
Method28------------> body
Method29------------> setSubject:
Method30------------> subject
Method31------------> setMessageComposeDelegate:
Method32------------> setBody:
Method33------------> addAttachmentURL:withAlternateFilename:
Method34------------> addAttachmentData:typeIdentifier:filename:
Method35------------> attachmentURLs
Method36------------> attachments
Method37------------> recipients
Method38------------> smsComposeControllerCancelled:
Method39------------> smsComposeControllerSendStarted:
Method40------------> setRecipients:

在我看来,smsComposeControllerSendStarted:方法可能比启动消息发送的实际函数更多的是委托.在上面的方法列表中,没有一个方法签名看起来更接近sendMessage:或类似于实际发送消息的函数.

我的问题是:

1)所有真正的MFMessageComposeViewController都在幕后.或者它是否有一些无法通过运行时函数访问的类集群?

2)如何找出实际的messageSend方法及其实现的类?

任何想法将不胜感激.

谢谢.

解决方法

内部MFMessageComposeViewController使用CKSMSComposeController作为私人ChatKit.framework的实际UI,它使用一大堆其他类(CKSMSComposeQueuingRemoteViewControllerProxy,CKSMSComposeRemoteViewController,CKSMSComposeViewServiceController),包括xpc接口xpcProxy< CKSMSCompose>.

更新1

在阅读了quellish评论后我发现这个http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/看起来像MFMessageComposeViewController和类似的类为他们的目的启动另一个过程.这些进程是xpc服务,它们实现了应用程序与之通信的特定协议.这些流程使用所有必需的权利进行签名.可能/Applications/MessagesViewService.app/MessagesViewService实际上是发送短信的.这个二进制文件是用com.apple.messages.composeclient签名的,这是为了发送我在ChatKit.framework中找到的this代码所必需的.我认为有一种方法可以手动与该xpc服务进行通信以发送短信,但这将很困难.你不能用类转储和类似的简单工具来搞错,这些工具并没有给你太多的信息.

更新2

我已经成功了解了这一点.我扔掉了所有帮助程序类,所有UI内容都没有真正与xpc服务通信.剩下的就足以显示SMS视图控制器并将一些方法发送到xpc服务而不会有任何障碍.

当我们显示SMS组合UI时,iOS确实会启动/Applications/MessagesViewService.app/MessagesViewService进程.这是xpc服务.您可以尝试在应用程序显示时杀死它 – 您将获得黑屏,这意味着它是正确的.

CKSMSComposeRemoteViewController是显示SMS UI的视图控制器.它是_UIRemoteViewController类的子类.基本上,它管理我们的应用程序与在其他进程中在xpc服务中运行的实际UI之间的连接.这是我如何在我的 – (void)viewDidLoad方法获取它的实例

_UIAsyncInvocation* cancelationInvocation = 
[CKSMSComposeRemoveViewController requestViewController:@"CKSMSComposeViewServiceController"
                        fromServiceWithBundleIdentifier:@"com.apple.mobilesms.compose"
                        connectionHandler:
^(CKSMSComposeRemoteViewController* obj,NSError* error){
    smsViewController = obj;
    [smsViewController setDelegate:self];

    smsViewControllerProxy = [smsViewController serviceViewControllerProxy];
}];

smsViewController是一个远程视图控制器实例. smsViewControllerProxy是xpcProxy< CKSMSCompose>实现CKSMSComposeViewServiceProtocol协议的实例 – 方法调用将被转发到xpc服务. xpcProxy并没有真正实现这些方法.它实现了forwardInvocation:方法,以便将调用转发到xpc连接.

_UIAsyncInvocation,查看ivar名称cancelationInvocation,用于取消xpc消息.它仅在CKSMSComposeController viewServiceDidTerminateWithError:方法调用.

以下是我显示控制器的方法

[self presentViewController:smsViewController animated:YES completion:NULL];

您可能注意到[smsViewController setDelegate:self].委托必须实现CKSMSComposeRemoteViewControllerDelegate协议或应用程序将崩溃异常(无法识别的选择器).这是我实施的:

-(void)smsComposeControllerAppeared
{
}

-(void)smsComposeControllerCancelled
{
}

-(void)smsComposeControllerDataInserted
{
}

这足以让你走了.

以下是我们如何向远程视图控制器发送消息:

[smsViewControllerProxy insertTextPart:@"Some text"];

这会将文本插入SMS文本字段并调用smsComposeControllerDataInserted委托方法.

考虑到所有这些,我不再认为我们可以在没有UI的情况下发送短信.实际UI正在另一个进程中运行,我们对它没有任何控制权.我们可以设置一些字段,但就是这样.我希望有一种方法,但事实是,难怪我们做不到.在iOS 6中引入了远程视图来解决这个确切的安全问题 – 在iOS 5上,有一种方法可以在没有用户许可的情况下发送SMS,而一些AppStore应用就是这样做的.所以对Apple赞不绝口.

更新3

我设法在我们与SMS UI交互时转储正在发送的xpc消息.关于日志格式的几句话.第一行 – 拦截消息的地方.它是函数名称或Incoming事件,这意味着它是来自服务的传入消息.连接名称只是xpc连接名称.消息是xpc消息字典内容.消息数据 – 一些xpc消息包含“d” – >“r”键的二进制数据.它是一个序列化的二进制属性列表,无法使用nspropertyListSerialization反序列化 – 它采用了一些新的格式.相反,你需要使用来自Foundation.framework的NSxpcDecoder – (id)_initWithRootxpcObject:(xpc_object_t).现在转储:

SMS UI正在呈现http://pastebin.com/NVEpujSh

按下“发送”按钮后的SMS UI http://pastebin.com/BYXd2djF

编辑SMS字段时会发送和接收消息,但它们仅对应于UI事件.例如,谁成为第一响应者,那些并不能真正说明SMS UI中发生了什么的东西.

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...