How to call iOS7 [jailbreak] from the application?



I had a task to call from iPhone to iOS7. On previous versions of iOS (6 and earlier), it was enough to use the private API and everything worked, but on iOS7 this approach stopped working. In this post I want to tell how to make a call and get my own phone number from the application.

Project code on github .

Jailbreak


The first thing that everything works is to do a Jailbreak. For the latest version of iOS 7.1.2, it is perfectly done using en.pangu.io - jailbreak tool You can see the jalibreak instructions here , for example . I did this with iPhone4, iOS 7.1.2 on Windows 8.1. After jailbreak is done, install OpenSSH via Cydia.



We go on the iPhone via ssh and change the password for root [default password: alpine]
$ssh root@10.231.65.56
$passwd


The phone is ready. Prepare the application that will ring. In the application, we will use the following private APIs:

void        CTCallListDisconnectAll();      // for ending call  header: CTCall.h
CTCallRef   CTCallDial(CFStringRef number); // for calling header: CTCall.h
CFStringRef CTSettingCopyMyPhoneNumber();   // for getting own number header: CTSetting.h

The header files CTCall.h, CTSetting.h can be found in the repository on GitHub.

Now let's look at a code that works without problems on iOS 6.1.4 and without jailbreak.

Call start method

- (IBAction)onPlaceCall:(id)sender {
    NSString *numberToCall = [self.tfNumberToCall text];
    NSLog(@"Open CoreTelephony");
    void *ptrCoreTelephone = dlopen("/System/Library/Framework/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
    if (ptrCoreTelephone == nil){
        NSLog(@"ptrCoreTelephone is nil");
        return;
    }
    NSLog(@"Get CTCallDial from CoreTelephony");
    int (*pCTCallDial)(NSString*) = dlsym(ptrCoreTelephone, "CTCallDial");
    if (pCTCallDial != nil) {
        int error = pCTCallDial(numberToCall);
        NSLog(@"pCTCallDial error: %d", error);
    }
    NSLog(@"Close CoreTelephony");
    dlclose(ptrCoreTelephone);
}

Wrap Interrupt Method

- (IBAction)onStopCall:(id)sender {
    NSLog(@"onStopCall");
    void *ptrCoreTelephone = dlopen("/System/Library/Framework/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
    if (ptrCoreTelephone == nil){
        NSLog(@"ptrCoreTelephone is nil");
        return;
    }
    NSLog(@"Get CTCallListDisconnectAll from CoreTelephony");
    int (*pCTCallListDisconnectAll)() = dlsym(ptrCoreTelephone,
            "CTCallListDisconnectAll");
    if (pCTCallListDisconnectAll != nil) {
        int error = pCTCallListDisconnectAll();
        NSLog(@"pCTCallListDisconnectAll error: %d", error);
    }
    dlclose(ptrCoreTelephone);
}

Number Method

-(NSString*) getMyNumber {
    NSLog(@"Open CoreTelephony");
    void *lib = dlopen("/Symbols/System/Library/Framework/CoreTelephony.framework/CoreTelephony",RTLD_LAZY);
    NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
    NSString* (*pCTSettingCopyMyPhoneNumber)() = dlsym(lib, "CTSettingCopyMyPhoneNumber");
    NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
    if (pCTSettingCopyMyPhoneNumber == nil) {
        NSLog(@"pCTSettingCopyMyPhoneNumber is nil");
        return nil;
    }
    NSString* ownPhoneNumber = pCTSettingCopyMyPhoneNumber();
    dlclose(lib);
    return ownPhoneNumber;
}


Now the fun part. The same code will work on iOS7 if you add entitlements to the application and re-sign it with these entitlements. To do this, do the following.

  • Build an application without a signature
  • Prepare and attach the application xml file with entitlements
  • Sign the application and put on the phone


Build an application without a signature

For this, you need to set the following in Xcode in Build Settings:

P

Then run the assembly.

Preparing an xml file with entitlements

You need to create a file with the following contents:
com.apple.coretelephony.Calls.allowcom.apple.coretelephony.Identity.get


com.apple.coretelephony.Calls.allow - for calls
com.apple.coretelephony.Identity.get - to get the number
Put it in the same place from where the signature command will be launched.

Signature and Installation

To sign, we need a folder with binaries. To understand where Xcode puts them, you can run the command:
$ls -la ~/Library/Developer/Xcode/DerivedData/ | grep JBCall


The path would be something like this:
/Users/username/Library/Developer/Xcode/DerivedData/JBCall-cktasembftvbmqaaiiunvljdwocs/Build/Products/Debug-iphoneos/JBCall.app


Copy JBCall.app to a separate folder, put entitlements.xml next to it:
JBCall.app
entitlements.xml


Now you need to sign the binaries with the following command:
$codesign --sign='iPhone Developer: FirstName  SecondName (XXXXXXXX)’ --entitlements entitlements.xml JBCall.app


iPhone Developer: FirstName SecondName (XXXXXXXX) - the name of the certificate, which can be viewed in keychain.


After the actions done, you can install the application and use. In this case, the installation consists of copying the * .app folder to the iPhone and restarting SpringBoard. I did this via scp in the script:

DST_DIR='/Applications'
APP_NAME='JBCall.app'
USER='root'
PASSWD='mypass'
IP='10.231.65.56'
APP_ON_MAC="/Users/username/Library/Developer/Xcode/DerivedData/JBCall-cktasembftvbmqaaiiunvljdwocs/Build/Products/Debug-iphoneos/JBCall.app"
sshpass -p $PASSWD scp -r $APP_NAME $USER@$IP:$DST_DIR


In the script, you need to change only the values ​​of variables for yourself and you can run it. The path also needs to be updated:

/ Users / username / Library / Developer / Xcode / DerivedData / JBCall-cktasembftvbmqaaiiunvljdwocs /Build/Products/Debug-iphoneos/JBCall.app

Restarting SpringBoard:
$sshpass -p $PASSWD ssh $USER@$IP su mobile -c uicache 1>/dev/null 2>&1


Separate restart command from the device:
$su mobile -c uicache 1>/dev/null 2>&1

Of course sshpass and scp must be installed.

All the described installation actions are arranged in the form of a script.
Everything, now the application can make calls, hang up, show the phone number.

Screenshots from iOS 6.1.4


Screenshots from iOS 7.1.2


Total


As a result, we got an application that calls on the latest version of iOS with jailbreak. I hope someone comes in handy this experience.

How did I find out about entitlements?


Thanks to the creker user on stackoverflow for the tip about entitlements that he found in the file:
/System/Library/CoreServices/SpringBoard.app/SpringBoard

Indeed, looking at the binary you can find the text lines:
com.apple.coretelephony.Calls.allow
com. apple.coretelephony.Identity.get




References



Also popular now: