Jamf威胁实验室发布迄今最完整的Predator iOS内核利用分析报告。此前Jamf已陆续披露Predator的反分析机制和录屏指示器绕过,参见:iPhone隐私指示灯成摆设?Predator间谍软件通过Hook完美隐身,但"它究竟如何获取内核级权限",直到这篇报告才有了答案。
iOS的安全防线
和其他平台拿到了初始权限就基本等于拿到了系统权限不同。Predator还必须同时突破iOS的两大安全机制:指针认证码(PAC)和内核地址空间布局随机化(KASLR)。
PAC是苹果2018年随A12芯片推出的硬件安全特性,为所有代码指针添加加密签名。处理器在执行函数调用或返回前会验证签名,任何指针篡改都会导致异常。
KASLR则在每次设备启动时随机化内核基地址,使攻击者无法预先定位需要修改的内核数据结构。
看上去已经无懈可击了?
七大关键技术发现
FDGuardNeonRW:用ARM向量寄存器做内核读写通道
FDGuardNeonRW是Predator最核心的创新,它将ARMNEON向量寄存器重新用作内核与用户空间之间的隐蔽数据传输通道。
NEON是ARM架构的SIMD(单指令多数据)扩展,包含32个128位向量寄存器(V0-V31),原本用于加速多媒体和数学运算。这些寄存器是线程上下文的一部分,内核在上下文切换时会自动保存和恢复它们的状态。
Predator利用Mach系统的thread_get_state和thread_set_stateAPI,通过异常处理机制读写这些寄存器。每次调用可传输528字节数据(包括FPSR、FPCR和对齐填充),比传统通用寄存器通道的272字节容量提高了近一倍。

这种方法的优势在于:NEON状态是内核标准线程管理的一部分,无需修改内核调度逻辑;双向传输使用同一机制;异常消息中包含完整的寄存器状态,无需额外数据结构。这个侧信道思路相当精妙。攻击者深刻理解iOS内核的上下文切换机制。
JavaScriptCore中的PAC绕过:借用苹果自身代码
为了安装系统钩子,Predator需要修改函数指针,但这些指针都带有PAC签名。Predator没有实现自己的签名算法,而是在苹果的JavaScriptCore框架中寻找可被滥用的现有代码序列。

Predator搜索JSC::JSArrayBuffer::isShared()函数周围1000字节的内存,寻找一个特定的20字节指令序列。这个序列的核心是PACIAX16,X17指令,它使用硬件PAC密钥对X16寄存器中的指针进行签名,X17作为上下文鉴别器。

通过控制这两个寄存器的值,Predator可以为任意指针生成有效的PAC签名。这种方法的巧妙之处在于它完全使用苹果签名的代码,不需要引入任何恶意的可执行代码。
256项PAC签名缓存:消除加密延迟
每次调用远程PAC签名操作需要创建线程、设置异常端口、修改内核状态和接收结果,耗时数毫秒。这对于需要在微秒级完成的钩子回调来说太慢了。
Predator的解决方案是在初始化阶段预计算一个包含256个签名指针的缓存,覆盖地址所有可能的最高字节值。当钩子触发时,即可获得正确签名的指针,无需实时计算。

构建完整缓存需要512次远程PAC调用(256×2),但这只在每个函数目标上执行一次。所有后续的钩子回调都是即时的缓存查找。
callFunc:基于Mach异常的远程函数执行框架
callFunc是Predator在远程进程中执行任意函数的主要机制,它将PAC缓存、Mach异常和线程状态操纵整合为一个可调用的原语,支持最多6个参数(x0-x5)。
其工作原理是在远程进程中植入一个"木马线程",该线程持续在断点处生成Mach异常。当需要执行远程函数时:
-
Predator捕获异常消息
-
填充参数寄存器(x0-x5)
-
从PAC缓存中查找正确签名的PC和LR
-
发送包含修改后线程状态的异常回复
-
内核交付回复,木马线程在指定参数下执行目标函数
-
"污染"的LR指向另一个断点,函数返回时重新生成异常,Predator重新获得控制权
这种机制创建了一个可无限重用的远程过程调用通道。代码中的日志字符串"TaskROPDevOff.h"证实这是一种为未启用开发者模式的设备设计的ROP技术。

