Search code examples
iosios6jailbreak

Block sms on ios6


I'm building for a jail-broken device and I want to block incoming messages. I'm trying to hook _ingestIncomingCTMessage, but it has no result( it seems not working on ios6). How else I can block sms in ios6?


Solution

  • This is quite tricky. Apple made major changes in this area. It's very easy on iOS 5 but on iOS 6 I couldn't find easy way to do it yet. First, you need to observer __kIMChatItemsDidChangeNotification notification using CTTelephonyCenter. I'm doing it in dylib injected in SpringBoard. Not sure but this may be important.

    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]);
            }];
        }
    }
    

    Last bit is very important. You can't just delete message. You need to do it on a specific internal thread or you'll get an error. This is why I'm using IMDMessageStore. It's performBlock: method executes block on this special thread. IMDChatRecordDeleteChatForGUID function can be found in IMDPersistence.framework. It deletes whole message tree (chat/conversation) with specific GUID. I couldn't find a way to retrive this GUID so I'm building it manually using GUIDs from SMS sqlite database as a sample.

    To delete just one message you can use IMDMessageRecordDeleteMessagesForGUIDs([NSArray arrayWithObject:[msg guid]]);

    IMChatItem and IMMessage can be found in IMCore.framework. IMDMessageStore is in IMDaemonCore.framework.

    This is easy part. Now when you receive message and block it this way you will see that it still shows in MobileSMS app, you still might get bullein notification, you still get badge telling you there is unread message. But if you open SMS sqlite database you will see that message was indeed deleted. Blocking these is not that easy.

    1. Bullein. In SpringBoard you need to hook BBServer method publishBulletin:destinations:alwaysOnLockScreen:. First argument is BBBulletin object. If it's incoming message bulletin it's section property equals com.apple.MobileSMS. To block bulletin just return from this method and don't call original implementation.
    2. MobileSMS app badge. There is ChatKit.serviceBundle that's being loaded in SpringBoard when there is incoming SMS. You need to hook two methods in MessagesBadgeController - _madridChatRegistered: and _madridUnreadCountChanged:. Their first argument is NSNotification object with object property containing IMChat object. Again, just return from these methods to prevent badge changes.
    3. MobileSMS app. To stop it from showing already deleted messages I'm hooking quite a lot of methods. I will just give you the list: SMSApplication _receivedMessage:, CKTranscriptController _messageReceived:, CKConversationList _handleRegistryDidRegisterChatNotification:, _handleRegistryDidLoadChatNotification:, hasActiveConversations, unreadCount. CKConversationController _chatParticipantsChangedNotification:, updateConversationList, CKMessagesController showConversation:animate:forceToTranscript:

    About ChatKit.serviceBundle. To hook it's classes you need to wait when SpringBoard actually loads it. This is done in SBPluginManager loadPluginBundle:. Bundle identifier should be equal to com.apple.SMSPlugin. Only then you can hook methods.

    That's it. Quite a lot of work but it's working perfectly - no sign of incoming message, even if you were in MobileSMS application when message arrived.

    I'm sure there is easier way to do it. There is com.apple.imagent daemon which sends notifications to various iOS components. It's very important in iOS 6 messaging system. Good place to start.