Some common files to check for: /Library/MobileSubstrate/MobileSubstrate.dylib
/Applications/Cydia.app
/var/cache/apt
/var/lib/apt
/var/lib/cydia
/var/log/syslog
/var/tmp/cydia.log
/bin/bash
/bin/sh
/usr/sbin/sshd
/usr/libexec/ssh-keysign
/etc/ssh/sshd_config
/etc/apt
Most check for Cydia related files.
Sample code to check
public static func jailbroken(application: UIApplication) -> Bool {
guard let cydiaUrlScheme = NSURL(string: "cydia://package/com.example.package") else { return isJailbroken() }
return application.canOpenURL(cydiaUrlScheme) || isJailbroken()
}
static func isJailbroken() -> Bool {
if isSimulator {
return false
}
let fileManager = NSFileManager.defaultManager()
if fileManager.fileExistsAtPath("/Applications/Cydia.app") ||
fileManager.fileExistsAtPath("/Library/MobileSubstrate/MobileSubstrate.dylib") ||
fileManager.fileExistsAtPath("/bin/bash") ||
fileManager.fileExistsAtPath("/usr/sbin/sshd") ||
fileManager.fileExistsAtPath("/etc/apt") ||
fileManager.fileExistsAtPath("/usr/bin/ssh") {
return true
}
if canOpen("/Applications/Cydia.app") ||
canOpen("/Library/MobileSubstrate/MobileSubstrate.dylib") ||
canOpen("/bin/bash") ||
canOpen("/usr/sbin/sshd") ||
canOpen("/etc/apt") ||
canOpen("/usr/bin/ssh") {
return true
}
let path = "/private/" + NSUUID().UUIDString
do {
try "anyString".writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
try fileManager.removeItemAtPath(path)
return true
} catch {
return false
}
}
static func canOpen(path: String) -> Bool {
let file = fopen(path, "r")
guard file != nil else { return false }
fclose(file)
return true
}
try this Github link too
Once a device is jailbroken, a lot of other files and applications are installed on the devcice. Checking for these files in the filesystem can help us identify whether the device is jailbroken or not. For e.g, most of the jailbreak softwares install Cydia on the device after jailbreaking. Hence just a simple check for the file path of Cydia can determine whether the device is jailbroken or not.
1
2
3
4
5
|
NSString *filePath = @ "/Applications/Cydia.app" ;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
}
|
However, not all devices that are jailbreaked have Cydia installed on them. In fact, most hackers can just change the location of the Cydia App. Checking for many other files related to Jailbroken devices can make this method much more efficient. For e.g, one can check if Mobile Substrate is installed on the device or not, which many applications require to run on a jailbroken device. One can also check for the location of the SSH Daemon, or the shell interpreter. Combining all these checks, we get a method like this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
+( BOOL )isJailbroken{
if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/Applications/Cydia.app" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/Library/MobileSubstrate/MobileSubstrate.dylib" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/bin/bash" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/usr/sbin/sshd" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/etc/apt" ]){
return YES;
}
return NO;
}
|
We have also learnt from the previous articles that applications that run as a mobile user run in a sandboxed environment and go inside the directory /var/mobile/Applications whereas applications that run with the root user (e.g Apple’s preloaded applications) aren’t subject to any sandbox environment and go inside the directory /Applications. A user running a jailbroken device can install your application in the /Applications folder thereby giving it root privileges. Hence, adding a check to see whether the application follows sandboxing rules can help the user identify whether the application is jailbroken or not. A good way to check for it would be to see if we can modify a file in some other location outside the application bundle.
1
2
3
4
5
6
7
8
9
10
11
|
NSError *error;
NSString *stringToBeWritten = @ "This is a test." ;
[stringToBeWritten writeToFile:@ "/private/jailbreak.txt" atomically:YES
encoding:NSUTF8StringEncoding error:&error];
if (error==nil){
return YES;
} else {
[[NSFileManager defaultManager] removeItemAtPath:@ "/private/jailbreak.txt" error:nil];
}
|
We know that a skilled hacker can just modify the location of the application. However, we know that 80% or more of the devices that are jailbroken have Cydia installed on them, and even if the hacker can change the location of the Cydia app, he most probably won’t change the URL scheme with which the Cydia app is registered. If calling the Cydia’s URL scheme (cydia://) from your application gives a success, you can be sure that the device is jailbroken.
Let’s also add a condition to make sure this code does not execute if we are testing our application on a simulator and not an actual device. After combining all the above techniques, our method looks like this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
+( BOOL )isJailbroken{
#if !(TARGET_IPHONE_SIMULATOR)
if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/Applications/Cydia.app" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/Library/MobileSubstrate/MobileSubstrate.dylib" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/bin/bash" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/usr/sbin/sshd" ]){
return YES;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:@ "/etc/apt" ]){
return YES;
}
NSError *error;
NSString *stringToBeWritten = @ "This is a test." ;
[stringToBeWritten writeToFile:@ "/private/jailbreak.txt" atomically:YES
encoding:NSUTF8StringEncoding error:&error];
if (error==nil){
return YES;
} else {
[[NSFileManager defaultManager] removeItemAtPath:@ "/private/jailbreak.txt" error:nil];
}
return YES;
}
#endif
return NO;
}
|
Honestly speaking, there is no foolproof method of detecting jailbroken devices. A skilled hacker will always find a way to bypass these checks. He can simply find the instructions in the binary and replace all instructions with No-op. He can also swizzle your method implementation with his own using Cycript.
No comments:
Post a Comment