开发环境: iphone4 (ios4.3.2)
使用hook截获系统处理通知事件,然后进行相应的处理来达到截获的效果。目前的截获不是很完美,黑名单中的人打电话时会先出现“嘟.."声之后才会提示所拨打的用户正在通话中……
前提:需要class-dump CoreTelephony framework,并配置hook开发环境
1. 在说截获之前,先说说dlsym的使用
我们通常会在网上看到一些函数具有我们需要的功能,然后我们在class-dump出的头文件中查找去找不到,但是使用grep在framework中确实可以搜索到相应的符号,导致使用上出现一些麻烦。此时我们就可以使用dlsym来从动态库中获取相应的函数。
2. 挂断电话的函数
- 1 // CoreTelephony framework在系统中的路径
- 2 #define CTPATH "/XCode4.0andIphoneSDK4.3/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony"
- 3
- 4 // 挂断电话函数
- 5 - (BOOL)disconnectCall:(id)call
- 6 {
- 7 void *framework = dlopen(CTPATH, RTLD_LAZY);
- 8 id (*CTCallDisconnect)(id) = dlsym(framework, "CTCallDisconnect");
- 9 CTCallDisconnect(call);
- 10 dlclose(framework);
- 11 return YES;
- 12 }
CTCallDisconnect为挂断电话的函数,但是却没有在头文件中找到相应的声明,故使用dlsym来获取函数指针,进而来使用该函数。
disconnectCall被我定义在Util.m中,做为一个object clss去使用的,不过最好还是定义成C类型的,比较方便使用。
disconnectCall作为挂断电话的函数在下面的截获实现中会使用到。
dlopen等函数在#include <dlfcn.h>头文件中, dlopen之后一定要dlclose去关闭,否则会出现一些问题。
3. 截获电话通知处理事件
CTCallCenter中有些函数是对电话的状态进行通知的,故对CTCallCenter中的handleNotificationFromConnection进行了处理,代码如下:
- 1 extern "C" void replaced_CTCallCenter_handleNotificationFromConnection(CTCallCenter *self, SEL cmd, void *arg1, id arg2, id arg3)
- 2 {
- 3 // NSLog(@"------------------------------------------replaced_CTCallCenter_handleNotificationFromConnection, arg1 = %@, arg2 = %@, arg3 = %@", arg1, arg2, arg3);
- 4
- 5 // NSLog(@"------------arg2Type = %@, arg3Type = %@", NSStringFromClass([arg2 class]), NSStringFromClass([arg3 class]));
- 6
- 7 NSDictionary *dic = (NSDictionary *)arg3;
- 8
- 9 // 此处获得电话状态,CTCallStateDialing, CTCallStateIncoming, CTCallStateConnected, CTCallStateDisconnected等,定义在CTCallCenter.h(非class-dump的头文件)中
- 10 NSLog(@"-------kCTCallStatus = %@", [dic objectForKey:@"kCTCallStatus"]);
- 11
- 12 NSLog(@"--------currentCalls = %@, callEventHandler = %@", self.currentCalls, self.callEventHandler);
- 13
- 14 // 获得CTCall对象
- 15 CTCall *call = [dic objectForKey:@"kCTCall"];
- 16
- 17 // NSLog(@"------callId = %@, callState = %@", call.callID, call.callState);
- 18
- 19 // 这里可以根据kCTCallStatus来判断需要进行的操作
- 20 if (call.callState == CTCallStateDialing)
- 21 {
- 22 NSLog(@"Call has been CTCallStateDialing");
- 23 }
- 24 else if (call.callState == CTCallStateIncoming)
- 25 {
- 26 NSLog(@"Call has just been CTCallStateIncoming");
- 27 //这儿可接可挂
- 28 // 挂断电话
- 29 BOOL flag = [Util disconnectCall:call];
- 30 NSLog(@"----------------是否挂断. flag = %d", flag);
- 31 }
- 32 else if(call.callState == CTCallStateConnected)
- 33 {
- 34 NSLog(@"Call is CTCallStateConnected");
- 35 }
- 36 else if (call.callState == CTCallStateDisconnected)
- 37 {
- 38 NSLog(@"Call is CTCallStateDisconnected");
- 39 }
- 40 else
- 41 {
- 42
- 43 NSLog(@"None of the conditions");
- 44
- 45 }
- 46
- 47 original_CTCallCenter_handleNotificationFromConnection(self, cmd, arg1, arg2, arg3);
- 48 }
上面的代码会对所有的电话都进行过滤处理,电话也都打不进来的,但是会留下一个未接电话。
此处只是提供一个思路,具体的截获需要对传进来的参数等等进行一些解析,并提供一些细致的处理。
在CoreTelephony framework中还含有其他的一些函数,例如对于电话状态改变等等的都可以去细致的研究下,相信会有很大的收获
http://www.cnblogs.com/ydhliphonedev/archive/2011/10/24/2223242.html
http://blog.csdn.net/laigb/article/details/6623068
- extern NSString* const kCTSMSMessageReceivedNotification;
- extern NSString* const kCTSMSMessageReplaceReceivedNotification;
- extern NSString* const kCTSIMSupportSIMStatusNotInserted;
- extern NSString* const kCTSIMSupportSIMStatusReady;
-
-
-
- typedef struct __CTCall CTCall;
- extern NSString *CTCallCopyAddress(void*, CTCall *);
-
- void* CTSMSMessageSend(id server,id msg);
- typedef struct __CTSMSMessage CTSMSMessage;
- NSString *CTSMSMessageCopyAddress(void *, CTSMSMessage *);
- NSString *CTSMSMessageCopyText(void *, CTSMSMessage *);
-
-
- int CTSMSMessageGetRecordIdentifier(void * msg);
- NSString * CTSIMSupportGetSIMStatus();
- NSString * CTSIMSupportCopyMobileSubscriberIdentity();
-
- id CTSMSMessageCreate(void* unknow,NSString* number,NSString* text);
- void * CTSMSMessageCreateReply(void* unknow,void * forwardTo,NSString* text);
-
-
- id CTTelephonyCenterGetDefault(void);
- void CTTelephonyCenterAddObserver(id,id,CFNotificationCallback,NSString*,void*,int);
- void CTTelephonyCenterRemoveObserver(id,id,NSString*,void*);
- int CTSMSMessageGetUnreadCount(void);
-
- static void callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
- {
- NSString *notifyname=(NSString *)name;
- if ([notifyname isEqualToString:@"kCTCallStatusChangeNotification"])
- {
- NSDictionary *info = (NSDictionary*)userInfo;
-
- NSString *state=[[info objectForKey:@"kCTCallStatus"] stringValue];
- if ([state isEqualToString:@"5"])
- NSLog(@"未接:%@",state);
-
- }
- else if ([notifyname isEqualToString:@"kCTCallIdentificationChangeNotification"])
- {
-
-
-
-
-
- NSDictionary *info = (NSDictionary *)userInfo;
- CTCall *call = (CTCall *)[info objectForKey:@"kCTCall"];
- NSString *caller = CTCallCopyAddress(NULL, call);
- NSLog(@"电话号码:%@",caller);
-
-
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTRegistrationDataStatusChangedNotification"])
- {
-
- }
- else if ([notifyname isEqualToString:@"kCTSMSMessageReceivedNotification"])
- {
- if ([[(NSDictionary *)userInfo allKeys]
- containsObject:@"kCTSMSMessage"])
- {
- CTSMSMessage *message = (CTSMSMessage *)
- [(NSDictionary *)userInfo objectForKey:@"kCTSMSMessage"];
- NSString *address = CTSMSMessageCopyAddress(NULL, message);
- NSString *text = CTSMSMessageCopyText(NULL, message);
-
-
-
-
- fflush(stdout);
-
- }
- }
- else if ([notifyname isEqualToString:@"kCTMessageReceivedNotification"])
- {
-
-
-
-
-
- NSDictionary *info = (NSDictionary *)userInfo;
- CFNumberRef msgID = (CFNumberRef)[info objectForKey:@"kCTMessageIdKey"];
- int result;
- CFNumberGetValue((CFNumberRef)msgID, kCFNumberSInt32Type, &result);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTIndicatorsSignalStrengthNotification"])
- {
-
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTRegistrationStatusChangedNotification"])
- {
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTRegistrationDataStatusChangedNotification"])
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTRegistrationCellChangedNotification"])
- {
-
-
-
-
-
-
- }
- else if ([notifyname isEqualToString:@"kCTIndicatorRadioTransmitNotification"])
- {
-
-
-
- }
-
-
-
-
- NSLog(@"名字:%@-详细:%@",notifyname,userInfo);
-
-
- }
-
- static void signalHandler(int sigraised)
- {
- printf("\nInterrupted.\n");
- exit(0);
-
- }
执行
- id ct = CTTelephonyCenterGetDefault();
- CTTelephonyCenterAddObserver(ct, NULL, callback, NULL, NULL, CFNotificationSuspensionBehaviorHold);
-
- sig_t oldHandler = signal(SIGINT, signalHandler);
- if (oldHandler == SIG_ERR)
- {
- printf("Could not establish new signal handler");
- exit(1);
- }
-
- printf("Starting run loop and watching for notification.\n");
-