首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在ios6上阻止短信

在ios6上阻止短信
EN

Stack Overflow用户
提问于 2013-04-26 00:14:01
回答 3查看 3.5K关注 0票数 3

我正在构建一个越狱设备,我想阻止传入的消息。我试图挂接_ingestIncomingCTMessage,但没有结果(它似乎不能在ios6上工作)。我还能如何在ios6中阻止短信?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-09 05:59:20

这是相当棘手的。苹果在这一领域做出了重大改变。在iOS 5上这很简单,但在iOS 6上我还找不到简单的方法。首先,您需要使用CTTelephonyCenter观察__kIMChatItemsDidChangeNotification通知。我是用SpringBoard注入的dylib来做的。不确定,但这可能很重要。

代码语言:javascript
运行
复制
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:方法在这个特殊的线程上执行块。在IMDPersistence.framework中可以找到IMDChatRecordDeleteChatForGUID函数。它删除具有特定GUID的整个消息树(聊天/对话)。我无法找到检索此GUID的方法,因此我使用SMS sqlite数据库中的GUID作为示例手动构建它。

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

可以在IMCore.framework中找到IMChatItemIMMessageIMDMessageStoreIMDaemonCore.framework中。

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

  1. Bullein.在SpringBoard中,您需要挂钩BBServer方法publishBulletin:destinations:alwaysOnLockScreen:。第一个参数是BBBulletin对象。如果它是传入消息公告,它的section属性等于com.apple.MobileSMS。要阻止公告,只需从该方法返回,不要调用原始实现。
  2. MobileSMS应用程序徽章。当有短消息传入时,SpringBoard中会加载ChatKit.serviceBundle。您需要在MessagesBadgeController中连接两个方法- _madridChatRegistered:_madridUnreadCountChanged:。他们的第一个参数是具有包含IMChat对象的object属性的NSNotification对象。同样,只需从这些方法返回,以防止徽章changes.
  3. MobileSMS应用程序。为了阻止它显示已经删除的消息,我挂接了相当多的方法。我只会给你一个列表:SMSApplication _receivedMessage:CKTranscriptController _messageReceived:CKConversationList _handleRegistryDidRegisterChatNotification:, _handleRegistryDidLoadChatNotification:, hasActiveConversations, unreadCountCKMessagesController showConversation:animate:forceToTranscript:

CKConversationController _chatParticipantsChangedNotification:, updateConversationList

关于ChatKit.serviceBundle。要挂接它的类,您需要等待SpringBoard实际加载它的时候。这是在SBPluginManager loadPluginBundle:中完成的。捆绑包标识符应等于com.apple.SMSPlugin。只有这样,你才能钩住方法。

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

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

票数 5
EN

Stack Overflow用户

发布于 2013-09-20 19:21:33

找到了更好更简单的方法。正如我所认为的,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对象,不加载任何代码。所以你不能挂接任何方法,因为类还没有从插件中加载。为了解决这个问题,我们可以从私有IMDaemonCore.framework连接IMDService -(void)loadServiceBundle方法。调用原始的实现,你就可以在插件内部挂接方法。要确定加载的是哪个插件,可以在IMDService -(NSBundle*)bundle中检查捆绑包标识符。

此方法仅适用于SMS和MMS消息。插件的处理方式类似,但使用不同的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之外,一切都是一样的。字典将包含所有短信内容。

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

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

票数 9
EN

Stack Overflow用户

发布于 2013-07-04 18:47:59

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

代码语言:javascript
运行
复制
%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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16219799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档