[转]iphone4 短信截获
转自:http://www.cnblogs.com/ydhliphonedev/archive/2011/10/23/2221965.html
iphone4 短信截获
所谓的短信截获,可以被程序提前接受到,经过过滤以及相应的处理,然后发送到手机的收件箱中。
ios3上的短信截获通过可以通过一些私有的api即可完成,网上的教程也较多,这里不在重复。
前段时间在调研的ios4上的短信截获,在网上也很难找到相应的,较完整的资料,刚好前段时间学习了hook,
故周末抽了点时间使用hook重新调研了下,这里做个记录,以防止后期遗忘.
测试环境: iphone4 ios4.3.2 已越狱
1. 搭建hook demo开发环境,可以参照我的另一篇文章,这里不再重复。对接受短信的函数进行hook,并进行相应处理与过滤,在通过到手机上。
2. class-dump SMSCTServer.framework, ChatKit.framework, CoreTelephony.framework等framework
其中SMSCTServer.framework中主要包含一些短信发送与接受相关的Api, ChatKit较复杂,其中CKSMSService.h包含很多相应的操作,
例如markAllMessagesInConversationAsRead则是当第一次阅读短信时设置标志位为阅读状态。
CoreTelephony.framework已在ios4上面开放,但是依然有很多的私有api没有被apple开放出来,需要自己测试。
将上面三个库倒出来的头文件加入XCode的编译搜索路径当中,当使用某个类的时候,就可以直接进行#import,此时当然会遇到一些编译错误,
此时需要考虑相对路径与绝对路径,对framework内部的一些#import进行处理。不过好处在于只有你#import某个头文件时,才会去检查这个
头文件内部的语法结构,这就不需要去手动处理所有的framework中的头文件。
3. 环境都搭建好了,接下来就需要去查询可能涉及到的函数,并对其进行hook。
在这里我推荐使用命令grep进行查询,例如查找sendMessage函数,使用grep sendMessage . -r就可以列出所有的包含有这个单词的相关内容。
便于高效快速的去获取到需要的信息。
4. 通过第3步,相信会对一些函数的作用产生怀疑,这个函数到底是不是接受短信的api呢?验证真理最好的办法就是测试。对这些函数进行hook,
并在其中加上一些打印,便可以试验出这些函数的可能功能。
5. 最后得出当接受短信时,由于framework中的函数众多,我只是hook了部分值得怀疑的函数。
- (void)_processReceivedMessageWithInfo:(struct __CFDictionary *)arg1;
- (void)_ingestIncomingCTMessage:(id)arg1;
- (void)_receivedMessage:(struct __CKSMSRecord *)arg1 replace:(BOOL)arg2;
当短信到来时,会至上而下的执行这些函数。在_ingestIncomingCTMessage可以对短信是否发送到手机上进行控制。如果在_processReceivedMessageWithInfo
函数中进行过滤的话,短信在当前确实不会到来,但是重启手机之后,短信其实已经到达收件箱了,只是没有收到通知而已,显然我们想要的不仅仅这么多。
hook的代码如下:
extern "C" void replaced_SMSCTServer_ingestIncomingCTMessage(SMSCTServer *self, SEL cmd, id arg1) { NSLog(@ "--------------------------------replaced_SMSCTServer_ingestIncomingCTMessage enter, arg1 =%@" , arg1); NSLog(@ "===================replaced_SMSCTServer_ingestIncomingCTMessage==============NSStringFromClass([arg1 class]) = %@" , NSStringFromClass([arg1 class ])); CTMessage *message = (CTMessage *)arg1; CTPhoneNumber *sender = (CTPhoneNumber *)message.sender; NSString *digits = sender.digits; // 电话号码 NSString *countryCode = sender.countryCode; NSDate *date = message.date; NSArray *items = message.items; for (CTMessagePart *part in items) { NSData *data = part.data; NSLog(@ "=====================data = %@" , data); // NSLog(@"====================smsData = %@", [CTMmsEncoder decodeMessageFromData:data]); } NSLog(@ "=============countryCode = %@, digits = %@, date = %@" , countryCode, digits, date); NSLog(@ "-----------------------------message = %@, sender = %@" , message, sender); // 在此处可以进行短信的成功截获,利用arg1包含的一些短信信息确认是否应该接受该信息 if ([@ "1065583393" isEqualToString:digits]) { NSLog(@ "---------------------------------------------不允许接受该电话号码的短信." ); |
// 对新短信的到来给予提示 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@ "垃圾短信(%@)" , digits] message:[NSString stringWithFormat:@ "短信发送日期:%@" , date] delegate:self cancelButtonTitle:@ "确定" otherButtonTitles:nil, nil]; [alertView show]; [alertView release]; |
return ; } original_SMSCTServer_ingestIncomingCTMessage(self, cmd, arg1); } |
这这个地方进行一些短信内容的解析工作,如上,1065583393这个号码进行骚扰我,每隔一两天就给我发垃圾短信,如此的话,这个号码再也不会给我发送短信啦。这里的号码就相当于黑名单,可以通过程序进行设置,然后在这里获取相应的号码,并进行过滤。
代码中的UIAlertView会对不打算接受的垃圾短信的到来进行提醒,但是不会去接受。(只是一个测试,别太介意)
参数arg1是CTMessage类型的,包含短信的发送号码,日期,内容等等信息。不过在我使用CTMmsEncoder去对短信内容进行解析时候,提示该类不存在,但是哪个NSData应该就是短信内容的data,对于每条短信的长短NSData的数据长短也不一致。
例如SMSCTServer 的playMessageSent会对发送短信成功的一些提示音进行控制, 不给与返回的话,短信发送出去也不会出现声音
// 控制短信发送完成播放声音 extern "C" void replaced_SMSCTServer_playMessageSent(SMSCTServer *self, SEL cmd) { NSLog(@ "--------------------------------replaced_SMSCTServer_playMessageSent enter " ); original_SMSCTServer_playMessageSent(self, cmd); } |
hook确实可以完成很多强大的功能,私有api,framework,hook,水够深呀!
暂时先做这些吧,等有时间的时候,把每次收到短信,那暴力的提示框给干掉,世界清静了!
by yytong