
Ios Exploiting
- 29 installs
- 1.6k repo stars
- Updated July 19, 2026
- wgpsec/aboutsecurity
Helps with ai & agent building tasks during AI-assisted development.
About
ios-exploiting is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- ios-exploiting
- AI & Agent Building
- AI-coding skill
Ios Exploiting by the numbers
- 29 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #9,417 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wgpsec/aboutsecurity --skill ios-exploitingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 29 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | July 19, 2026 |
| Repository | wgpsec/aboutsecurity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
iOS 系统级漏洞利用方法论
阶段流: 环境准备(Corellium) → 漏洞面分析 → 内核漏洞利用 → WebKit利用 → PAC绕过 → 沙箱逃逸 → 已知CVE分析
深入参考
- iOS 内核堆机制与利用技术 → references/ios-kernel-heap.md
- 缓解机制详解与绕过方法 → references/ios-exploit-mitigations.md
---
Phase 0: 环境准备 (Corellium)
研究环境选择
研究环境?
├─ Corellium(云端 iOS 虚拟化)
│ ├─ 支持内核调试
│ ├─ 支持快照/回滚
│ ├─ 支持多版本 iOS 并行
│ └─ 付费,但研究价值最高
├─ 越狱真机
│ ├─ A11 以下: checkra1n(硬件级越狱)
│ ├─ 需配合 JTAG/SWD(高端研究)
│ └─ 限制: 无法调试内核启动
├─ QEMU (开源)
│ ├─ Project Sandcastle 部分支持
│ └─ 功能有限,不完整
└─ 补丁对比环境
├─ Ghidra + BinDiff
└─ 对比不同 iOS 版本 kernelcachekernelcache 提取
# 1. 下载 IPSW
# https://ipsw.me/ → 选择目标设备和版本
# 2. 解压 IPSW (实际是 ZIP)
unzip iPhone*.ipsw -d ipsw_contents/
# 3. 解压 kernelcache
# 使用 img4tool 或 joker
img4tool -e -o kernelcache.raw ipsw_contents/kernelcache.*
# 或
jtool2 --dec kernelcache.release.*
# 4. Ghidra 加载分析
ghidraRun
# 新建项目 → 导入 kernelcache → ARM64 / AARCH64
# 自动分析完成后可搜索函数/符号BinDiff 版本对比
# 定位安全补丁修改的函数
# 1. 下载漏洞版本和补丁版本的 IPSW
# 2. 提取两个 kernelcache
# 3. Ghidra 分析两个版本
# 4. 导出 BinExport: File → Export → Binary BinExport (v2) for BinDiff
# 5. BinDiff 打开 → 新建 workspace → 添加 diff
# 6. 主文件=漏洞版本,次文件=补丁版本
# 7. 关注: Changed Functions → 修改的函数即补丁位置XNU 版本对应
# iOS 版本 → XNU 版本映射
# https://www.theiphonewiki.com/wiki/kernel
# 例: iOS 15.1 → Darwin Kernel Version 21.1.0 → xnu-8019.43.1---
Phase 1: 漏洞面分析
iOS 攻击面分类
攻击面?
├─ 远程无交互 (Zero-Click)
│ ├─ iMessage 解析器(图片/音频/视频/PDF/vCard)
│ ├─ FaceTime / VoIP
│ ├─ AirDrop / Bluetooth
│ └─ WiFi 驱动 / 协议栈
├─ 远程需交互 (One-Click)
│ ├─ Safari / WebKit (JavaScript → JIT → RCE)
│ ├─ URL Scheme 处理
│ └─ 恶意配置文件 (.mobileconfig)
├─ 本地提权
│ ├─ 内核 syscall 接口
│ ├─ IOKit 驱动(IOSurface/AGX/IOMFB)
│ ├─ XPC 服务
│ ├─ Mach IPC(port/message/voucher)
│ └─ 文件系统 / sandbox 逃逸
└─ 物理接触
├─ USB(lockdownd/usbmuxd)
├─ bootrom(checkm8 系列)
└─ DFU 模式攻击常见漏洞类型
| 漏洞类型 | 常见位置 | 利用复杂度 |
|---|---|---|
| UAF (Use-After-Free) | IPC ports, IOKit objects | 中-高 |
| 堆溢出 (Heap Overflow) | 解析器(图片/字体/媒体) | 中 |
| 类型混淆 (Type Confusion) | WebKit JIT, IOKit | 高 |
| 整数溢出 | 内核内存分配, 长度校验 | 中 |
| 竞态条件 (Race Condition) | syscall 并发, lock 缺失 | 高 |
| 信息泄露 | KASLR 绕过, 堆地址泄露 | 低-中 |
| OOB Read/Write | 数组/缓冲区边界检查缺失 | 中 |
---
Phase 2: 内核漏洞利用
内核堆布局 (Heap Feng Shui)
堆布局策略?
├─ 旧版 (Pre-iOS 15)
│ ├─ kalloc zones: 按大小分区(16/32/64/.../1280)
│ ├─ 同大小对象相邻 → 堆喷射可预测布局
│ ├─ freelist 指针裸露 → 可伪造
│ └─ 步骤:
│ ├─ 1. 喷射填充碎片孔
│ ├─ 2. 继续喷射迫使新页分配
│ ├─ 3. 放置攻击者控制对象
│ ├─ 4. 释放一个对象创造空洞
│ ├─ 5. 触发目标对象分配到空洞
│ └─ 6. 溢出/UAF 覆写目标对象
└─ 新版 (iOS 15+)
├─ kalloc_type: 按类型+大小分区
├─ 不同类型对象隔离(OSData ≠ task_t)
├─ freelist 指针 XOR 编码
├─ per-CPU cache 降低确定性
├─ guard pages 检测溢出
└─ 需要类型特定漏洞或信息泄露内核原语构建
利用原语构建路径?
├─ 信息泄露 → KASLR 绕过
│ ├─ Mach port 信息泄露
│ ├─ IOKit 属性读取越界
│ └─ 获得内核基地址 + 堆地址
├─ 任意读 (Arbitrary Read)
│ ├─ 伪造 IOKit 对象的虚表
│ ├─ 利用 mach_msg OOL 描述符
│ └─ 内核 task port 伪造
├─ 任意写 (Arbitrary Write)
│ ├─ freelist 指针伪造(旧版)
│ ├─ 虚表劫持 → 控制函数指针
│ └─ pipe buffer 篡改
└─ 任意代码执行
├─ 修改进程凭据 (ucred)
├─ 绕过代码签名 (trust cache)
├─ kernel task port 获取
└─ 需绕过 PAC + PPL/SPTMIOSurface 物理 UAF (经典案例)
IOSurface 利用流程:
├─ 1. 分配 IOSurface 对象
├─ 2. 获取底层物理页面引用
├─ 3. 释放 IOSurface(但保持物理页引用)
├─ 4. 物理页被回收,分配给其他内核对象
├─ 5. 通过保留的映射读写被复用的内核对象
└─ 6. 构建 kernel r/w 原语---
Phase 3: WebKit/Safari 利用
WebKit 漏洞利用链
WebKit → 系统完整利用链:
├─ Stage 1: WebKit Renderer RCE
│ ├─ JIT 编译器漏洞(DFG/FTL)
│ ├─ DOM 对象 UAF / 类型混淆
│ ├─ ArrayBuffer 越界读写
│ └─ 获取: JS 层面任意 r/w
├─ Stage 2: 沙箱逃逸
│ ├─ XPC 服务漏洞
│ ├─ Mach port 操作
│ └─ 获取: 进程外代码执行
├─ Stage 3: 内核提权
│ ├─ IPC UAF → kernel r/w
│ ├─ IOKit 驱动漏洞
│ └─ 获取: 内核级权限
└─ Stage 4: 持久化
├─ 修改 trust cache
├─ 代码签名绕过
└─ 安装无签名 payloadJSKit 框架模式 (商业间谍软件)
实战中观察到的模式:
JSKit 利用框架特征:
├─ 可复用入口: 任何 WebKit JIT bug → JS 任意 r/w
├─ 版本抽象: 内置多版本 PAC 绕过模块
├─ 目标指纹: 自动识别 iOS 版本,选择对应绕过
├─ 手动 Mach-O 映射: 内存解析 dyld cache,无需落盘
├─ 组合模式:
│ WebKit RCE → 内核 IPC UAF → kernel r/w → 代码签名绕过 → 无签名 stager
└─ 反分析: Watcher 模块检测:
├─ developer_mode_status
├─ 越狱痕迹(Cydia/checkrain/frida/sshd)
├─ 安全应用(McAfee/Avast/Norton)
├─ 自定义代理/根证书
└─ 特定 locale (US/IL)---
Phase 4: PAC 绕过
PAC 机制概述
PAC (Pointer Authentication Codes):
├─ 硬件: ARMv8.3+ (A12 起)
├─ 五个 128-bit 密钥:
│ ├─ APIAKey / APIBKey → 指令指针签名
│ ├─ APDAKey / APDBKey → 数据指针签名
│ └─ APGAKey → 通用签名
├─ 指令:
│ ├─ PACxx → 签名指针(嵌入 PAC 到高位)
│ ├─ AUTxx → 验证+去除 PAC
│ └─ XPACxx → 去除 PAC(不验证)
├─ Modifier(上下文绑定):
│ └─ SP / frame pointer / object ID → 防止跨上下文重用
└─ Apple 定制:
├─ 每次启动随机化密钥
├─ 用户态/内核态域隔离
└─ 九种 modifier 类型PAC 绕过技术分类
PAC 绕过方法?
├─ 内核态 PAC 绕过(极难)
│ ├─ 签名 gadget 重用
│ ├─ 未保护的间接分支
│ ├─ CVE-2023-32424 (Apple Silicon M1/M2)
│ └─ 通常需要实现级 bug,无通用绕过
├─ 用户态 PAC 绕过
│ ├─ dyld shared cache
│ │ ├─ 预签名函数指针复用
│ │ └─ PAC oracle 构建
│ ├─ dlsym(3) 返回已签名指针
│ │ ├─ 调用 dlsym("symbol") → 获取 A-key 签名指针
│ │ ├─ iOS 18.4 dlsym bug (Synacktiv)
│ │ └─ context = 0 的签名可跨进程重用
│ ├─ DYLD 重定位窗口
│ │ ├─ 动态链接时临时 RW 页面
│ │ ├─ 竞态利用修改重定位表
│ │ └─ SPRR/VM_FLAGS_TPRO 保护(新版)
│ └─ ObjC Runtime (SLOP)
│ ├─ NSPredicate / NSExpression / NSInvocation
│ ├─ ISA / selector 指针未完全 PAC 保护
│ └─ SeLector Oriented Programming
└─ 组合绕过
├─ 信息泄露 + signing gadget
├─ 类型混淆 → 控制已签名对象
└─ 多 stage 链: 每个 stage 提供不同原语---
Phase 5: 沙箱逃逸
iOS 沙箱架构
沙箱层次:
├─ App Sandbox(最严格)
│ ├─ 文件系统: 仅访问自身容器
│ ├─ IPC: 受限的 XPC/Mach port 访问
│ ├─ 网络: 受 ATS 约束
│ └─ 逃逸路径: XPC 服务漏洞 / Mach port 操作
├─ WebContent Sandbox(Safari 渲染进程)
│ ├─ 比 App 更严格
│ ├─ 无直接文件系统访问
│ ├─ 有限的 Mach 服务列表
│ └─ 逃逸路径: 利用可达的 Mach 服务
├─ 系统服务 Sandbox
│ ├─ mediaserverd / imagent / SpringBoard
│ ├─ 各有不同权限范围
│ └─ 可作为提权中间跳板
└─ 内核 (无沙箱)
└─ 完全权限PPL / SPTM 绕过
PPL (Page Protection Layer) 保护:
├─ 内核内的内核: 即使 kernel r/w 也无法修改保护页
├─ 保护范围:
│ ├─ 页表结构
│ ├─ 代码签名元数据 / trust cache
│ ├─ entitlement 表
│ └─ 内核代码页
├─ 基于 APRR (Access Permission ReRouting)
│ └─ PTE 索引 → APRR 寄存器 → 实际权限
├─ 已知绕过:
│ ├─ Project Zero TLB stale entry trick
│ │ ├─ 操控页表映射 + 不完整 TLB flush
│ │ └─ 获得 PPL 保护页的可写映射
│ └─ PPL 代码本身的 bug(边界检查缺失等)
└─ 演进: A15+/M2+ → SPTM 替代 PPL
└─ 更高特权级别的页表监控---
Phase 6: 已知 CVE 分析
典型漏洞利用链
Safari → 内核全链 (CVE-2023-419xx 系列)
Intellexa Predator 利用链:
├─ CVE-2023-41993: WebKit JIT → renderer RCE
│ └─ JSKit 框架获取 JS 任意 r/w
├─ CVE-2023-41992: 内核 IPC UAF
│ └─ 释放 IPC 对象 → 重分配 → 悬挂指针利用
│ └─ 构建 kernel r/w
├─ CVE-2023-41991: 代码签名绕过
│ └─ 修改 trust cache → 无签名代码执行
└─ PREYHUNTER: 后续监控植入
├─ VoIP 录音 (mediaserverd hook)
├─ 键盘记录
├─ 拍照(无 UI)
└─ 录音指示灯隐藏 (SpringBoard hook)iMessage Zero-Click 模式
iMessage 零点击攻击面:
├─ 图片解析器: ImageIO (TIFF/GIF/PNG/JPEG/HEIF)
├─ 音频解析器: CoreAudio (CAF/MP3/AAC)
├─ 视频解析器: AVFoundation
├─ PDF 渲染: CoreGraphics
├─ vCard 解析: Contacts framework
├─ 利用链典型模式:
│ ├─ 1. 畸形媒体文件触发解析器漏洞
│ ├─ 2. 在 imagent/mediaserverd 进程中获得 RCE
│ ├─ 3. 利用该进程可达的内核接口提权
│ └─ 4. 无需用户任何交互
└─ 案例:
├─ FORCEDENTRY (NSO): JBIG2 PDF → 图灵完备虚拟机
├─ Operation Triangulation: 字体解析 → kernel
└─ CVE-2021-30860: CoreGraphics PDF 整数溢出缓解措施演进
| 缓解机制 | 引入时期 | 防护目标 |
|---|---|---|
| Code Signing | 初始 | 未签名代码执行 |
| DEP/W^X | 早期 | shellcode 执行 |
| ASLR | iOS 4-5 | 地址预测 |
| KASLR | iOS 5-6 | 内核地址预测 |
| KPP / Watchtower | iOS 9 时代,A7-A9 常见 | 内核代码篡改 |
| KTRR / KIP | A10+ | 内核代码页写入 |
| PPL | A12+ | 内核内存修改保护页 |
| PAC | A12+ (ARMv8.3) | 指针篡改/ROP/JOP |
| BTI | ARMv8.5+ | 间接分支劫持 |
| PAN | ARMv8.1+ | 内核访问用户内存 |
| PXN | ARMv8+ | 内核执行用户代码 |
| SPTM/TXM | 较新平台(如 A15+ / iOS 17+) | 内核内存与页表权限管理 |
| MTE/EMTE/MIE | A19+ | UAF/堆溢出/OOB |
---
Phase 7: 异常处理机制(利用相关)
XNU 异常处理流程
异常触发 → 利用影响:
├─ CPU 异常 (Data Abort / Illegal Instruction / PAC Fail)
├─ trap handler → exception_triage()
├─ 分发顺序:
│ ├─ 1. Thread exception port (调试器)
│ ├─ 2. Task exception port (进程级)
│ └─ 3. Host exception port (ReportCrash)
├─ 无人处理 → bsd_exception() → UNIX signal
│ ├─ EXC_BAD_ACCESS → SIGSEGV/SIGBUS
│ ├─ EXC_BAD_INSTRUCTION → SIGILL
│ ├─ EXC_ARM_PAC → SIGILL (非致命) / 直接终止 (TFRO_PAC_EXC_FATAL)
│ └─ EXC_CRASH → SIGKILL
└─ PAC 异常特殊处理:
├─ 平台二进制: TFRO_PAC_EXC_FATAL = true
├─ PAC 失败直接终止,不经过调试器
└─ 防止调试器绕过 PAC 检查利用中的异常处理
异常在利用中的角色:
├─ 信息收集: 通过异常信息泄露地址
├─ 条件检查: 触发/不触发异常判断条件
├─ crash 稳定性: 利用失败时的优雅退出
├─ anti-analysis 对抗:
│ ├─ Hook EXC_BREAKPOINT → 实现自定义断点
│ ├─ Mach exception port → 自定义异常处理
│ └─ thread_set_state → 修改寄存器恢复执行
└─ 对抗缓解:
├─ PAC 异常 → 需避免触发(而非处理)
└─ 寄存器覆写 → 破坏 crash 取证---
工具速查
| 工具 | 用途 | 场景 |
|---|---|---|
| Ghidra | kernelcache 反编译 | 补丁对比/函数分析 |
| BinDiff | 二进制差异对比 | 定位安全补丁 |
| Corellium | iOS 虚拟化研究 | 内核调试/漏洞复现 |
| Frida | 运行时 Hook | 用户态利用验证 |
| r2frida | 内存分析 | 运行时堆分析 |
| jtool2 / otool | 二进制解析 | Mach-O 结构分析 |
| img4tool | IPSW 解析 | kernelcache 提取 |
| checkra1n | A5-A11 越狱 | 研究设备准备 |
---
参考资源
iOS 漏洞利用缓解机制详解与绕过方法
缓解机制全景
1. 代码签名 (Code Signing)
机制: 所有可执行代码必须经 Apple 证书链签名。Mach-O loader 在加载时验证代码页、段、entitlements。
防护: 阻止任意代码注入、二进制修改、未签名 payload 执行。
绕过难度: 高。需要内核级原语修改 trust cache 或利用签名验证 bug。
签名验证检查点:
├─ 加载时: loader 验证 Mach-O 签名
├─ 运行时: mprotect 可执行页需签名验证
├─ 动态代码: JIT 需 JIT entitlement
└─ entitlements: 特权 API 需特定 entitlement2. CoreTrust
机制: 运行时签名验证子系统,对 Apple 根证书直接验证(不依赖本地 trust store)。
防护: 阻止替换/修改系统二进制、篡改 entitlements。
绕过: 需要 trust cache 修改(需 kernel r/w + PPL 绕过)。
3. DEP / W^X (数据执行保护)
机制: 可写页不可执行,可执行页不可写。MMU 强制。
防护: 阻止 shellcode 直接执行。
绕过: ROP/JOP 不直接执行注入代码,而是复用已有代码片段。
攻击者尝试:
mprotect(heap_addr, size, PROT_EXEC)
→ 系统拒绝: 需代码签名验证
→ 即使绕过 mprotect,PAC 阻止 ROP gadget 串联4. ASLR (用户空间)
机制: 库、堆、栈基地址每次启动随机化。
防护: 阻止硬编码 gadget 地址。
绕过: 需要信息泄露(leak)获取基地址。
绕过步骤:
├─ 1. 信息泄露漏洞 → 获取某个库的地址
├─ 2. 计算 slide (随机偏移)
├─ 3. 所有 gadget 地址 = 已知偏移 + slide
└─ 注意: 每次运行 slide 不同5. KASLR (内核空间)
机制: 内核 text 基地址每次启动随机化。
防护: 阻止静态内核利用。
绕过: 需要内核信息泄露漏洞。
KASLR 绕过常见方法:
├─ Mach port 信息泄露 → 泄露内核指针
├─ IOKit 属性越界读 → 泄露内核堆地址
├─ 内核 stack 残留数据 → 泄露返回地址
└─ 时序侧信道(理论上可行,实践困难)6. KPP/AMCC (内核补丁保护)
机制: 硬件/固件模块持续监控内核 text 页完整性(hash 校验)。
防护: 阻止内核代码篡改(inline hook / 函数修改)。
绕过: 数据攻击(不修改代码,只修改数据/指针)。
绕过策略:
├─ 不修改内核代码 → 修改内核数据
├─ 修改函数指针/虚表 → 控制流劫持
├─ 修改进程凭据 → 权限提升
└─ 修改页表 → 内存映射操控7. KTRR (内核 Text 只读区域)
机制: 硬件级保护,启动后内核 text 页物理只读,即使 EL1 也无法写入。
防护: 阻止内核代码修改,即使获得内核权限。
绕过: 需要破坏启动链,或利用 KTRR 实现 bug。
8. PAC (指针认证)
见 SKILL.md Phase 4 详述。
9. BTI (分支目标识别)
机制: 间接分支目标必须以 BTI landing pad 开始。
防护: 减少可用 ROP/JOP gadget 数量。
BTI 变体:
├─ BTI C: 允许 call 类间接分支 (BLR)
├─ BTI J: 允许 jump 类间接分支 (BR)
└─ BTI JC: 两者皆可
与 PAC 协同:
├─ PAC: 确保指针值正确(来源验证)
├─ BTI: 确保目标是合法入口点(目标验证)
└─ 攻击者需要: 正确的 PAC + 目标有 BTI pad10. PAN (特权访问禁止) + PXN (特权执行禁止)
PAN 机制: 内核态无法直接读写用户空间内存。
PXN 机制: 内核态无法执行用户空间代码。
PAN 工作流:
├─ 内核接收用户指针
├─ 需要访问时: 临时禁用 PAN (MSR PSTATE.PAN, #0)
├─ 完成后: 重新启用 PAN (MSR PSTATE.PAN, #1)
└─ 忘记重新启用 → 安全风险
PAN 已知问题:
└─ Execute-only 用户页面 (--x)
└─ 可能不触发 PAN(规范歧义)
└─ 内核可从 execute-only 页读取数据
└─ Apple 可能禁止 execute-only 用户页
PXN 保护:
├─ 用户页 PXN bit = 1
├─ 内核尝试跳转到用户页 → fault
└─ 阻止 ret2usr 攻击11. TBI (Top Byte Ignore)
机制: 指针高 8 位被忽略,可用于存储标签/元数据。
用途: MTE (Memory Tagging Extension) 的基础。
12. PPL / SPTM
见 SKILL.md Phase 5 详述。
13. MTE / EMTE / MIE
机制: 内存标签检查,每个分配块和指针携带标签。
EMTE 工作流:
├─ 分配 A (地址 0x1000) → 标签 T1
├─ 分配 B (地址 0x2000) → 标签 T2
├─ 指针 P = (T1 << 56) | 0x1000
├─ *(P + offset) = value → T1 匹配 → 允许
├─ *(P + size_of_A) = value → 进入 B 区域 → T2 ≠ T1 → fault
├─ free(A) → 重新标记为 T3
└─ *(P) = value → T3 ≠ T1 → fault (UAF 检测)
Apple EMTE vs 标准 MTE:
├─ 同步模式(立即检测,无延迟窗口)
├─ 标签保密性(防止侧信道泄露标签)
├─ 分配器集成(kalloc_type / xzone malloc)
├─ 默认启用(支持硬件上)
└─ 覆盖内核+用户空间缓解绕过组合策略
完整利用链需要绕过的层次
构建完整利用链:
├─ 信息泄露
│ └─ 绕过 ASLR + KASLR
├─ 代码执行
│ └─ 绕过 DEP/W^X (ROP/JOP)
│ └─ 绕过 PAC (签名 gadget / dlsym / SLOP)
│ └─ 绕过 BTI (仅使用有 landing pad 的 gadget)
├─ 内核提权
│ └─ 绕过 PAN/PXN (数据攻击,不跳转用户空间)
│ └─ 绕过 KPP/KTRR (修改数据不修改代码)
│ └─ 绕过 zone 隔离 (类型特定漏洞)
├─ 持久化
│ └─ 绕过 PPL/SPTM (TLB trick / PPL bug)
│ └─ 绕过 CoreTrust (修改 trust cache)
│ └─ 绕过 Code Signing (添加自签名 entry)
└─ 存活检测
└─ 绕过 MTE/EMTE (仅新设备,标签碰撞/泄露)各 iOS 版本防护等级
防护演进:
├─ iOS 10 以下: ASLR + DEP + Code Signing
│ └─ 利用难度: 低-中
├─ iOS 12 (A12): + PAC + KASLR 增强
│ └─ 利用难度: 中
├─ iOS 14-15: + kalloc_type + encoded freelist
│ └─ 利用难度: 中-高
├─ iOS 16-17: + PPL/SPTM + BTI 增强
│ └─ 利用难度: 高
└─ iOS 18+ (A19): + EMTE/MIE
└─ 利用难度: 极高iOS 内核堆机制与利用技术
旧版内核堆 (Pre-iOS 15 / Pre-A12)
Zone 分配器架构
内核使用 kalloc zone 分配器,按固定大小分区:
| Zone 名称 | 元素大小 | 典型用途 |
|---|---|---|
default.kalloc.16 | 16 字节 | 微小结构体/指针 |
default.kalloc.32 | 32 字节 | 小结构体/对象头 |
default.kalloc.64 | 64 字节 | IPC 消息/小缓冲区 |
default.kalloc.128 | 128 字节 | OSObject 部件 |
default.kalloc.256 | 256 字节 | 中型内核对象 |
| ... | ... | ... |
default.kalloc.1280 | 1280 字节 | IOSurface/图形元数据 |
Freelist 机制
Zone 页面布局 (64 字节 chunks):
[ A ] [ F ] [ F ] [ A ] [ F ] [ A ] [ F ]
Freelist 链表:
HEAD --> [ F ] --> [ F ] --> [ F ] --> [ F ] --> NULL
(next 指针存储在 freed chunk 开头 8 字节)
分配操作:
1. 弹出 HEAD (返回给调用者)
2. HEAD = HEAD->next
释放操作:
freed_chunk->next = HEAD
HEAD = freed_chunkFreelist 投毒攻击
正常状态:
HEAD --> [ F1 ] --> [ F2 ] --> [ F3 ] --> NULL
堆溢出覆写 F1->next:
HEAD --> [ F1 ]
(next) --> 0xDEAD_BEEF_CAFE (攻击者指定地址)
下次 alloc:
1. 返回 F1
2. HEAD = 0xDEAD_BEEF_CAFE
3. 再次 alloc → 返回攻击者指定地址的内存
→ 可在任意内核地址构造伪对象堆风水 (Heap Feng Shui) 步骤
阶段 1: 填充碎片孔
├─ 大量分配同大小对象 → 填满现有空洞
└─ 堆变得连续且可预测
阶段 2: 迫使新页分配
├─ 继续分配 → zone 耗尽已有页面
├─ 分配器分配新页(slab)
└─ 新页中对象紧密排列
阶段 3: 放置攻击者对象
├─ 喷射攻击者控制的对象(如 OSData)
├─ 在新页中占据多个位置
└─ 已知布局: [攻击者][攻击者][攻击者]...
阶段 4: 创造空洞
├─ 释放其中一个攻击者对象
├─ 创建精确位置的空洞
└─ freelist HEAD 指向该空洞
阶段 5: 目标对象就位
├─ 触发内核分配目标对象(如 ipc_port)
├─ 目标对象落入空洞位置
└─ 布局: [攻击者][目标][攻击者]
阶段 6: 利用
├─ 从相邻攻击者对象溢出 → 覆写目标对象
├─ 或: UAF → 释放目标 → 重新分配为攻击者数据
└─ 构建 kernel r/w 原语现代内核堆 (iOS 15+ / A12+)
kalloc_type 类型隔离
旧版:
kalloc.64: [OSData][ipc_port][OSString][task_t] ← 同大小混放
攻击者喷射 OSData → 可能与 ipc_port 相邻
新版:
kalloc_type_osdata: [OSData][OSData][OSData] ← 按类型隔离
kalloc_type_ipc_port: [port][port][port]
→ 攻击者的 OSData 永远不会与 ipc_port 相邻Freelist 编码
旧版:
freed_chunk[0:8] = next_free_ptr (明文指针)
新版:
freed_chunk[0:8] = next_free_ptr XOR zone_cookie
→ 不知道 cookie 就无法伪造 freelist 指针
→ 堆溢出覆写 freelist 指针不再直接可用分配流程 (现代)
malloc(size, type) → 选择 kalloc_type zone
├─ 检查 per-CPU cache
│ ├─ 有空闲 → 返回
│ └─ 无空闲 → 检查全局 freelist
├─ 全局 freelist
│ ├─ 有空闲 → 解码指针 → 返回
│ └─ 无空闲 → 分配新 slab
└─ 新 slab (4KB 页)
├─ 切分为固定大小 chunks
└─ 返回第一个 chunk新版防护总结
| 防护 | 效果 |
|---|---|
| kalloc_type 类型隔离 | 不同类型对象不相邻 |
| Freelist XOR 编码 | 无法直接伪造 freelist |
| per-CPU cache | 降低喷射确定性 |
| Guard pages | 溢出触发 panic |
| zone_require | 防止跨 zone 释放 |
| PPL/SPTM | 保护页表/签名/凭据 |
| PAC | 保护函数指针 |
仍可利用的模式
即使有新防护,以下模式仍是研究方向:
现代攻击方向:
├─ 引用计数操作 → retain/release 控制 → UAF
├─ 虚表 (vtable) 劫持 → 控制流
├─ 共享内存对象 (IOSurface / Mach ports)
│ └─ 桥接 user ↔ kernel 的对象
├─ 类型特定漏洞(同类型内的 bug)
├─ 信息泄露 → 破坏 KASLR + 堆随机化
└─ 大块分配 (>16KB) → 绕过 zone,直接 VM 分配IOSurface 物理 UAF 技术
IOSurface 是跨 user/kernel 共享的图形缓冲区对象:
利用流程:
1. 创建 IOSurface → 内核分配物理页面
2. 获取物理页映射(通过 IOSurface API)
3. 释放 IOSurface → 内核回收物理页
4. 但用户空间仍持有映射 → 物理 UAF
5. 物理页被重新分配给其他内核对象
6. 通过用户空间映射读写其他内核对象
7. 构建 kernel r/w 原语
关键点:
- 物理级别的 UAF,不受虚拟地址隔离限制
- 可跨所有虚拟地址空间影响
- 需要精确控制物理页回收和重分配用户态堆 (xzone malloc, iOS 17+)
架构概览
xzone malloc 结构:
├─ Segment Groups(按用途分区)
│ ├─ data: 纯数据分配
│ ├─ pointer_xzones: 含指针的分配
│ ├─ data_large: 大数据块
│ └─ pointer_large: 大含指针块
├─ Segments(VM 范围)
│ └─ 每个 segment 有独立的 metadata slab
├─ Chunks(大小类切片)
│ └─ 内含 blocks(实际分配单元)
└─ Metadata(带外存储)
└─ free/used 位图存储在独立 VM 区域
└─ 溢出无法覆写 metadataxzone 安全特性
防护矩阵:
├─ 元数据解耦 → 溢出不触及 metadata
├─ Guard pages → 检测 OOB 写
├─ 类型隔离 → 相同大小不同类型 → 不同 zone
├─ EMTE/MIE 标签 → 检测 UAF/OOB/stale access
├─ 延迟复用 / poisoning → 降低 UAF 利用窗口
├─ Chunk 回收 → 未使用 chunk 整体 unmap
├─ 随机化放置 → 降低相邻确定性
└─ 纯数据分离 → 不含指针的分配单独区域