はじめに
iOS端末は脱獄(JailBreak)するとappleからの制限を解除する事ができます。
制限が解除されるとアプリ開発者が触れて欲しくない値にもアクセスされる可能性があり、よろしくないです。
このような行為により、チートが発生します。
今回は脱獄端末を検知してみようと思います。
ただ、今回紹介する方法では脱獄検知回避ツールを使われてしまうと簡単に破られます笑
実装
Jailbreak
というフラグを作って脱獄判定を行います
import SwiftUI
struct ContentView: View {
@State var isDeviceJailBroken: Bool = false
var body: some View {
Text(isDeviceJailBroken ? "❌: 脱獄あり" : "✅: 脱獄なし")
}
}
脱獄判定にはこちらの関数を使用します。
// 脱獄判定
func checkDeviceJailBroken() {
if access("/Applications/Cydia.app", F_OK) != -1 ||
access("/Applications/blackra1n.app", F_OK) != -1 ||
access("/Applications/FakeCarrier.app", F_OK) != -1 ||
access("/Applications/Icy.app", F_OK) != -1 ||
access("/Applications/IntelliScreen.app", F_OK) != -1 ||
access("/Applications/MxTube.app", F_OK) != -1 ||
access("/Applications/RockApp.app", F_OK) != -1 ||
access("/Applications/SBSettings.app", F_OK) != -1 ||
access("/Applications/WinterBoard.app", F_OK) != -1 ||
access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/Veency.plist", F_OK) != -1 ||
access("/private/var/lib/apt", F_OK) != -1 ||
access("/private/var/lib/cydia", F_OK) != -1 ||
access("/private/var/mobile/Library/SBSettings/Themes", F_OK) != -1 ||
access("/private/var/stash", F_OK) != -1 ||
access("/private/var/tmp/cydia.log", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.ikey.bbot.plist", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", F_OK) != -1 ||
access("/usr/bin/sshd", F_OK) != -1 ||
access("/usr/libexec/sftp-server", F_OK) != -1 ||
access("/usr/sbin/sshd", F_OK) != -1 ||
access("/bin/bash", F_OK) != -1 ||
access("/etc/apt", F_OK) != -1
{
isDeviceJailBroken = true
} else if let url = URL(string: "cydia://package/com.example.package") {
if UIApplication.shared.canOpenURL(url) {
isDeviceJailBroken = true
} else {
isDeviceJailBroken = false
}
} else {
isDeviceJailBroken = false
}
}
onAppear
で表示時に判定します
import SwiftUI
struct ContentView: View {
@State var isDeviceJailBroken: Bool = false
var body: some View {
Text(isDeviceJailBroken ? "❌: 脱獄あり" : "✅: 脱獄なし")
.onAppear() {
checkDeviceJailBroken()
}
}
// 脱獄判定
func checkDeviceJailBroken() {
if access("/Applications/Cydia.app", F_OK) != -1 ||
access("/Applications/blackra1n.app", F_OK) != -1 ||
access("/Applications/FakeCarrier.app", F_OK) != -1 ||
access("/Applications/Icy.app", F_OK) != -1 ||
access("/Applications/IntelliScreen.app", F_OK) != -1 ||
access("/Applications/MxTube.app", F_OK) != -1 ||
access("/Applications/RockApp.app", F_OK) != -1 ||
access("/Applications/SBSettings.app", F_OK) != -1 ||
access("/Applications/WinterBoard.app", F_OK) != -1 ||
access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/Veency.plist", F_OK) != -1 ||
access("/private/var/lib/apt", F_OK) != -1 ||
access("/private/var/lib/cydia", F_OK) != -1 ||
access("/private/var/mobile/Library/SBSettings/Themes", F_OK) != -1 ||
access("/private/var/stash", F_OK) != -1 ||
access("/private/var/tmp/cydia.log", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.ikey.bbot.plist", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", F_OK) != -1 ||
access("/usr/bin/sshd", F_OK) != -1 ||
access("/usr/libexec/sftp-server", F_OK) != -1 ||
access("/usr/sbin/sshd", F_OK) != -1 ||
access("/bin/bash", F_OK) != -1 ||
access("/etc/apt", F_OK) != -1
{
isDeviceJailBroken = true
} else if let url = URL(string: "cydia://package/com.example.package") {
if UIApplication.shared.canOpenURL(url) {
isDeviceJailBroken = true
} else {
isDeviceJailBroken = false
}
} else {
isDeviceJailBroken = false
}
}
}
これで完成のように思いますが、このままではシュミレーターで実行した際にも脱獄判定されてしまいます。

シュミレーターで実行した際は脱獄判定を行わないように変更します。
シュミレーター判定はこんな感じでできます。
#if !targetEnvironment(simulator)
// 実機のみ実行されます
#endif
こちらをonAppear
に追加します
完成
import SwiftUI
struct ContentView: View {
@State var isDeviceJailBroken: Bool = false
var body: some View {
Text(isDeviceJailBroken ? "❌: 脱獄あり" : "✅: 脱獄なし")
.onAppear() {
#if !targetEnvironment(simulator)
checkDeviceJailBroken()
#endif
}
}
// 脱獄判定
func checkDeviceJailBroken() {
if access("/Applications/Cydia.app", F_OK) != -1 ||
access("/Applications/blackra1n.app", F_OK) != -1 ||
access("/Applications/FakeCarrier.app", F_OK) != -1 ||
access("/Applications/Icy.app", F_OK) != -1 ||
access("/Applications/IntelliScreen.app", F_OK) != -1 ||
access("/Applications/MxTube.app", F_OK) != -1 ||
access("/Applications/RockApp.app", F_OK) != -1 ||
access("/Applications/SBSettings.app", F_OK) != -1 ||
access("/Applications/WinterBoard.app", F_OK) != -1 ||
access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", F_OK) != -1 ||
access("/Library/MobileSubstrate/DynamicLibraries/Veency.plist", F_OK) != -1 ||
access("/private/var/lib/apt", F_OK) != -1 ||
access("/private/var/lib/cydia", F_OK) != -1 ||
access("/private/var/mobile/Library/SBSettings/Themes", F_OK) != -1 ||
access("/private/var/stash", F_OK) != -1 ||
access("/private/var/tmp/cydia.log", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.ikey.bbot.plist", F_OK) != -1 ||
access("/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", F_OK) != -1 ||
access("/usr/bin/sshd", F_OK) != -1 ||
access("/usr/libexec/sftp-server", F_OK) != -1 ||
access("/usr/sbin/sshd", F_OK) != -1 ||
access("/bin/bash", F_OK) != -1 ||
access("/etc/apt", F_OK) != -1
{
isDeviceJailBroken = true
} else if let url = URL(string: "cydia://package/com.example.package") {
if UIApplication.shared.canOpenURL(url) {
isDeviceJailBroken = true
} else {
isDeviceJailBroken = false
}
} else {
isDeviceJailBroken = false
}
}
}
追記(2022/08/17)
以下を設定しないとcanOpenURL(url)
が常にfalseになる事みたいです
Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>cydia</string>
</array>
おわり
今回作成したプロジェクトです