Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running unsigned code in an iOS app to test jailbreak

Tags:

ios

jailbreak

I need a stable way to attempt to run an unsigned executable on an iOS device in order to test if the device has been jailbroken (i.e. allows the running of unsigned code).

I have written a small executable which essentially does nothing.

int main(int argc, char *argv[]) {
    return 23;
}

Which I have compiled and run successfully on an iOS device (both Jailbroken and not).

I have then added this executable to an App bundle and deployed the app to an iOS device.

This results in a read only version of the executable on the device. I attempted to chmod this file to give it execute permissions, but this failed, so I copied it into the tmp directory for the app, where I was able to chmod with executable permissions.

Other questions have suggested using execve to call the executable, but this will replace the running process with the new one, which will kill the app. Fork() always fails, so that is not an option. System() requires a shell, and it would be possible to have a jailbreak without a shell which still allows unsigned code to run, so that's out. Popen() forks, so that won't work.

Interestingly, from what I have discovered, calling execv on my executable in a normal device causes an "Operation not permitted" error, whereas calling it on a jailbroken device causes a "Permission denied" error. This alone would work for jailbreak detection, except for the case that if a jailbreak ever occurs in which the execv is allowed to proceed, the App will then crash immediately as it's process will be replaced.

According to this, iBooks performs jailbreak detection doing this, but it appears to use the fairplayd binary to perform it's execve calls.

Does anyone have any suggestions for either running an executable or using fairplayd?

like image 712
richie Avatar asked Aug 31 '12 10:08

richie


1 Answers

You can't change permissions on the test executable directly, because app resources can't be modified after installing your app. That would be a security hole. So, that's why you need to copy it to a tmp/caches/documents directory, to then make it runnable.

I'm not sure if your app needs to support multitasking, and if you need to detect the jailbreak at the start of the first run, or if it's ok to wait until the app closes. But, if you can turn off multitasking, then you could implement this method (little executable named test in this example):

- (void)applicationWillTerminate:(UIApplication *)application {
    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent: @"test"];
    int result = execlp([path UTF8String], [path UTF8String], NULL);
    // if we got here, then the attempt to run the external process failed, so make a note of this:
    [[NSUserDefaults standardUserDefaults] setValue: [NSNumber numberWithBool: NO] forKey: @"is_jailbroken"];
    NSLog(@"test returns %d", result);
}

If the execlp() call succeeds, then yes, your process will be replaced. But, the process is about to shut down anyway. When I do this, I do not see an actual crash log, so I'm not sure if Apple would complain about this. There's no appearance of crashing to the user.

If you can't exec the separate process, then your app will continue to the line of code that allows you to log the fact that the phone is apparently not jailbroken, which can be noted the next time your app starts.

If you do need to support multitasking, then you could try putting the above code into a multitasking callback like applicationDidEnterBackground:. If the phone is normal, the exec call fails (and returns), so your app will not terminate (exit). I would assume (?) that Apple reviewers don't test your app on jailbroken phones. For those people with jailbroken phones, your app will then exit, instead of going into the background. Maybe that's good enough for your needs?

Also, just FYI, there's other ways to test for a jailbroken system, that are probably pretty reliable (I'm not sure if you want to be able to detect a jailbroken phone 100% of the time, or detect the standard jailbroken configuration)

Determining if an iPhone is Jail broken Programmatically

How do I detect that an iOS app is running on a jailbroken phone?

like image 195
Nate Avatar answered Oct 22 '22 08:10

Nate