探索iOS 6 MACH下的守护进程配置

iOS系统中,获取无线网络连接状态的信息相对有限。公共API仅允许获取SSID、BSSID和适配器网络设置等信息。那么,加密模式和信号强度等数据如何获取呢?本文将介绍一种在不使用私有API和越狱的情况下获取这些数据的方法。

iOS5.x时代的系统日志

在iOS 5.x版本中,可以通过Apple系统日志设施获取系统消息,这些消息在连接到网络时显示,其中包含了加密模式和信号强度数据。以下是Objective-C代码示例,展示了如何使用系统日志获取这些信息:

aslmsg asl, message; aslresponse searchResult; int i; const char *key, *val; NSMutableArray *result_dicts = [NSMutableArray array]; asl = asl_new(ASL_TYPE_QUERY); if (!asl) { NSLog(@"Failed creating ASL query"); } asl_set_query(asl, "Sender", "kernel", ASL_QUERY_OP_EQUAL); asl_set_query(asl, "Message", "AppleBCMWLAN Joined BSS:", ASL_QUERY_OP_PREFIX|ASL_QUERY_OP_EQUAL); searchResult = asl_search(NULL, asl); while (NULL != (message = aslresponse_next(searchResult))) { NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary]; for (i = 0; (NULL != (key = asl_key(message, i))); i++) { NSString *keyString = [NSString stringWithUTF8String:(char *)key]; val = asl_get(message, key); NSString *string = [NSString stringWithUTF8String:val]; [tmpDict setObject:string forKey:keyString]; } [result_dicts addObject:tmpDict]; } aslresponse_free(searchResult); asl_free(asl);

然而,苹果公司在意识到这一点后,像往常一样关闭了对系统消息的访问。因此,需要找到一种新的方法来获取这些数据。

在Mac OS和iOS中获取数据

首先,可以使用scutil工具,它允许获取系统配置数据,包括所需的信息。在iOS 6上测试越狱的iPhone证明该工具工作得很好。这对来说是一个线索,开始寻找在iOS上访问SystemConfiguration的方法。

SystemConfiguration.framework允许连接到Mac OS值存储并获取属性列表,其中包含了无线网络数据。但是,当查看库的头文件时,会发现使用所需方法受到限制。

CFPropertyListRef SCDynamicStoreCopyValue( SCDynamicStoreRef store, CFStringRef key ) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_NA);

首先,确保该方法是有效的。

void *handle = dlopen("/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration", RTLD_LAZY); CFArrayRef (*_SCDynamicStoreCopyKeyList)(int store, CFStringRef pattern) = dlsym(handle, "SCDynamicStoreCopyKeyList"); NSLog(@"Lib handle: %u", handle); NSString *key = @"State:/Network/Global/DNS"; CFArrayRef testarrray = _SCDynamicStoreCopyKeyList(0, CFSTR("State:/Network/Interface/en0/AirPort")); NSLog(@"Tested array res: %@", testarrray);

一切都很好。结果返回了。所以没有阻碍,只有苹果公司的形式限制,这将不允许在App Store中通过验证。

编写自己的库

不管怎样,为什么不自己写一个库呢?源代码很容易找到:它是守护进程configd的一部分。

当阅读SCDynamicStoreCopyValue的描述时,最有趣的部分开始了。

#include "config.h" /* MiG generated file */ ... /* send the key & fetch the associated data from the server */ status = configget(storePrivate->server, myKeyRef, myKeyLen, &xmlDataRef, (int*)&xmlDataLen, &newInstance, (int*)≻_status);

OK。请求被传递到使用MACH Interface Generator生成的文件。在附近的文件中找到了MIG的描述。

routine configget ( server : mach_port_t; key : xmlData; out data : xmlDataOut, dealloc; out newInstance : int; out status : int);

现在有两个选择——普通人的方式和绝地武士的方式。可以运行mig在文件config.defs上,并获得要输入到项目中的代码。

但不幸的是,在研究过程中没有发现该文件,所以不得不做一些逆向工程:)然而,Dmitry Sklyarov展示了他的绝地武士技能,并设法恢复了发送请求到MACH端口configd的过程。因此,该方法被完全恢复了。

#define kMachPortConfigd "com.apple.SystemConfiguration.configd" -(NSDictionary *)getSCdata:(NSString *)key { if (SYSTEM_VERSION_LESS_THAN(@"6.0")) { // It does not work on iOS 5.* return nil; } struct send_body {mach_msg_header_t header; int count; UInt8 *addr; CFIndex size0; int flags; NDR_record_t ndr; CFIndex size; int retB; int rcB; int f24; int f28;}; mach_port_t bootstrapport = MACH_PORT_NULL; mach_port_t configport = MACH_PORT_NULL; mach_msg_header_t *msg; mach_msg_return_t msg_return; struct send_body send_msg; // Make request CFDataRef extRepr; extRepr = CFStringCreateExternalRepresentation(NULL, (__bridge CFStringRef)(key), kCFStringEncodingUTF8, 0); // Connect to Mach MIG port of configd task_get_bootstrap_port(mach_task_self(), &bootstrapport); bootstrap_look_up2(bootstrapport, kMachPortConfigd, &configport, 0, 8LL); // Make request send_msg.count = 1; send_msg.addr = (UInt8*)CFDataGetBytePtr(extRepr); send_msg.size0 = CFDataGetLength(extRepr); send_msg.size = CFDataGetLength(extRepr); send_msg.flags = 0x1000100u; send_msg.ndr = NDR_record; // Make message header msg = &(send_msg.header); msg->msgh_bits = 0x80001513u; msg->msgh_remote_port = configport; msg->msgh_local_port = mig_get_reply_port(); msg->msgh_id = 20010; // Request server msg_return = mach_msg(msg, 3, 0x34u, 0x44u, msg->msgh_local_port, 0, 0); if (msg_return) { if (msg_return - 0x10000002u >= 2 && msg_return != 0x10000010) { mig_dealloc_reply_port(msg->msgh_local_port); } else { mig_put_reply_port(msg->msgh_local_port); } } else if (msg->msgh_id != 71 && msg->msgh_id == 20110 && msg->msgh_bits <= -1) { if ((send_msg.flags & 0xFF000000) == 0x1000000) { CFDataRef deserializedData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, send_msg.addr,send_msg.size0, kCFAllocatorNull); CFPropertyListRef proplist = CFPropertyListCreateWithData(kCFAllocatorDefault, deserializedData, kCFPropertyListImmutable, NULL, NULL); mig_dealloc_reply_port(msg->msgh_local_port); mach_port_deallocate(mach_task_self(), bootstrapport); mach_port_deallocate(mach_task_self(), configport); mach_msg_destroy(msg); NSDictionary *property_list = (__bridge NSDictionary*)proplist; if (proplist) CFRelease(proplist); CFRelease(deserializedData); CFRelease(extRepr); return property_list; } } mig_dealloc_reply_port(msg->msgh_local_port); mach_port_deallocate(mach_task_self(), bootstrapport); mach_port_deallocate(mach_task_self(), configport); mach_msg_destroy(msg); CFRelease(extRepr); return nil; }

所需的数据位于键@«Setup:/Network/Interface/en0/AirPort»。因此,实现了SystemConfiguration.framework的一部分,并在不越狱和非法使用库的情况下获取了数据。

有趣的是,iOS6中有100多个开放的MACH端口,具有各种名称。猜这为研究提供了舞台。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485