文章总结: 本文探讨了一种绕过ARM64指针认证(PAC)的新方法。该方法利用JavaScriptJIT编译过程,通过精心构造的shellcode喷射,在指令域签名而在数据域校验,从而绕过PAC验证。文章详细分析了PAC的密钥分域机制、JIT喷射攻击原理,并从细粒度密钥管理、JIT常量隔离等方面提出了防御建议。 综合评分: 85 文章分类: 漏洞分析,二进制安全,web安全,恶意软件,渗透测试
PAC 绕过新维度
原创
Snow狼 Snow狼
Ghost Wolf Lab
2026年7月1日 00:00 北京
在小说阅读器读本章
去阅读
摘要
ARM64 的指针认证通过 PACIA/PACIB 指令为返回地址和函数指针附加密码学签名,阻断了传统 ROP/JOP 攻击。然而,PAC 的密钥分域——指令地址用 A-key,数据地址用 B-key——留下了裂隙。攻击者可以在 JavaScript JIT 编译过程中喷射精心构造的 shellcode,利用 JIT 引擎生成混合了返回指令序列的代码,在指令域签名却在数据域校验,从而绕过 PAC 验证。
ARM64 PAC密钥分域与签名
PAC 指令与密钥
ARMv8.3-A 引入了指针认证(PAC),使用基于 QARMA 的轻量级 MAC 算法为 64 位指针生成认证码,嵌入指针的高位。核心指令:
- PACIA Xd, Xn:使用指令 A-key 对 Xn 生成签名,存储到 Xd。
- PACIB Xd, Xn:使用指令 B-key 对 Xn 签名。
- AUTIA Xd, Xn:验证 A-key 签名,若失败则将 Xd 设为无效指针。
- AUTIB Xd, Xn:验证 B-key 签名。
A-key 用于指令地址(如返回地址、函数指针),B-key 用于数据地址(如虚函数表指针)。这构成了密钥分域:一个域下生成的签名无法在另一个域下通过验证。
密钥分域安全
分域设计假设攻击者无法同时控制指令域和数据域的签名生成。但在 JIT 环境下,这一假设被打破。JIT 编译器动态生成代码,其中包含大量的函数调用和返回指令序列。如果攻击者能够操控 JIT 生成的代码,在指令域中嵌入特定的返回指令序列,并在数据域中喷射与之对应的指针,就可能制造跨域 PAC 伪造。
JavaScript JIT 喷射的跨域攻击窗口
V8 JIT 的代码生成与返回地址签名
V8 的 TurboFan 编译器在生成代码时,对每个函数入口会使用 PACIBSP 对返回地址签名(存储在栈上),在函数返回前使用 AUTIBSP 验证。默认情况下,JIT 生成的代码运行在指令域内,受 A-key 保护。
JIT 喷射中的返回指令序列混淆
JIT 喷射的核心是构造一个巨大的常量数组(如浮点数组),其中包含精心挑选的指令字节,通过跳转到这些常量的不同偏移位置来执行不同的指令序列。在 ARM64 上,攻击者可以喷射以下混合:
- 一段模拟
AUTIB失败后不会崩溃的合法代码路径(即不会产生异常,因为 AUTIB 失败通常会将指针置零,导致空指针访问崩溃,但攻击者可以提前在零地址映射内存,使得零地址解引用有效)。 - 使用 B-key 伪造的返回地址。由于 JIT 数据区(常量池)内的数据地址通常使用 B-key 签名,攻击者可以预先用
PACIB对目标返回地址签名,然后将签名后的指针嵌入数据区。当 JIT 代码加载这个伪造的返回地址并执行RET时,由于硬件自动用 B-key 验证(AUTIB),验证通过,CPU 即跳转到攻击者指定的代码。
这一跨域过程本质上是:在指令域(A-key)生成代码,将 B-key 签名的伪造返回地址带入控制流,完成从 A-key 到 B-key 的信任转移。
从JavaScript到跨域PAC伪造
构造恶意 JIT 函数
攻击者需要构造一个特殊的 JavaScript 函数,使其 JIT 编译后生成如下模式的代码:
- 读取常量池中的一个 64 位值(即伪造的返回地址)。
- 将该值写入 Link Register (X30) 或直接作为返回地址压栈。
- 执行返回指令
RET。
这可以通过控制 JIT 优化来实现,例如使用 try/catch、生成特定形状的对象等,诱导 TurboFan 发射特定的加载/返回序列。
跨域签名伪造的数据准备
在 JavaScript 中,利用 ArrayBuffer 和 Float64Array 可以精确控制二进制数据。攻击者通过预先计算 B-key 签名的有效载荷地址(例如目标 shellcode 的地址,该地址已经用 B-key 签名),并将其作为常量写入数组。随后诱导 JIT 将这组常量编译为只读数据段,并将对应的机器码生成到指令段。
利用零地址映射应对验证失败
由于 ARM64 上 AUTIB 失败会导致 X30 被置为零(在某些实现中为 -1),如果 CPU 跳转到零地址,通常会导致崩溃。攻击者可以通过在 JavaScript 中分配大型 ArrayBuffer 并利用内存碎片,在地址 0 附近映射一页,写入 NOP sled 和最终的 shellcode,从而安全接管执行流。
核心利用代码
ARM64 汇编级别的跨域签名伪造演示
// 假设 X1 指向数据段,其中包含使用 B-key 签名的目标地址
// 攻击者预先用 PACIB 计算好的值:target_b_signed
LDR X30, [X1, #0] // 将伪造的返回地址加载到链接寄存器
AUTIB X30, SP // 使用 B-key 验证(与 SP 作为上下文)
CBNZ X30, skip_trap // 如果验证成功(X30 != 0),跳转
// 如果失败,X30 为零,执行零地址 shellcode(攻击者已映射)
MOV X0, #0
BR X0 // 跳转到零地址(已部署 payload)
skip_trap:
RET // 正常返回,实际跳转到攻击者期望的目标
在实际攻击中,攻击者会确保 target_b_signed 是用 B-key 正确签名的一个合法代码地址,这样 AUTIB 成功,直接执行 RET 跳转到 shellcode。
JavaScript 侧构造 JIT 常量喷射
// 构造一个包含 B-key 签名地址的 Float64Array
// 假设 target_addr 是 shellcode 的地址,事先用 PACIB 签名(通过原生函数计算)
// 这里仅展示概念,实际签名需要通过外部计算(例如预先在原生代码中计算好)
functiongenBKeySignedAddress(targetAddr, modifier) {
// 模拟 PACIB 计算(实际硬件相关,这里用伪码)
// 实际攻击中,攻击者在编译时计算好签名值
return targetAddr ^ (modifier & 0xFFFF000000000000); // 简化
}
const TARGET_ADDR = 0x1234567800n; // shellcode 地址
const MODIFIER = 0xabcdef0000000000n;
const signed = genBKeySignedAddress(TARGET_ADDR, MODIFIER);
// 将 64 位值表示为两个 32 位值放入 ArrayBuffer
const buf = newArrayBuffer(8);
const view = new BigInt64Array(buf);
view[0] = signed;
// 创建一个函数,强制 JIT 优化并包含该常量
functionjitSpray(arr) {
let x = arr[0];
// 诱导 JIT 生成 "LDR X0, [常量]; RET" 的代码
// ... 经过一系列优化后,JIT 可能内联常量并执行 RET
}
V8 引擎 Patch 以模拟零地址 shellcode
在真实环境中,需在 V8 启动时预先分配 0 地址内存(通过 mmap 或 VirtualAlloc),并写入 shellcode。攻击者在获得代码执行后,可通过漏洞(如 JIT 内存保护绕过)将 shellcode 写入零页面,然后触发上述跨域 PAC 绕过。
防御
- 细粒度 PAC 密钥管理:限制 B-key 在用户态的使用,对 JIT 生成的数据段使用不同于标准 B-key 的派生密钥,使攻击者难以预计算签名。
- JIT 常量隔离:将 JIT 生成的常量数据放置于不可执行页,并禁止在这些页中使用 B-key 签名。
- 控制流完整性(CFI)补充:配合 Clang CFI,检查间接分支目标是否合法。
- 硬件更新:未来的 ARMv9 可能引入更细粒度的 PAC 密钥(如每个 EL 级别独立密钥),缩减跨域攻击面。
结语
PAC 并非无懈可击。JavaScript JIT 引擎的动态代码生成能力,为攻击者提供了跨越密钥域的桥梁。通过巧妙地喷射 B-key 签名的返回地址,并配合零地址映射,攻击者能够打破指令与数据之间的密码学壁垒。这一攻击手法再次印证了:在复杂的系统软件栈中,安全特性的设计假设需覆盖从高级语言到微架构的所有层级,任何未预见的交互都可能滋生新的攻击面。对于防御者,除了依赖硬件特性,还需要在编译器、运行时和操作系统层面构建纵深防御,方能封堵这不断涌现的 PAC 绕过新维度。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Ghost Wolf Lab Snow狼 Snow狼《PAC 绕过新维度》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论