ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

iOS Crash Dump Analysis Book:指针认证(PAC)指南——为什么你的指针突然变成 EXC_BAD_ACCESS

2026/8/27 15:08:32 拓冰建站 浏览量
iOS Crash Dump Analysis Book:指针认证(PAC)指南——为什么你的指针突然变成 EXC_BAD_ACCESS iOS Crash Dump Analysis Book指针认证PAC指南——为什么你的指针突然变成 EXC_BAD_ACCESS【免费下载链接】ios-crash-dump-analysis-bookiOS Crash Dump Analysis Book项目地址: https://gitcode.com/gh_mirrors/io/ios-crash-dump-analysis-book本文基于 iOS Crash Dump Analysis BookiOS 崩溃转储分析讲解 iOS 指针认证Pointer AuthenticationPAC机制、arm64e 引发的典型EXC_BAD_ACCESS崩溃以及快速定位、调试与修复的方法帮你看懂崩溃报告中那句 possible pointer authentication failure。什么是指针认证PAC为什么指针会多出 24 位从 A12 仿生芯片iPhone XS / XS Max / XR 及之后机型开始苹果在 ARMv8.3-A 架构中引入了指针认证Pointer Authentication简称 PAC。它的原理非常巧妙64 位指针实际只需要 40 位就能寻址高出的比特位平时是空闲的系统把指针地址 上下文值 密钥算出的哈希值PAC放进高位一旦指针被 bug 或恶意代码篡改哈希对不上这个指针就被判定为无效当它被用来改变程序控制流比如函数跳转时就会触发SIGSEGV。PAC 常用于保护 C 虚函数表不被篡改等安全场景。对崩溃分析来说最关键的一点是指针认证失败时崩溃报告不会直接告诉你是 PAC 出了问题而是伪装成一个看似普通的EXC_BAD_ACCESS这正是新手最容易踩坑的地方。如何开启指针认证Xcode 一键添加 arm64e内核层面苹果早已在 A12 及更新的设备上默认启用 PAC对用户态代码也就是你的 App而言它是一个可选启用opt-in的特性。开启步骤只有一步打开 Xcode 项目的Build Settings在Architectures设置中追加arm64e架构如下图中红圈标注所示如果你正在开发安全敏感的软件尽早采用 arm64e 是个好习惯。完整章节可参考书中 PointerAuthentication.md。真实案例icdab_ptr 的possible pointer authentication failure书籍配套的icdab_ptr示例程序故意对函数指针做了一次没剥离 PAC的算术运算最终崩溃。在 iPhone 11A13 芯片上运行后崩溃报告的关键部分是Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x2000000100ae9df8 - 0x0000000100ae9df8 (possible pointer authentication failure) VM Region Info: 0x100ae9df8 is in 0x100ae4000-0x100aec000 ... --- __TEXT 100ae4000-100aec000 [ 32K] r-x完整报告见 icdab_ptr_ios.crash。 注意箭头两边的两个地址0x2000000100ae9df8是程序真正持有的坏指针高位0x200000是一个特殊的无效 PAC 标记0x0000000100ae9df8是崩溃报告系统剥离 PAC 后推演出的有效地址——它确实落在本程序__TEXT代码段里也就是说目标地址本身没问题坏在指针高 24 位的认证码上。这就是指针突然变成 EXC_BAD_ACCESS的真相地址没错签名错了。快速识别 PAC 崩溃崩溃报告 4 个自查要点拿到一份EXC_BAD_ACCESS报告时用下表 4 步自查是否为指针认证失败#查看位置特征含义1Exception Subtype出现(possible pointer authentication failure)崩溃报告已明确提示 PAC 失败2故障地址高 24 位如0x200000、0x045d34等怪异高位值高位是未通过验证的 PAC3崩溃线程寄存器x8等寄存器带着同样的坏高位如x8: 0x045d340100ae9df8坏指针就在现场4esr 与 Binary Imagesesr: 0x82000004 (Instruction Abort)、镜像架构为arm64e指令跳转被 PAC 拦截且该二进制启用了指针认证根本原因未剥离 PAC 就做了指针运算icdab_ptr的意图是用指针差值算出相邻函数nextInterestingJumpToFunc的地址但直接拿带 PAC 的完整指针值相减得到的高位是两把不同签名的混乱结果再把差值加回原指针时留下的仍是旧函数的 PAC而不是目标函数的 PAC。正确做法是先用ptrauth_strip编译为内建宏__builtin_ptrauth_strip对应汇编指令xpaci作用是剥离寄存器中的 PAC再运算ptrdiff_t clean_delta ptrauth_strip(nextInterestingJumpToFunc, ptrauth_key_asia) - ptrauth_strip(interestingJumpToFunc, ptrauth_key_asia);两个容易忽视的要点崩溃时机滞后指针运算本身不会崩溃只有当这个坏指针被用来改链接寄存器、执行跳转汇编指令blraaz x8——带指令密钥 A 认证的带链接跳转时CPU 才校验并拦截PAC 只能剥、不能自己签你无法用自己的代码给指针重新算出合法的 PAC签名需要私有的密钥与 salt所以手工拼指针在 arm64e 上基本走不通。示例源码可对照 ViewController.m 阅读。如何调试在 lldb 中复现 PAC 崩溃调试 arm64e 目标时有几个实用技巧打印指针时看到的是剥离后的地址。在调试器里打印出问题的result(lldb) po result (actual0x000000010201ddf8 icdab_ptrnextInterestingJumpToFunc at ViewController.m:25)调试器挂着时看不到崩溃报告执行detach分离后让程序继续运行它会在原处触发 PAC 崩溃并生成报告方便把调试器中的寄存器现场与崩溃报告逐一对应本例中x8寄存器恰好就是那个坏指针用 Hopper 这类反汇编工具打开崩溃二进制的 ARM64 反汇编视图定位blraaz、xpaci等 PAC 相关指令确认控制流在哪条跳转上被拦截中文详细解析见 icdab_ptr_ios_explanation.md。不止你的代码系统音频库里的真实 PAC 崩溃书中还收录了一份来自 App Store 真实游戏Unity 引擎的崩溃进程get的第 27 号线程崩溃异常子类型同样是(possible pointer authentication failure)故障函数位于系统库libEmbeddedSystemAUs.dylib的InterruptionListener音频会话中断监听。这说明两件事⚠️ PAC 崩溃未必是你的代码直接造成的系统库、第三方引擎也可能踩雷✅ 但只要崩溃报告里出现那句提示 怪异的高位地址定位思路完全一样找到坏指针检查它是否来自未认证的指针运算或未剥离 PAC 的地址缓存。原始报告可查阅 adventure_crash_ios.crash。项目资料清单从这里继续深入学习书内章节英文markdown/PointerAuthentication.mdPAC 崩溃中文解析markdown/zh/icdab_ptr_ios_explanation.md崩溃样本examples/icdab_ptr_ios/icdab_ptr_ios.crash、examples/icdab_ptr_ios/icdab_ptr_ios_single_session.crash真实案例examples/adventure_pac_crash_ios/adventure_pac_crash_explanation.md示例工程源码source/icdab_ptr/一句话总结在 A12 芯片上指针 地址 认证码。看到EXC_BAD_ACCESS且地址高位不对劲时先查 PAC——剥掉认证码再运算是修复 arm64e 指针崩溃的钥匙。【免费下载链接】ios-crash-dump-analysis-bookiOS Crash Dump Analysis Book项目地址: https://gitcode.com/gh_mirrors/io/ios-crash-dump-analysis-book创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考