阻止ios6上的短信

时间:2013-04-25 16:14:01

标签: ios ios6 jailbreak

我正在构建一个破牢的设备,我想阻止传入的消息。 我正在尝试挂钩_ingestIncomingCTMessage,但它没有结果(它似乎不适用于ios6)。我怎样才能阻止ios6中的短信?

3 个答案:

答案 0 :(得分:9)

找到更好,更简单的方法。正如我认为com.apple.imagent守护进程非常重要,并且正在处理kCTMessageReceivedNotification的是他。这就是我们自己处理kCTMessageReceivedNotification时获取空消息对象的原因 - com.apple.imagent将其从CTMessageCenter中删除。

我们需要挂钩两个方法,但找到并挂钩它们非常棘手。这两种方法都挂在com.apple.imagent守护进程中。

首先,SMSServiceSession -(void)_processReceivedMessage:(CTMessage*)msg。这是传入消息最初处理,保存到SMS数据库并传递给所有其他iOS组件的地方。问题是在任何地方都没有关于此API的信息。如果您将其拆解,com.apple.imagent似乎没有使用它。这是因为它是在运行时手动加载的。

启动com.apple.imagent时,他会加载几个插件。我们需要的是/System/Library/Messages/PlugIns/SMS.imservice/ - 这是实施SMSServiceSession的地方。你不会在那里找到二进制文件,因为就像它编译成/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv7的所有框架一样。 IDA识别此文件,让您选择要拆卸的二进制内容。

要删除收到的消息并阻止任何有关它的通知,您需要致电[[CTMessageCenter sharedMessageCenter] acknowledgeIncomingMessageWithId:[msg messageId]]并从_processReceivedMessage:返回,而无需调用原始实施。调用CTMessageCenter方法很重要,因为它会对传入的消息进行排队。

现在我们需要找到一种方法来了解实际加载SMS.imservice插件的时间。最初,imagent只创建NSBundle个对象而不加载任何代码。因此,您无法挂钩任何方法,因为类尚未从插件加载。要解决此问题,我们可以将IMDService -(void)loadServiceBundle方法与私有IMDaemonCore.framework挂钩。调用原始实现,您可以在插件中挂钩方法。要确定加载哪个插件,您可以在IMDService -(NSBundle*)bundle中检查包标识符。

此方法仅适用于短信和彩信。 iMessages以类似的方式处理,但使用不同的插件 - /System/Library/Messages/PlugIns/iMessage.imservice。挂钩MessageServiceSession -(void)_handler:(id) incomingMessage:(id) encryptionType:(id) messageID:(id) fromIdentifier:(id) fromToken:(id) timeStamp:(id) storageContext:(id) allowRetry:(char) completionBlock:(id)应该可以解决问题。

<强>更新

适用于iOS 7

更新2

在iOS 8上,除了您需要挂钩不同的SMSServiceSession方法 - -(void)_processReceivedDictionary:(NSDictionary*)msg之外,所有内容的工作方式都相同。字典将包含所有SMS消息内容。

如果您不想重写iOS 8的所有内容,则可以重复使用旧代码。传入的SMS通知由隐藏的非导出C回调函数处理 - 您无法挂钩它。首先,它调用SMSServiceSession -(id)_convertCTMessageToDictionary:(CTMessage*)msg requiresUpload:(BOOL*)upload将SMS消息对象转换为字典。然后它调用SMSServiceSession -(void)_processReceivedDictionary:(NSDictionary*)msg来处理消息。最后,它调用SMSServiceSession -(BOOL)relayDictionaryToPeers:(NSDictionary*)msg requiresUpload:(BOOL)upload来通知所有其他iOS组件有关传入消息。

要阻止短信,您需要挂钩_convertCTMessageToDictionary,您可以使用与之前iOS版本相同的代码。您还需要挂钩_processReceivedDictionaryrelayDictionaryToPeers以实际阻止传入的消息。只需从它们返回而不调用原始实现。您可以在_convertCTMessageToDictionary中设置一些全局变量,并在其他方法中检查并重置它。这样做是非常安全的 - 这些方法是一个接一个地同步调用的。那个C回调函数是调用这些方法的唯一地方。

答案 1 :(得分:5)

这非常棘手。 Apple在这方面做出了重大改变。这在iOS 5上很容易,但在iOS 6上我找不到简单的方法。 首先,您需要使用CTTelephonyCenter观察__kIMChatItemsDidChangeNotification通知。我是在SpringBoard注入的dylib中做的。不确定,但这可能很重要。

CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, Callback, NULL, NULL, CFNotificationSuspensionBehaviourHold);

void Callback(CFNotificationCenterRef, void*, NSString* notification, const void*, NSDictionary* userInfo)
{
    if (![notification isEqualToString:@"__kIMChatItemsDidChangeNotification"])
    {
        return;
    }

    for (IMChatItem* chatItem in userInfo[@"__kIMChatItemsKey"])
    {
        IMMessage* msg = [chatItem message];//Incoming message object
        NSString* text = [[msg text] string];//message text
        NSString* sender = [[msg sender] ID];//message sender

        [[IMDMessageStore sharedInstance] performBlock:^{
            IMDChatRecordDeleteChatForGUID([NSString stringWithFormat:@"SMS;-;%@", sender]);
        }];
    }
}

最后一点非常重要。你不能只删除邮件。您需要在特定的内部线程上执行此操作,否则您将收到错误。这就是我使用IMDMessageStore的原因。它的performBlock:方法在这个特殊线程上执行块。 IMDChatRecordDeleteChatForGUID函数可以在IMDPersistence.framework中找到。它删除具有特定GUID的整个消息树(聊天/对话)。我无法找到一种方法来检索此GUID,因此我使用SMS sqlite数据库中的GUID作为样本手动构建它。

要删除一条消息,您可以使用IMDMessageRecordDeleteMessagesForGUIDs([NSArray arrayWithObject:[msg guid]]);

可以在IMChatItem中找到

IMMessageIMCore.frameworkIMDMessageStore位于IMDaemonCore.framework

这很容易。现在,当您收到消息并以此方式阻止它时,您将看到它仍然显示在MobileSMS应用程序中,您仍然可能会收到bullein通知,您仍然会获得徽章,告诉您有未读消息。但是,如果您打开SMS sqlite数据库,您将看到该消息确实被删除。阻止这些并不容易。

  1. Bullein。在SpringBoard中,您需要挂钩BBServer方法publishBulletin:destinations:alwaysOnLockScreen:。第一个参数是BBBulletin对象。如果是传入消息公告,则section属性等于com.apple.MobileSMS。要阻止公告,只需从此方法返回,不要调用原始实现。
  2. MobileSMS应用徽章。当有传入的短信时,有SpringKoard加载的ChatKit.serviceBundle。您需要在MessagesBadgeController - _madridChatRegistered:_madridUnreadCountChanged:中挂钩两个方法。他们的第一个参数是NSNotification对象,其object属性包含IMChat个对象。再次,只需从这些方法返回以防止徽章更改。
  3. MobileSMS应用。为了阻止它显示已删除的消息,我是 挂了很多方法。我会给你清单: SMSApplication _receivedMessage:CKTranscriptController _messageReceived:CKConversationList _handleRegistryDidRegisterChatNotification:, _handleRegistryDidLoadChatNotification:, hasActiveConversations, unreadCountCKConversationController _chatParticipantsChangedNotification:, updateConversationListCKMessagesController showConversation:animate:forceToTranscript:
  4. 关于ChatKit.serviceBundle。要挂钩它的类,你需要等待SpringBoard实际加载它。这是在SBPluginManager loadPluginBundle:中完成的。 Bundle标识符应该等于com.apple.SMSPlugin。只有这样你才能挂钩方法。

    就是这样。相当多的工作,但它工作得很好 - 没有传入消息的迹象,即使你在消息到达时在MobileSMS应用程序中。

    我确信有更简单的方法可以做到这一点。 com.apple.imagent守护程序向各种iOS组件发送通知。这在iOS 6消息传递系统中非常重要。开始的好地方。

答案 2 :(得分:1)

我有一个更好的解决方案来阻止所有短信

%hook CKConversationListController

- (void)viewDidLoad
{
    %orig;

    CKConversationList *list = MSHookIvar<CKConversationList *>(self, "_conversationList");

    if ([list count]) {
        [deleteAll release];
    }
}

%new
- (void)deleteAll:(id)sender {

    CKConversationList *list = MSHookIvar<CKConversationList *>(self, "_conversationList");
    UITableView *messages = MSHookIvar<UITableView *>(self, "_table");

    for (unsigned int i = 0; i < [[list conversations] count]; i++) {
        [list deleteConversationAtIndex:i];
    }

    [messages reloadData];
}
%end