RWTransfer:跨进程共享内核读写
Predator采用模块化架构,由一个"观察者"进程管理生命周期,多个"助手"进程执行具体的监控任务。只有观察者进程通过初始漏洞获得了内核读写权限,助手进程也需要这种权限才能执行监控操作。

RWTransfer机制解决了这个问题,它通过以下步骤在进程间传递内核读写能力: -观察者使用FDGuardNeonRW遍历内核链表 -找到助手进程的任务结构 -定位助手进程的IPC空间和特定端口条目 -修改内核数据结构,将受保护的文件描述符和Mach端口权限转移给助手
这是Predator中最复杂的组件之一,需要同时操纵Mach端口、文件描述符、内核链表和线程状态。
远程Objective-C方法解析
当Predator需要挂钩远程进程中的Objective-C方法时,不能依赖本地运行时查询。虽然dyld共享缓存中的方法在同一启动的所有进程中映射到相同地址,但应用程序特定二进制文件中的方法会受到每个进程独立的ASLR偏移影响。

Predator的解决方案是使用callFunc远程执行完整的Objective-C运行时解析链。 所有这些步骤都在远程进程上下文中执行,确保即使对于共享缓存之外的方法也能获得正确的地址。
设备支持矩阵:5个类别21款机型
由于不同iPhone型号的SoC代际、安全特性和内核构建差异,内核结构布局各不相同。Predator维护了按设备类别划分的精确内核偏移配置表。
|
设备类别 |
SoC芯片 |
支持机型 |
数量 |
|---|---|---|---|
|
0 |
A12/A12X/A12Z |
iPhoneXS/XSMax/XR,iPadPro2018 |
5 |
|
1 |
A13 |
iPhone11/11Pro/11ProMax |
3 |
|
3 |
A14 |
iPhone12/12mini/12Pro/12ProMax |
4 |
|
4 |
A15/A16 |
iPhone13系列,iPhone14/14Plus/14Pro/14ProMax |
9 |
总计支持21款iPhone机型,覆盖2018-2022年发布的硬件。设备类别2在本次分析的样本中未使用,可能保留给特定硬件修订版或已与其他类别合并。对于不支持的设备,函数返回错误码5,安全终止执行以避免内核崩溃。
设备识别通过XOR编码的字符串比较实现。代码中的十六进制常量实际上是XOR编码的设备标识符(如"iPhone15,3"对应iPhone14ProMax),增加了静态分析的难度。
Predator攻击链回顾

Predator的后利用链是一个严格的流水线,每个阶段都依赖于前一个阶段的成功:
-
初始利用(CVE-2023-41993)
-
内核读写:突破用户态限制,获得读写内核内存的能力
-
绕过PAC
-
远程执行
-
能力转移
-
监控:控制SpringBoard可以禁用麦克风、摄像头访问的可视指示器;控制mediaserverd则可以监听摄像头。
每个阶段都有完善的错误处理,任一失败即中止整个攻击链。
后续,苹果在A15及以上芯片中引入了SPTM(安全页表监视器)。通过将页表管理移至更高特权级别的EL2,即使攻击者获得了内核(EL1)执行权限,也无法直接修改页表来获得任意内存访问。

不过最有效的防御措施仍然是及时更新操作系统。本次的攻击链在iOS17及以上版本中不再有效,因为苹果已经修复了Predator使用的初始漏洞,并引入了额外的内核保护机制。
参考资料:InsidePredator"skernelenginehttps://www.jamf.com/blog/predator-spyware-ios-kernel-exploitation-engine/
声明:本文来自玄月调查小组,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。