iOS 越狱隐藏:从 Dopamine 到 RootHide
内容提要
本文分析 RootHide 越狱隐藏机制。原版 Dopamine 固定 /var/jb 路径且全进程注入,易被检测。RootHide 通过随机 jbroot 路径、iOS 沙盒阻止枚举、选择性注入三重防护实现隐藏:黑名单 App 走原版 posix_spawn,不注入 dylib、不 hook 函数,进程空间完全干净;路径翻译在用户态完成,无需 bind mount。结论是黑名单进程内检测越狱结构性不可行,防线应移至服务端风控与行为分析。
延伸解读
RootHide 的隐藏逻辑:让不同进程看到不同世界
RootHide 的核心思路不是把越狱痕迹彻底抹掉,而是让被注入的进程和未被注入的进程看到不同的系统环境。被注入的进程(如系统级 mediaserverd)能看到越狱环境、tweak 生效、路径被翻译;未被注入的进程(如银行 App)则看到完全正常的系统,没有 hook、没有越狱文件。两者运行在同一内核上,但用户态环境被隔离。这种设计让越狱用户既能正常使用敏感 App,又能保留系统级定制功能。
三重防护如何让黑名单 App 进程内检测失效
RootHide 通过随机 jbroot 路径、iOS 沙盒阻止枚举、选择性注入三重机制协同实现隐藏。jbroot 目录名包含 64 位随机值且每次越狱重新生成,普通 App 无法枚举父目录发现它;黑名单 App 走原版 posix_spawn,不注入 dylib、不 hook 函数,进程空间完全干净。因此,黑名单进程内不存在可观测的越狱差异,检测越狱在进程内结构性不可行,防线应移至服务端风控与行为分析。
默认配置与黑名单:用户需主动配置才生效
RootHide 的注入决策由 isBlacklistedPath() 做出,它检查用户手动配置的 RootHideConfig.plist。配置文件不存在时返回 false,意味着默认所有进程(包括 App Store 应用)都会被注入 systemhook。只有用户在 RootHide 管理器中手动将 App 加入黑名单后,该 App 及其扩展进程才走原版 posix_spawn,不被注入。因此,抗越狱检测能力需要用户主动配置,并非开箱即用。
内核级修改仍全局可见,但沙盒限制观测
RootHide 在用户态做了大量隐藏工作,但部分修改是内核级、全局生效的,例如 sysctl OID 交换隐藏 developer_mode_status、Trust Cache 修改允许未签名代码执行、AMFI patch 放宽签名验证。这些修改理论上可被检测,但 iOS 沙盒限制了普通 App 的观测能力,实测 opendir 和 KERN_PROC 均返回 EPERM。因此,全局状态虽存在,但普通 App 无法直接观测,进一步强化了隐藏效果。
Q&A
RootHide 和原版 Dopamine 是同一个项目吗?
不是。原版 Dopamine 由 opa334 开发,使用固定 /var/jb 路径且全进程注入,不做任何隐藏;RootHide 是 roothide 团队对 Dopamine 2.x 的魔改 fork,实现了随机 jbroot、选择性注入和用户态路径翻译等隐藏机制。
RootHide 是如何隐藏越狱痕迹的?
RootHide 通过三重防护实现隐藏:1) 随机 jbroot 路径,每次越狱生成 64 位随机目录名;2) 利用 iOS 沙盒阻止 App 枚举父目录发现 .jbroot-*;3) 选择性注入,黑名单 App 走原版 posix_spawn,不注入 dylib、不 hook 函数,进程空间完全干净。
为什么黑名单 App 无法在进程内检测到 RootHide 越狱?
因为黑名单 App 的进程空间完全干净:不注入 dylib、不 hook 函数、csflags 与正常进程一致;jbs 协议、mach-lookup 等旁路按 audit token 排除黑名单进程;jbroot 目录和 mount 表虽存在,但 iOS 沙盒不允许普通 App 观测。因此可观测差异不存在,进程内检测结构性不可行。
RootHide 的路径翻译是怎么工作的?
对于被注入的进程,systemhook 拦截 open、access、stat 等文件系统 API,判断路径是否需要翻译,将 jbroot 路径翻译为真实路径后调用原始函数;对于未被注入的进程,没有 systemhook,直接走真实系统调用,访问越狱文件会返回 ENOENT,与正常设备一致。
RootHide 的黑名单是如何配置和生效的?
黑名单由用户在 RootHide 管理器中手动配置,存储在 RootHideConfig.plist 的 appconfig 字典中。注入决策由 isBlacklistedPath() 做出:配置文件不存在时默认所有 App 都被注入;用户手动添加某 App 后,该 App 及其扩展进程走原版 posix_spawn,不注入 systemhook。
RootHide 做了哪些内核级修改?
RootHide 的内核级修改包括:1) sysctl OID 交换,隐藏 developer_mode_status(仅 iOS 16.0+);2) 修改 Trust Cache,允许未签名代码执行;3) AMFI patch,放宽代码签名验证。这些修改全局生效,但用户态隐藏主要依靠选择性注入和路径翻译。
既然进程内检测不可行,防御方应该怎么做?
文章结论指出,对于被 RootHide 黑名单的 App,进程内检测越狱已结构性不可行,防线应移至服务端风控与行为分析,例如通过服务端检测异常行为模式,而不是依赖客户端本地检测。