现在的位置: 首页 > 综合 > 正文

iphone4 电话截获

2013年09月07日 ⁄ 综合 ⁄ 共 8040字 ⁄ 字号 评论关闭

开发环境: 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/*always 0*/,NSString* number,NSString* text);  
    void * CTSMSMessageCreateReply(void* unknow/*always 0*/,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"])//disconnect  
                NSLog(@"未接:%@",state);  
              
        }  
        else if ([notifyname isEqualToString:@"kCTCallIdentificationChangeNotification"])  
        {  
    //        CTCallCenter *center = [[CTCallCenter alloc] init];  
    //        center.callEventHandler = ^(CTCall *call) {  
    //            NSLog(@"call:%@", [call description]);  
    //        };  
              
            NSDictionary *info = (NSDictionary *)userInfo;  
            CTCall *call = (CTCall *)[info objectForKey:@"kCTCall"];  
            NSString *caller = CTCallCopyAddress(NULL, call);  
            NSLog(@"电话号码:%@",caller);  
            //CTCallDisconnect(call);  
            /* or one of the following functions: CTCallAnswer 
             CTCallAnswerEndingActive 
             CTCallAnswerEndingAllOthers 
             CTCallAnswerEndingHeld 
            */  
              
        }  
        else if ([notifyname isEqualToString:@"kCTRegistrationDataStatusChangedNotification"])  
        {  
              
        }  
        else if ([notifyname isEqualToString:@"kCTSMSMessageReceivedNotification"])  
        {//api 已过期  
            if ([[(NSDictionary *)userInfo allKeys]    
                 containsObject:@"kCTSMSMessage"]) // SMS Message    
            {    
                CTSMSMessage *message = (CTSMSMessage *)    
                [(NSDictionary *)userInfo objectForKey:@"kCTSMSMessage"];    
                NSString *address = CTSMSMessageCopyAddress(NULL, message);    
                NSString *text = CTSMSMessageCopyText(NULL, message);    
                //NSArray *lines = [text componentsSeparatedByString:@"\n"];    
                  
                //printf("  %s %d\n", [address cString], [lines count]);    
                //printf("  %s\n", [text cString]);    
                fflush(stdout);    
              
            }  
        }  
        else if ([notifyname isEqualToString:@"kCTMessageReceivedNotification"])//收到短信  
        {  
            /* 
             kCTMessageIdKey = "-2147483636"; 
             kCTMessageTypeKey = 1;  
            */  
              
            NSDictionary *info = (NSDictionary *)userInfo;  
            CFNumberRef msgID = (CFNumberRef)[info objectForKey:@"kCTMessageIdKey"];  
            int result;  
            CFNumberGetValue((CFNumberRef)msgID, kCFNumberSInt32Type, &result);  
              
            /* 
            Class CTMessageCenter = NSClassFromString(@"CTMessageCenter"); 
            id mc = [CTMessageCenter sharedMessageCenter]; 
            id incMsg = [mc incomingMessageWithId: result]; 
             
            int msgType = (int)[incMsg messageType]; 
             
            if (msgType == 1) //experimentally detected number 
            { 
                id phonenumber = [incMsg sender]; 
                 
                NSString *senderNumber = (NSString *)[phonenumber canonicalFormat]; 
                id incMsgPart = [[incMsg items] objectAtIndex:0]; 
                NSData *smsData = [incMsgPart data]; 
                NSString *smsText = [[NSString alloc] initWithData:smsData encoding:NSUTF8StringEncoding]; 
            } 
            */  
        }  
        else if ([notifyname isEqualToString:@"kCTIndicatorsSignalStrengthNotification"])//信号  
        {  
            /* 
            kCTIndicatorsGradedSignalStrength = 2; 
            kCTIndicatorsRawSignalStrength = "-101"; 
            kCTIndicatorsSignalStrength = 19; 
            */  
              
        }  
        else if ([notifyname isEqualToString:@"kCTRegistrationStatusChangedNotification"])//网络注册状态  
        {  
            /* 
             kCTRegistrationInHomeCountry = 1; 
             kCTRegistrationStatus = kCTRegistrationStatusRegisteredHome; 
            */  
              
        }  
        else if ([notifyname isEqualToString:@"kCTRegistrationDataStatusChangedNotification"])  
        {  
            /* 
             kCTRegistrationDataActive = 1; 
             kCTRegistrationDataAttached = 1; 
             kCTRegistrationDataConnectionServices =     ( 
             kCTDataConnectionServiceTypeInternet, 
             kCTDataConnectionServiceTypeWirelessModemTraffic, 
             kCTDataConnectionServiceTypeWirelessModemAuthentication 
             ); 
             kCTRegistrationDataContextID = 0; 
             kCTRegistrationDataIndicator = kCTRegistrationDataIndicator3G; 
             kCTRegistrationDataStatus = kCTRegistrationDataStatusAttachedAndActive; 
             kCTRegistrationDataStatusInternationalRoaming = 1; 
             kCTRegistrationRadioAccessTechnology = kCTRegistrationRadioAccessTechnologyUTRAN; 
            */   
        }  
        else if ([notifyname isEqualToString:@"kCTRegistrationCellChangedNotification"])  
        {  
            /* 
             kCTRegistrationGsmCellId = 93204174; 
             kCTRegistrationGsmLac = 55583; 
             kCTRegistrationInHomeCountry = 1; 
             kCTRegistrationRadioAccessTechnology = kCTRegistrationRadioAccessTechnologyUTRAN;  
            */  
        }  
        else if ([notifyname isEqualToString:@"kCTIndicatorRadioTransmitNotification"])  
        {  
            /* 
            kCTRadioTransmitDCHStatus = 1; 
            */   
        }  
        //int unread=CTSMSMessageGetUnreadCount();  
        //if (unread>0)  
            //NSLog(@"未读短信:%d",unread);  
              
        NSLog(@"名字:%@-详细:%@",notifyname,userInfo);  
          
           
    }  
      
    static void signalHandler(int sigraised)    
    {    
        printf("\nInterrupted.\n");    
        exit(0);    

    }   
 

执行

    id ct = CTTelephonyCenterGetDefault();  
        CTTelephonyCenterAddObserver(ct, NULL, callback, NULL, NULL, CFNotificationSuspensionBehaviorHold);  
        // Handle Interrupts    
        sig_t oldHandler = signal(SIGINT, signalHandler);    
        if (oldHandler == SIG_ERR)    
        {    
            printf("Could not establish new signal handler");    
            exit(1);    
        }   
        // Run loop lets me catch notifications    
        printf("Starting run loop and watching for notification.\n");    
        //CFRunLoopRun();   

抱歉!评论已关闭.