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的后利用链是一个严格的流水线,每个阶段都依赖于前一个阶段的成功:

  1. 初始利用(CVE-2023-41993)

  2. 内核读写:突破用户态限制,获得读写内核内存的能力

  3. 绕过PAC

  4. 远程执行

  5. 能力转移

  6. 监控:控制SpringBoard可以禁用麦克风、摄像头访问的可视指示器;控制mediaserverd则可以监听摄像头。

每个阶段都有完善的错误处理,任一失败即中止整个攻击链。

后续,苹果在A15及以上芯片中引入了SPTM(安全页表监视器)。通过将页表管理移至更高特权级别的EL2,即使攻击者获得了内核(EL1)执行权限,也无法直接修改页表来获得任意内存访问。

不过最有效的防御措施仍然是及时更新操作系统。本次的攻击链在iOS17及以上版本中不再有效,因为苹果已经修复了Predator使用的初始漏洞,并引入了额外的内核保护机制。

参考资料:InsidePredator"skernelenginehttps://www.jamf.com/blog/predator-spyware-ios-kernel-exploitation-engine/

声明:本文来自玄月调查小组,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。