如何判断设备是否越狱?

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

iPhone 越狱已经不是什么新鲜事,但是越狱之后意味着已经拿到了系统的所有权限,继续在越狱的设备上运行你的程序也就意味着不再安全,因此目前很多主流的 App 都是禁止运行在此类设备上的。

但是怎么判断一个设备是否为越狱的机器呢?今天就来讲讲我所知道的一些方法。

方法一

检查手机上是否安装了 Cydia ,玩越狱的同学肯定都清楚,这个 app 堪称是越狱系统的 App Store,上边可以安装各种正规 App Store 安装不到的软件。Cydia 上除了独立的应用程序之外,更多的包是 iOS 本身和应用程序的扩展、修改和主题。

因此可以说只要是越狱的设备,都会安装这个应用,那我们只需要检测这个应用存不存在就行了。

这里主要用到的方法是用 canOpenURL 是否能打开 cydia:// 这个 URL Scheme。

csharp 复制代码
func isJailBreak() -> Bool {
    return UIApplication.shared.canOpenURL(URL(string: "cydia://")!)
}

这里记得把 cydia 加入到 info.plist 中的 LSApplicationQueriesSchemes 字段里才能正常检测应用是否安装

这种方式简单粗暴,不过不建议用,因为准确度可能不高,一方面 cydia 可能把这个 URL Scheme 改掉防止你检测。另一方面正常手机也可能会有一个 app 的 URL Scheme 叫这个名字,造成误判。

方法二

检测是否存在 MobileSubstrate 动态库,这个库是 cydia 的基石,越狱环境下安装绝大部分插件,必须要有 MobileSubstrate,因此我们只需要判断是否存在这个动态库即可。

我在网上找了一个 c 语言的实现:

arduino 复制代码
bool
isJailBreak(void)
{
    const char *const imageName = "MobileSubstrate";
    if (imageName != NULL) {
        const uint32_t imageCount = _dyld_image_count();
        for (uint32_t iImg = 0; iImg < imageCount; iImg++) {
            const char *name = _dyld_get_image_name(iImg);
            if (strstr(name, imageName) != NULL) {
                return true;
            }
        }
    }
    return false;
}

方法三

还是检测文件,如果越狱的话,设备会创建许多文件,可以使用 FileManager 来检测这些文件是否存在:

csharp 复制代码
func isJailBreak() -> Bool {
#if targetEnvironment(simulator)
    return false
#else
    let files = [
        "/private/var/lib/apt",
        "/Applications/Cydia.app",
        "/Applications/RockApp.app",
        "/Applications/Icy.app",
        "/Applications/WinterBoard.app",
        "/Applications/SBSetttings.app",
        "/Applications/blackra1n.app",
        "/Applications/IntelliScreen.app",
        "/Applications/Snoop-itConfig.app",
        "/bin/sh",
        "/usr/libexec/sftp-server",
        "/usr/libexec/ssh-keysign /Library/MobileSubstrate/MobileSubstrate.dylib",
        "/bin/bash",
        "/usr/sbin/sshd",
        "/etc/apt /System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
        "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
        "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
        "/Library/MobileSubstrate/DynamicLibraries/Veency.plist"
    ]
    return files.contains(where: {
        return FileManager.default.fileExists(atPath: $0)
    })
#endif
}

这里有个条件编译,在模拟器下是不需要检查的。

方法四

越狱之后所有 App 都被授予 root 权限,并且可以修改沙箱之外的文件。利用这个特点,如果我们的 App 可以写入其沙箱之外的文件,则证明该设备已越狱:

php 复制代码
func isJailBreak() -> Bool {
    let string = "iOS 新知"
    do {
        try string.write(to: URL(filePath: "/private/myfile.txt"), atomically: true, encoding: .utf8)
        return true
    } catch {
        return false
    }
}

方法五

越狱之后也就意味着 App 可以随意调用系统 API 了,因此我们可以尝试调用系统 API,来查看是否能得到正确结果,以此来判断是否越狱:

swift 复制代码
func isJailBreak() -> Bool {
    let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
    let forkPtr = dlsym(RTLD_DEFAULT, "fork")
    typealias ForkType = @convention(c) () -> Int32
    let fork = unsafeBitCast(forkPtr, to: ForkType.self)

    return fork() != -1
}

建议以上五种方法结合使用,提高检测的准确率

检测到越狱设备,禁止使用

如果检测到当前运行环境为越狱设备,可以强制退出 App,以确保安全。强制退出 app 的方法就很多了,可以使用 exit(-1),也可以人为做个数组越界之类的:

scss 复制代码
// 检测到越狱设备
if isJailBreak() {
    // 退出 app
    exit(-1)
    // 或者数组越界 crash
    // [0][1]
}

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
程序猿看视界3 小时前
如何在 UniApp 中实现 iOS 版本更新检测
ios·uniapp·版本更新
dr李四维6 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
️ 邪神6 小时前
【Android、IOS、Flutter、鸿蒙、ReactNative 】自定义View
flutter·ios·鸿蒙·reactnative·anroid
比格丽巴格丽抱18 小时前
flutter项目苹果编译运行打包上线
flutter·ios
网络安全-老纪19 小时前
iOS应用网络安全之HTTPS
web安全·ios·https
今天啥也没干21 小时前
使用 Sparkle 实现 macOS 应用自定义更新弹窗
前端·javascript·swift
1024小神1 天前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
lzhdim1 天前
iPhone 17 Air看点汇总:薄至6mm 刷新苹果轻薄纪录
ios·iphone
安和昂1 天前
【iOS】知乎日报第四周总结
ios
yngsqq1 天前
037集——JoinEntities连接多段线polyline和圆弧arc(CAD—C#二次开发入门)
开发语言·c#·swift