1
0

iOS脱獄(Jailbreak)検知機能の実装

Posted at

はじめに

この文書では、iOSデバイスが脱獄(Jailbreak)されているかどうかを判断するSwiftクラスJailbreakCheckerについて解説します。
このクラスは、いくつかの方法を用いてデバイスが脱獄(Jailbreak)されているかをチェックします。

機能概要

JailbreakCheckerクラスは以下の機能を提供します:

  1. シミュレーターのチェック - デバイスがシミュレーターかどうかを判断します。
  2. Cydiaのインストールチェック - CydiaアプリがインストールされているかをURIスキームを用いて判断します。
  3. 怪しいパスの存在チェック - 脱獄(Jailbreak)されたデバイスに特有のファイルパスが存在するかをチェックします。
  4. システムファイルの編集権限チェック - アプリがシステムファイルを編集できるかどうかをテストします。

実装詳細

1. シミュレーターのチェック

private static var isSimulator: Bool {
    return TARGET_OS_SIMULATOR != 0
}

このメソッドは、デバイスがシミュレーターかどうかを確認します。

2. Cydiaのインストールチェック

private static func hasCydiaInstalled() -> Bool {
    if let url = URL(string: "cydia://package/com.example.package"), UIApplication.shared.canOpenURL(url) {
        return true
    }
    return false
}

Cydiaアプリがインストールされているかを、URIスキームを用いてチェックします。

3. 怪しいパスの存在チェック

private static func isSuspiciousPathExists() -> Bool {
    for path in suspiciousPathsToCheck where FileManager.default.fileExists(atPath: path) {
        return true
    }
    return false
}

特定のパスが存在するかどうかをチェックし、それによって脱獄(Jailbreak)の状態を判断します。

怪しいパス

脱獄(Jailbreak)されたデバイスでは、以下のような特定のパスが存在することがあります:

// Path list url: https://github.com/OWASP/owasp-mastg/blob/master/Document/0x06j-Testing-Resiliency-Against-Reverse-Engineering.md
static var suspiciousPathsToCheck: [String] {
    return ["/Applications/Cydia.app",
            "/Applications/FakeCarrier.app",
            "/Applications/Icy.app",
            "/Applications/IntelliScreen.app",
            "/Applications/MxTube.app",
            "/Applications/RockApp.app",
            "/Applications/SBSettings.app",
            "/Applications/WinterBoard.app",
            "/Applications/blackra1n.app",
            "/Library/MobileSubstrate/MobileSubstrate.dylib",
            "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
            "/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
            "/Library/MobileSubstrate/MobileSubstrate.dylib",
            "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
            "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
            "/bin/bash",
            "/bin/sh",
            "/etc/apt",
            "/etc/ssh/sshd_config",
            "/private/var/lib/apt",
            "/private/var/lib/cydia",
            "/private/var/mobile/Library/SBSettings/Themes",
            "/private/var/stash",
            "/private/var/tmp/cydia.log",
            "/var/tmp/cydia.log",
            "/usr/bin/sshd",
            "/usr/libexec/sftp-server",
            "/usr/libexec/ssh-keysign",
            "/usr/sbin/sshd",
            "/var/cache/apt",
            "/var/lib/apt",
            "/var/lib/cydia",
            "/usr/sbin/frida-server",
            "/usr/bin/cycript",
            "/usr/local/bin/cycript",
            "/usr/lib/libcycript.dylib",
            "/var/log/syslog"]
}

これらのパスの存在をチェックすることで、脱獄(Jailbreak)の有無をより確実に判断することができます。

4. システムファイルの編集権限チェック

private static func canEditSystemFiles() -> Bool {
    do {
        let pathToFileInRestrictedDirectory = "/private/jailbreak.txt"
        try "This is a test.".write(toFile: pathToFileInRestrictedDirectory, atomically: true, encoding: String.Encoding.utf8)
        try FileManager.default.removeItem(atPath: pathToFileInRestrictedDirectory)
        return true
    } catch {
        return false
    }
}

このメソッドは、アプリがシステムレベルのファイルを編集できるかをテストします。これが可能な場合、デバイスは脱獄(Jailbreak)されている可能性が高いです。

全体像

class JailbreakChecker {
    // Check if the device is jailbroken
    static var isJailBroken: Bool {
        if JailbreakChecker.isSimulator { return false }
        if JailbreakChecker.hasCydiaInstalled() { return true }
        if JailbreakChecker.isSuspiciousPathExists() { return true }
        return JailbreakChecker.canEditSystemFiles()
    }

    // Check if the device is a simulator
    private static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }

    // Check if Cydia is installed (using URI Scheme)
    private static func hasCydiaInstalled() -> Bool {
        if let url = URL(string: "cydia://package/com.example.package"), UIApplication.shared.canOpenURL(url) {
            return true
        }
        return false
    }

    // Check if suspicious path exists
    private static func isSuspiciousPathExists() -> Bool {
        for path in suspiciousPathsToCheck where FileManager.default.fileExists(atPath: path) {
            return true
        }
        return false
    }

    // Check if the app can edit system files
    private static func canEditSystemFiles() -> Bool {
        do {
            let pathToFileInRestrictedDirectory = "/private/jailbreak.txt"
            try "This is a test.".write(toFile: pathToFileInRestrictedDirectory, atomically: true, encoding: String.Encoding.utf8)
            try FileManager.default.removeItem(atPath: pathToFileInRestrictedDirectory)
            return true
        } catch {
            return false
        }
    }

    // suspicious paths to check
    // Path list url: https://github.com/OWASP/owasp-mastg/blob/master/Document/0x06j-Testing-Resiliency-Against-Reverse-Engineering.md
    static var suspiciousPathsToCheck: [String] {
        return ["/Applications/Cydia.app",
                "/Applications/FakeCarrier.app",
                "/Applications/Icy.app",
                "/Applications/IntelliScreen.app",
                "/Applications/MxTube.app",
                "/Applications/RockApp.app",
                "/Applications/SBSettings.app",
                "/Applications/WinterBoard.app",
                "/Applications/blackra1n.app",
                "/Library/MobileSubstrate/MobileSubstrate.dylib",
                "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
                "/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
                "/Library/MobileSubstrate/MobileSubstrate.dylib",
                "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
                "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
                "/bin/bash",
                "/bin/sh",
                "/etc/apt",
                "/etc/ssh/sshd_config",
                "/private/var/lib/apt",
                "/private/var/lib/cydia",
                "/private/var/mobile/Library/SBSettings/Themes",
                "/private/var/stash",
                "/private/var/tmp/cydia.log",
                "/var/tmp/cydia.log",
                "/usr/bin/sshd",
                "/usr/libexec/sftp-server",
                "/usr/libexec/ssh-keysign",
                "/usr/sbin/sshd",
                "/var/cache/apt",
                "/var/lib/apt",
                "/var/lib/cydia",
                "/usr/sbin/frida-server",
                "/usr/bin/cycript",
                "/usr/local/bin/cycript",
                "/usr/lib/libcycript.dylib",
                "/var/log/syslog"]
    }
}

使用方法

if JailbreakChecker.isJailBroken {
    // Do something
}

このクラスを使用して、アプリが脱獄(Jailbreak)されたデバイス上で実行されているかどうかを判定できます。例えば、アプリの初期化時にJailbreakChecker.isJailBrokenをチェックして、脱獄(Jailbreak)されている場合は特定の処理を行うことができます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0