Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

ios - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Found much better and simpler way. Just as I thought com.apple.imagent daemon is very important and it's him who is handling kCTMessageReceivedNotification. This is why we get empty message object when handling kCTMessageReceivedNotification yourself - com.apple.imagent is removing it from CTMessageCenter.

We need to hook just two methods but finding and hooking them is quite tricky. Both methods are hooked in com.apple.imagent daemon.

First, SMSServiceSession -(void)_processReceivedMessage:(CTMessage*)msg. This is where incoming message is being initially processed, saved to the SMS database and passed to all other iOS components. Problem is there is no information about this API anywhere. com.apple.imagent appears to be not using it if you disassemble it. It's because it's being loaded manually at runtime.

When com.apple.imagent is started he's loading several plugins. The one that we need is located in /System/Library/Messages/PlugIns/SMS.imservice/ - this is where SMSServiceSession is implemented. You will not find binary in there because just like all the frameworks it's compiled into /System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv7. IDA recognizes this file and let's you choose which binary inside of it you want to disassemble.

To delete incoming message and prevent any notifications about it you need to call [[CTMessageCenter sharedMessageCenter] acknowledgeIncomingMessageWithId:[msg messageId]] and return from _processReceivedMessage: without calling original implementation. Calling CTMessageCenter method is important because it queues incoming messages.

Now we need to find a way to know whenSMS.imservice plugin is being actually loaded. Initially imagent only creates NSBundle objects without loading any code. So you can't hook any methods because classes are not yet loaded from the plugins. To solve this we can hook IMDService -(void)loadServiceBundle method from private IMDaemonCore.framework. Call original implementation and you can hook methods inside the plugin. To determine which plugin is being loaded you can check bundle identifier in IMDService -(NSBundle*)bundle.

This method works only with SMS and MMS messages. iMessages are processed in similar way but with different plugin - /System/Library/Messages/PlugIns/iMessage.imservice. Hooking MessageServiceSession -(void)_handler:(id) incomingMessage:(id) encryptionType:(id) messageID:(id) fromIdentifier:(id) fromToken:(id) timeStamp:(id) storageContext:(id) allowRetry:(char) completionBlock:(id) should do the trick.

UPDATE

Works on iOS 7

UPDATE 2

On iOS 8 everything works the same way except you need to hook different SMSServiceSession method - -(void)_processReceivedDictionary:(NSDictionary*)msg. Dictionary will contain all SMS message contents.

If you don't want to rewrite everything for iOS 8 you can reuse your old code. Incoming SMS notification is handled by hidden non-exported C callback function - you can't hook it. First, it calls SMSServiceSession -(id)_convertCTMessageToDictionary:(CTMessage*)msg requiresUpload:(BOOL*)upload to convert SMS message object to dictionary. Then it calls SMSServiceSession -(void)_processReceivedDictionary:(NSDictionary*)msg to process message. Finally, it calls SMSServiceSession -(BOOL)relayDictionaryToPeers:(NSDictionary*)msg requiresUpload:(BOOL)upload to notify all other iOS components about incoming message.

To block SMS you need to hook _convertCTMessageToDictionary where you can use the same code you used on previous iOS versions. You also need to hook both _processReceivedDictionary and relayDictionaryToPeers to actually block incoming message. Just return from them without calling original implementation. You can set some global variable in _convertCTMessageToDictionary and check and reset it in other methods. It's perfectly safe to do it that way - these methods are called one after another synchronously. That C callback function is the only places where these methods are called.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...