iOS脱獄チェックメモ


とりあえずまるごとまとめたもの。
現在いろいろ脱獄端末を用意しつつ検証中


```objc
+(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){
        //Device is jailbroken
        return YES;
    } else {
        [[NSFileManager defaultManager] removeItemAtPath:@"/private/jailbreak.txt" error:nil];
    }
    
    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]){
        //Device is jailbroken
        return YES;
    }
    
    FILE *f = fopen("/bin/bash", "r");
    BOOL isJB = NO;
    if (f != NULL)
    {
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    f = fopen("/bin/ssh", "r");
    if ( f != NULL){
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    f = fopen("/Applications/Cydia.app", "r");
    if (f != NULL)
    {
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    f = fopen("/Library/MobileSubstrate/MobileSubstrate.dylib", "r");
    if (f != NULL)
    {
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    f = fopen("/usr/sbin/sshd", "r");
    if (f != NULL)
    {
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    f = fopen("/etc/apt", "r");
    if (f != NULL)
    {
        //Device is jailbroken
        isJB = YES;
    }
    fclose(f);
    
    if(isJB) return YES;
    
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if([fileManager fileExistsAtPath:@"/private/var/lib/apt/"]){
        //Device is jailbroken
        return YES;
    }
#endif
    
    //All checks have failed. Most probably, the device is not jailbroken
    return NO;
}

```

⇒[How do I detect that an iOS app is running on a jailbroken phone?](http://stackoverflow.com/questions/413242/how-do-i-detect-that-an-ios-app-is-running-on-a-jailbroken-phone)
上記に記載されてたのを全部まとめてみただけのメモです。
脱獄していると中身を書き換えられる場合もあるので、関数名は'isRedColor'とかわからない系にしておくのがいいみたい。

# 検証
検証用コード(それぞれの項目に番号付与)

```objc
+ (BOOL)isJailbroken
{

#if !(TARGET_IPHONE_SIMULATOR)

    if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]) {
//        return YES;
        NSLog(@"1");
    } //else
        if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Library/MobileSubstrate/MobileSubstrate.dylib"]) {
//        return YES;
        NSLog(@"2");
    } //else
        if ([[NSFileManager defaultManager] fileExistsAtPath:@"/bin/bash"]) {
//        return YES;
        NSLog(@"3");
    } //else
        if ([[NSFileManager defaultManager] fileExistsAtPath:@"/usr/sbin/sshd"]) {
//        return YES;
        NSLog(@"4");
    } //else
        if ([[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt"]) {
//        return YES;
        NSLog(@"5");
    }

    NSError *error;
    NSString *stringToBeWritten = @"This is a test.";
    [stringToBeWritten writeToFile:@"/private/jailbreak.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];
    if (error == nil) {
        // Device is jailbroken
//        return YES;
        NSLog(@"6");
    } else {
        [[NSFileManager defaultManager] removeItemAtPath:@"/private/jailbreak.txt" error:nil];
    }

    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]) {
        // Device is jailbroken
//        return YES;
        NSLog(@"7");
    }

    FILE *f = fopen("/bin/bash", "r");
    BOOL isJB = NO;
    if (f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"8");
    }
    fclose(f);
    f = fopen("/bin/ssh", "r");
    if ( f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"9");
    }
    fclose(f);
    f = fopen("/Applications/Cydia.app", "r");
    if (f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"10");
    }
    fclose(f);
    f = fopen("/Library/MobileSubstrate/MobileSubstrate.dylib", "r");
    if (f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"11");
    }
    fclose(f);
    f = fopen("/usr/sbin/sshd", "r");
    if (f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"12");
    }
    fclose(f);
    f = fopen("/etc/apt", "r");
    if (f != NULL) {
        // Device is jailbroken
        isJB = YES;
        NSLog(@"13");
    }
    fclose(f);

    if (isJB) {
//        return YES;
        NSLog(@"14");
    }

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:@"/private/var/lib/apt/"]) {
        // Device is jailbroken
//        return YES;
        NSLog(@"15");
    }
#endif /* if !(TARGET_IPHONE_SIMULATOR) */

    // All checks have failed. Most probably, the device is not jailbroken
    return NO;
}
```

## 7: CydiaのURLスキームチェック

```objc
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]])
```

URLスキームに関しては、脱獄する必要のない通常のアプリのURLスキームに`cydia`が設定されていた場合引っかかるため、一般ユーザーも検知する可能性があるため脱獄チェックには向かない。



# 端末でのチェック結果
## iPhone5S iOS 7.1.2 panguを使っての脱獄直後
BreakThrough⇒脱獄回避アプリ

| 項目 | 脱獄直後 | 脱獄専用アプリインストール | BreakThrough |
|--------|:------:|:------:|:------:|
|   1    |   ◯    |   ◯    |   ×    |
|   2    |   ×    |   ◯    |   ◯    |
|   3    |   ◯    |   ◯    |   ×    |
|   4    |   ×    |   ◯    |   ×    |
|   5    |   ◯    |   ◯    |   ◯    |
|   6    |   ×    |   ×    |   ×    |
|   7    |   ◯    |   ◯    |   ×    |
|   8    |   ◯    |   ◯    |   ×    |
|   9    |   ×    |   ×    |   ×    |
|   10   |   ◯    |   ◯    |   ◯    |
|   11   |   ×    |   ◯    |   ◯    |
|   12   |   ×    |   ◯    |   ◯    |
|   13   |   ◯    |   ◯    |   ◯    |
|   14   |   ◯    |   ◯    |   ◯    |
|   15   |   ◯    |   ◯    |   ×    |