ARM64架构下指针认证(PAC)与影子栈(SCS)安全机制解析
字数 1806 2025-12-23 12:13:22
ARM64架构下指针认证(PAC)与影子栈(SCS)安全机制解析
概述
本文详细解析ARM64架构下的两种重要安全机制:指针认证(Pointer Authentication, PAC)和影子栈(Shadow Call Stack, SCS)。这两种机制共同构成了现代ARM64系统的核心安全防护体系。
指针认证(PAC)机制
基本概念
指针认证是ARMv8.3及以上版本引入的硬件安全特性,其主要目的是防止指针篡改攻击。PAC通过对指针值进行加密签名和验证,确保指针的完整性。
技术原理
- 签名过程:使用特定的密钥对指针进行签名,生成认证码
- 验证过程:在执行指针使用前验证认证码的有效性
- 指令支持:
paciza:对指针进行签名autiza:验证指针签名
实现示例
void help() {
void (*f)();
for(int i = 0; i < 4; i++) {
f = BUILTINS[i].fptr;
__asm__("paciza %0\n" : "=r"(f) : "r"(f));
printf("%8s: %p\n", BUILTINS[i].name, f);
}
}
地址变换过程
假设原始地址:0x0000550000000b7c
经过paciza签名后变为:0xf123abcd00000b7c
- 高16位:签名认证码
- 低48位:原始地址
影子栈(SCS)机制
基本概念
影子栈是基于PAC实现的增强安全机制,专门用于保护函数返回地址不被篡改。
技术特点
- 依赖关系:SCS依赖于PAC功能实现
- 硬件要求:需要特定处理器架构支持
- 实现方式:使用X18寄存器存储影子栈指针
架构对比
| 项目 | 指针认证(PAC) | 影子栈(SCS) |
|---|---|---|
| 本质 | ARM硬件安全机制 | 基于PAC的安全机制 |
| 作用 | 防止指针篡改 | 保护函数返回地址 |
| 依赖 | 硬件支持 | 依赖PAC功能 |
| 实现 | paciza/autiza指令 | 编译器自动处理 |
实际应用分析
示例程序解析
分析一个具体的PAC演示程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[8];
void (*fptr)();
} builtin_func;
// 功能函数定义
void ls() { system("ls"); }
void read64() { /* 读取内存 */ }
void write64() { /* 写入内存 */ }
builtin_func BUILTINS[4] = {
{ .name = "help", .fptr = help },
{ .name = "ls", .fptr = ls },
{ .name = "read64", .fptr = read64 },
{ .name = "write64", .fptr = write64 },
};
int main() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
void (*fptr)() = NULL;
puts("Welcome to pac shell v0.0.1");
help();
while(1) {
printf("pacsh> ");
scanf("%p", &fptr);
__asm__("autiza %0\n" : "=r"(fptr) : "r"(fptr));
(*fptr)();
}
}
安全机制工作流程
- 初始化阶段:程序启动时显示各函数的签名指针
- 用户交互:接收用户输入的指针值
- 验证执行:使用autiza指令验证指针签名,然后执行
漏洞利用限制
由于PAC机制的存在,传统的漏洞利用技术受到严格限制:
- 直接跳转到任意地址会被签名验证阻止
- 需要正确的签名才能执行代码
跨架构对比
硬件支持要求
| 架构 | PAC支持 | SCS支持 | 实现基础 |
|---|---|---|---|
| ARM64 | ARMv8.3+ | 基于PAC | 硬件特性 |
| x86_64 | 无 | Intel CET | 硬件特性 |
| x86 (32位) | 无 | 无 | 软件模拟 |
| 其他架构 | 依赖具体实现 | 依赖具体实现 | 可变 |
QEMU模拟限制
根据知识库信息,QEMU目前不支持PAC指令的模拟,因为PAC是硬件特性。这给相关安全研究带来了一定挑战。
ARM64架构安全特性
ASLR强制启用
- ARM64架构设计时就将ASLR作为安全机制强制启用
- 这是ARMv8-A架构的安全特性,无法通过系统设置禁用
- 与x86架构不同,ARM64没有提供禁用ASLR的机制
汇编指令基础
函数调用规范
STP X29, X30, [SP, #-16]! ; 保存现场
MOV X29, SP ; 设帧指针
; 函数体...
LDP X29, X30, [SP], #16 ; 恢复现场
RET ; 返回
关键指令分类
-
数据传送指令
MOV:寄存器间赋值/立即数加载MVN:按位取反后传送
-
算术逻辑运算
ADD/SUB:加减法AND/ORR/EOR:位运算
-
内存访问
LDR/STR:32位加载存储LDRB/STRB:字节操作LDRH/STRH:半字操作
开发与调试实践
编译选项
普通aarch64程序使用PAC功能时:
- 编译时使用
-mpac等选项 - 编译器自动处理安全机制
- 无需在代码中直接写paciza和autiza指令
调试技巧
# GDB调试命令
gdb-multiarch ./pacsh
target remote:1234
# 调试脚本示例
io = process(['qemu-aarch64', '-L', '/usr/aarch64-linux-gnu', '-g', '1234', file_name])
总结
指针认证(PAC)和影子栈(SCS)代表了现代处理器安全架构的发展方向。通过硬件级别的安全机制,有效防御了多种内存破坏攻击。理解这些机制对于二进制安全研究、漏洞挖掘和安全开发都具有重要意义。
核心要点回顾
- PAC是基础:提供指针完整性保护
- SCS是增强:基于PAC提供返回地址保护
- 硬件依赖:两种机制都需要特定硬件支持
- 开发透明:正常开发中由编译器自动处理
- 研究挑战:模拟环境支持有限,需要真实硬件环境
这些安全机制的普及标志着系统安全防护进入了新的阶段,对安全研究人员提出了更高的技术要求。