-
-
【iOS逆向与安全】sms短信转发插件开发
-
发表于: 2023-7-31 16:55 4919
-
前言
经过之前的分享,相信大家已经掌握了用户级的插件开发。勤奋好学的你是否对系统级的插件也有着浓厚的性趣,本篇文章将和大家一起学习如何分析并编写一款系统级的插件。
一、目标
一步步分析并编写一个短信自动转发的deb插件
二、工具
- mac系统
- 已越狱iOS设备:脱壳及frida调试
- IDA Pro:静态分析
- 测试设备:iphone6-ios12.5.5
三、步骤
1、守护进程
守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。例如:推送服务、人脸解锁、iCloud、查找我的iPhone、iMessage等。
相应的配置目录:
/Library/LaunchAgents:管理员控制特定用户的代理
/Library/LaunchDaemons:管理员提供的系统级守护进程(cydia、filza、frida等就在这)
/System/Library/LaunchDaemons:iOS提供的默认守护进程
本文的目的主要短信,所以关注的重点在iOS提供的守护进程,常见的进程配置文件有:
名称 | 描述 |
---|---|
com.apple.apsd | 推送服务 |
com.apple.biometrickitd.pearl | 人脸解锁 |
com.apple.cloudd | iCloud |
com.apple.icloud.findmydeviced | 查找我的iPhone |
com.apple.imagent | 即时消息代理 (iMessage) |
更多服务请参考https://www.theiphonewiki.com/wiki/Services
2、定位关键函数
在iPhone中使用文件管理工具查看/System/Library/LaunchDaemons/com.apple.imagent
文件关键信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version = "1.0" > < dict > <key>EnvironmentVariables< / key> < dict > <key>NSRunningFromLaunchd< / key> <string> 1 < / string> < / dict > <key>ProgramArguments< / key> <array> <string> / System / Library / PrivateFrameworks / IMCore.framework / imagent.app / imagent< / string> < / array> <key>RunAtLoad< / key> <true / > < / dict > < / plist> |
ProgramArguments所对应的路径,就是该进程执行的二进制文件。执行frida-trace -U -m "*[IM* *]" imagent -o a.log
后,当手机收到短信后的日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | - [SMSServiceSession smsMessageReceived: 0x10524abc0 msgID: 0x80000006 ] - [SMSServiceSession _processSMSorMMSMessageReceivedWithContext: 0x10524abc0 messageID: 0x80000006 ] + [IMMetricsCollector sharedInstance] - [IMMetricsCollector trackEvent: 0x1d02ab1e8 ] - [SMSServiceSession _convertCTMessageToDictionary: 0x109a0e510 requiresUpload: 0x16f832c2f ] - [IMMetricsCollector _trackEvent: 0x1d02ab1e8 ] - [SMSServiceSession _fixIncomingDate: 0xd13d420d70d597e6 ] - [SMSServiceSession shouldFixIncomingDate] - [SMSServiceSession _myCTPhoneNumber] + [IMCTSubscriptionUtilities sharedInstance] - [IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions] + [IMCTSubscriptionUtilities sharedInstance] - [IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions] + [IMCTSMSUtilities IMMMSEmailAddressToMatchForPhoneNumber: 0x100830240 simID: 0x0 ] + [IMCTSubscriptionUtilities sharedInstance] - [IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions] - [SMSServiceSession _convertCTMessagePartToDictionary: 0x109a28610 ] - [SMSServiceSession _shouldUploadToMMCS: 0x10524aca0 ] - [SMSServiceSession _receivedSMSDictionary: 0x10524aca0 requiresUpload: 0x0 isBeingReplayed: 0x0 ] - [SMSServiceSession _processReceivedDictionary: 0x10524aca0 storageContext: 0x0 ] + [IMMessageNotificationTimeManager sharedInstance] - [IMMessageNotificationTimeManager acquireAssertionToUnsuspendProcess] + [IMLockdownManager sharedInstance] - [IMLockdownManager isInternalInstall] - [IMLockdownManager _calculateInstallType] - [IMMessageItem initWithSender: 0x100890210 time: 0x1008831d0 body: 0x10083ba80 attributes: 0x0 fileTransferGUIDs: 0x1007081d0 flags: 0x1 error: 0x0 guid: 0x10524acc0 ] - [IMMessageItem initWithSender: 0x100890210 time: 0x1008831d0 body: 0x10083ba80 attributes: 0x0 fileTransferGUIDs: 0x1007081d0 flags: 0x1 error: 0x0 guid: 0x10524acc0 type : 0x0 ] - [IMMessageItem initWithSenderInfo: 0x10085c330 time: 0x1008831d0 timeRead: 0x0 timeDelivered: 0x0 timePlayed: 0x0 subject: 0x0 body: 0x10083ba80 bodyData: 0x0 attributes: 0x0 fileTransferGUIDs: 0x1007081d0 flags: 0x1 guid: 0x10524acc0 messageID: 0x0 account: 0x0 accountID: 0x0 service: 0x0 handle: 0x0 roomName: 0x0 unformattedID: 0x0 countryCode: 0x0 expireState: 0x0 balloonBundleID: 0x0 payloadData: 0x0 expressiveSendStyleID: 0x0 timeExpressiveSendPlayed: 0x0 bizIntent: 0x0 locale: 0x0 errorType: 0x0 type : 0x0 ] - [IMItem initWithSenderInfo: 0x10085c330 time: 0x1008831d0 guid: 0x10524acc0 messageID: 0x0 account: 0x0 accountID: 0x0 service: 0x0 handle: 0x0 roomName: 0x0 unformattedID: 0x0 countryCode: 0x0 type : 0x0 ] - [IMItem setSenderInfo: 0x10085c330 ] |
根据日志可看出关键函数-[SMSServiceSession smsMessageReceived:0x10524abc0 msgID:0x80000006]
, 使用命令frida-trace -U -m "-[SMSServiceSession smsMessageReceived:msgID:]" imagent
跟踪该函数,js代码如下:
1 2 3 4 5 6 7 | { onEnter(log, args, state) { log(`-[SMSServiceSession smsMessageReceived:${ObjC.Object(args[2])} msgID:${args[3]}]`); }, onLeave(log, retval, state) { } } |
当手机收到短信时,对应日志输出如下:
1 | - [SMSServiceSession smsMessageReceived:<CTXPCServiceSubscriptionContext 0x10bfd1240 slotID = CTSubscriptionSlotOne, uuid = 00000000 - 0000 - 0000 - 0000 - 000000000001 , labelID = "90D990CE-3484-4310-9F39-49A66EB80541" , label = "USER_LABEL_PRIMARY" , phoneNumber = "+8618121861895" , userDataPreferred = 1 , userDefaultVoice = 1 > msgID: 0x80000010 ] |
根据日志信息可看出,该方法里除了msgID,并没有包含我们需要的短信及发件人相关信息。那我们继续按日志的顺序往下看,-[SMSServiceSession _convertCTMessageToDictionary:requiresUpload:]
这函数看着比较亲切。trace该函数得到日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | - [SMSServiceSession _convertCTMessageToDictionary:<[CTMessageAddress: 18980003726 / TYPE = PLMN] [Recipients: ( )] [Items: ( "<CTMessagePart: 0x10be7f340>" )] [Raw Headers: (null)] [Date: 2023 - 07 - 30 14 : 43 : 23 + 0000 ] [message ID : - 2147483630 ] [message Type : 1 ] [service center: (null)] [Content - type : (null)] [Content - type params: { }] [replace message: 0 ] requiresUpload: 0x16edaec2f ] - [SMSServiceSession _convertCTMessageToDictionary:requiresUpload:] = { co = "+8618121861895" ; g = "00ECAC3B-0790-8674-CAD5-58DD07F4DEBA" ; h = 18980003726 ; k = ( { data = <e58fa6>; type = "text/plain" ; } ); l = 0 ; m = sms; n = 460 ; re = ( ); sV = 1 ; w = "2023-07-30 14:43:25 +0000" ; }} = |
从日志可以看出。该方法就是我们要hook方法,收件人:co,发件人:h,短信内容:k
3、编写deb插件
具体的创建流程请参考之前的文章,源码如下:
#import <Foundation/Foundation.h> #import "CaptainHook/CaptainHook.h" @interface SMSServiceSession @end @interface IMDService -(void)loadServiceBundle; @property (nonatomic,retain,readonly) NSBundle * bundle; @end CHDeclareClass(SMSServiceSession); // declare class CHOptimizedMethod2(self, id, SMSServiceSession, _convertCTMessageToDictionary, NSDictionary *, arg1, requiresUpload, BOOL*, arg2) { id result = CHSuper2(SMSServiceSession, _convertCTMessageToDictionary, arg1, requiresUpload, arg2); @try { NSString *from = result[@"h"]; NSString *to = result[@"co"]; NSArray *msgList = result[@"k"]; if (msgList.count > 0) { NSData *data = msgList[0][@"data"]; NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"witwit =from %@=to %@=content %@=",from, to, content); } else { NSLog(@"witwit =sms为空="); } } @catch (NSException *exception) { NSLog(@"witwit =SMSServiceSession _convertCTMessageToDictionary=err=%@=", exception); } @finally { } return result; } CHDeclareClass(IMDService) CHOptimizedMethod0(self, void, IMDService, loadServiceBundle) { CHSuper0(IMDService, loadServiceBundle); NSString *bundleId = [[self bundle] bundleIdentifier]; NSLog(@"witwit =IMDService loadServiceBundle=%@=", bundleId); if ([bundleId isEqualToString:@"com.apple.imservice.sms"]) { CHLoadLateClass(SMSServiceSession); CHHook2(SMSServiceSession, _convertCTMessageToDictionary, requiresUpload); } } CHConstructor // code block that runs immediately upon load { @autoreleasepool { NSLog(@"witwit SMSForward load success"); CHLoadLateClass(IMDService); CHHook0(IMDService, loadServiceBundle); } }
info.plist文件配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version = "1.0" > < dict > <key> Filter < / key> < dict > <key>Bundles< / key> <array> <string>com.apple.imagent< / string> < / array> < / dict > < / dict > < / plist> |
注:插件安装完成后。请重启imagent:
1 2 | launchctl unload / System / Library / LaunchDaemons / com.apple.imagent.plist launchctl load / System / Library / LaunchDaemons / com.apple.imagent.plist |
总结
本篇文章主要对短信转发器的核心方法进行了分析及试验,拿到短信内容后,具体的转发逻辑请自行实现。
提示:阅读此文档的过程中遇到任何问题,请关住工众好【
移动端Android和iOS开发技术分享
】或+99 君羊【812546729
】
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课