App with jailbreak detection rejected by Apple
app-store, ios, jailbreak, objective-c
Solution
From https://www.theiphonewiki.com/wiki/Bypassing_Jailbreak_Detection
While there are countless ways apps can implement checks for jailbroken devices, they typically boil down to the following: Existence of directories - Check your file system for paths like `/Applications/Cydia.app/` and `/private/var/stash`, amongst a handful of others. Most often, these are checked using the `-(BOOL)fileExistsAtPath:(NSString*)path` method in `NSFileManager`, but more sneaky apps like to use lower-level C functions like `fopen()`, `stat()`, or `access()`. Directory permissions - Check the Unix file permissions of specific files and directories using `NSFileManager` methods as well as C functions like `statfs()`. Far more directories have write access on a jailbroken device than on one still in jail. Process forking - `sandboxd` does not deny App Store applications the ability to use `fork()`, `popen()`, or any other C functions to create child processes on non-jailbroken devices. `sandboxd` explicitly denies process forking on devices in jail. if you check the returned pid on `fork()`, your app can tell if it has successfully forked or not, at which point it can determine a device's jailbreak status. SSH loopback connections* - Due to the large portion of jailbroken devices that have OpenSSH installed, some apps will attempt to connect to 127.0.0.1 on port 22. If the connection succeeds, it means OpenSSH is installed and running on the device, therefore it is jailbroken. system() - Calling the `system()` function with a NULL argument on a device in jail will return 0; doing the same on a jailbroken device will return 1. This is since the function will check whether `/bin/sh` exists, and this is only the case on jailbroken devices.[1] dyld functions - By far the hardest to get around. Calling functions like `_dyld_image_count()` and `_dyld_get_image_name()` to see which dylibs are currently loaded. Very difficult to patch, as patches are themselves part of `dylibs`. *Only a very small number of applications implement this (as it is not nearly as effective as the others)
These methods seem like they would be less likely to be rejected by apple and are very simple to use.
The above passage has been edited for brevity
Problem
the App we are working on was rejected because the Device in the Review Process was detected as jailbroken ^^ To detect a jailbroken Device, several Tests were performed: ``` NSString* bundlePath = [[NSBundle mainBundle] bundlePath]; // scan for itunes metadata BOOL isDirectory = NO; NSString* directoryPath = [bundlePath stringByAppendingPathComponent:@"SC_Info/"]; BOOL directoryIsAvailable = [[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:&isDirectory]; BOOL contentSeemsValid = ([[[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:NULL] count] == 2); if (directoryIsAvailable && contentSeemsValid) { return YES; } contentSeemsValid = [[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/iTunesMetadata.plist", bundlePath]]; if (contentSeemsValid) { return YES; } // scan for cydia app NSURL* testURL = [NSURL URLWithString:@"cydia://"]; if ([[UIApplication sharedApplication] canOpenURL:testURL]) { return YES; } // scan for paths available NSArray* paths = @[@"/Applications/Cydia.app", @"/Applications/RockApp.app", @"/Applications/Icy.app", @"/usr/sbin/sshd", @"/usr/bin/sshd", @"/private/var/lib/apt", @"/private/var/lib/cydia", @"/private/var/stash", @"/usr/libexec/sftp-server"]; for (NSString* string in paths) { if ([[NSFileManager defaultManager] fileExistsAtPath:string]) { return YES; } } // scan for forking int forkValue = fork(); if (forkValue >= 0) { return YES; } // try to write in private space NSString* testString = @"test"; NSError* error = nil; [testString writeToFile:@"/private/test.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (error == nil) { return YES; } // seems not jailbroken return NO; ``` One (or more) of these Tests return YES on the Devices Apple use for Review, but none of our DevDevices. Which one could it be? Does anybody know more Details about the Devices Apple use for the Review? Any Hints or other Guesses? (The Context from the App is HealthCare in Hospitals, so we need to be sure that the Patient Data were save) Best Regards, Zeek