- iOS进程通讯安全和利用
iOS有Mach Message,XPC等多种进程通讯方式,由于越狱环境权限较大,进程之间的通讯安全尤为重要。本文通过介绍iOS进程通讯的常用方式,对方式的实现进行安全性分析,给出通讯方式的伪造利用案例及防护方案。
一,iOS IPC概述
Mach Message为iOS进程通信的基本方式,常用的进程通讯均在Mach Message上进行封装
常用的IPC如下:
- Mach Message->MIG->Distributed Notifications
- Mach Message->Distributed Objects
- Mach Message->XPC->NSXPC
- Mach Message->CFPort->CFMessage Port
iOS全部通讯方式Ian Beer整理了一份详细的关系图:
二,常用IPC和适用场景
1,Distributed Notifications
系统层通讯,接收端通过在注册监听系统消息中心,发送端通过发送全局广播的方式进行通讯,适用快捷方便适合轻量级的通讯,越狱插件与前端的通讯方式几乎全部使用此方法。
接收端监听消息demo:
CFNotificationCenterRef distributedCenter = CFNotificationCenterGetDistributedCenter(); CFNotificationSuspensionBehavior behavior =CFNotificationSuspensionBehaviorDeliverImmediately; CFNotificationCenterAddObserver(distributedCenter, NULL, Callback, CFSTR("xxx"), NULL, behavior);
接收端接收消息后的回调函数:
static void Callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { }
发送端使用底层c函数notify_post(“xxx”)即可发送全局广播,或使用封装好的CFNotificationCenterPostNotification如下
void *object; CFDictionaryRef userInfo; CFNotificationCenterRef distributedCenter =CFNotificationCenterGetDistributedCenter(); CFNotificationCenterPostNotification(distributedCenter, CFSTR("xxx"), object, userInfo, true);
2,CFMessage Port
CFMessage Port通过Mach port实现,适合简单的一对一通讯,通过CFMessagePortCreateLocal创建一个有唯一标识符的本地CFMessagePortRef对象,同时设置回调函数用于处理事件,最后将创建的对象添加到Runloop中实现端口的监听,Runloop收到端口相应的事件即调用指定的回调函数
在iOS7以后CFMessage Port通讯方式已被弃用。
接收端demo:
static CFDataRef Callback(CFMessagePortRef port, SInt32 messageID, CFDataRef data, void *info) { } CFMessagePortRef localPort = CFMessagePortCreateLocal(nil, CFSTR("com.example.app.port.server"), Callback, nil, nil); CFRunLoopSourceRef runLoopSource =CFMessagePortCreateRunLoopSource(nil, localPort, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
发送端demo:
CFDataRef data; SInt32 messageID = 0x1111; // Arbitrary CFTimeInterval timeout = 10.0; CFMessagePortRef remotePort = CFMessagePortCreateRemote(nil,CFSTR("com.example.app.port.client")); SInt32 status =CFMessagePortSendRequest(remotePort, messageID, data, timeout, timeout, NULL, NULL); if (status == kCFMessagePortSuccess) { // ... }
3,XPC
2011年开始使用,最早用于OSX10.7和iOS5,在Mach Message基础上进行封装,简化了消息传递细节,通过客户端和服务端建立连接的方式,现作为iOS系统服务的主流通讯方式,除少数系统服务直接只用Mach Message通讯外其他均为XPC
在OSX10.8以后Foundation.framework中添加了NSXPCConnection相关的类,XPC即可使用NSXPCConnection的OC实现,也可使用底层的C实现
客户端demo:
xpc_connection_t client = xpc_connection_create_mach_service("com.apple.test", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_event_handler(client, ^void(xpc_object_t response) { double result = xpc_dictionary_get_double(response, "result");}); xpc_connection_resume(client); xpc_object_t dictionary = xpc_dictionary_create(NULL, NULL, 0); xpc_object_t reply = xpc_connection_send_message_with_reply_sync(client, dictionary);
服务端demo:
xpc_connection_t listener=xpc_connection_create_mach_service("com.apple.test1", NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); xpc_connection_set_event_handler(listener,^(xpc_object_t peer){ xpc_connection_set_event_handler(static_cast<xpc_connection_t>(peer), ^(xpc_object_t event) { xpc_type_t type = xpc_get_type(event); if(type==XPC_TYPE_DICTIONARY){ xpc_object_t dictionary = xpc_dictionary_create(NULL, NULL, 0); xpc_connection_send_message(static_cast<xpc_connection_t>(peer), dictionary);} }); xpc_connection_resume(static_cast<xpc_connection_t>(peer)); }); xpc_connection_resume(listener);
XPC为目前最先进的进程通讯方式,但在越狱插件的使用中比Distributed Notifications复杂,iOS所有服务由lauched组织启动,需通过task_get_bootstrap_porto找到lauchd端口,bootstrap_check_in通过lauchd寻找所要启动的服务
三,IPC安全分析及利用
1,越狱环境下主流app通讯方式和隐患
在非越狱环境下程序无法主动调用以上进程通讯方式,进程通讯发生在系统服务间
在越狱环境下分析目前市场上主流的越狱插件360手机卫士pro等,前端与dylib之间的通讯均使用Distributed Notifications
Distributed Notifications通讯为dylib注册监听通知中心中自定义消息名,前端发送此消息名的全局广播则dylib执行回调函数,而自定义的消息名硬编码在二进制文件中可通过IDA提取,所以通讯中存在安全隐患,可以创建第三方app发送带此消息名的广播调用dylib全部功能
2,腾讯手机管家密码破解
手机管家有隐私短信,隐私照片,隐藏app,软件锁等多项隐私保护功能,所有功能均由dylib实现,通过在前端输入密码如果前端判断输入密码正确则对dylib发送指定消息,在密码未知的情况下创建任意app发送此消息则实现密码的全部破解
以破解隐藏app为例,以下为管家监听和发送源码:
检查密码发送端:
dylib监听消息,收到消息执行sub_10800显示全部app:
设置密码隐藏全部指定app
创建任意app执行import<notify.h>
notify_post("DarwinPrivacyManagerUnHiddingNotification");隐藏全部显示
其他破解私密短信和相册同理。
3,其他通讯方式安全性分析
Distributed Notifications为系统级通讯,接收端监听消息无法判断消息来源是否合法。测试了其他进程通讯如Mach Message,XPC,由于所有进程通讯方式均会创建服务名或端口等唯一标示符号,而发送消息函数固定,提取唯一标识符后均可伪造消息。所以在越狱环境下所有进程通讯都是不安全的。
四,IPC保护
发送接收函数固定,在越狱环境阻止通讯伪造可通过阻止硬编码唯一标识符的提取,可使用代码混淆阻止定位到注册消息函数或使用硬编码混淆 https://github.com/pjebs/Obfuscator-iOS