搞定PatchGuard:利用KPTI绕过内核修改保护
字数 1708 2025-08-19 12:41:44

利用KPTI绕过Windows PatchGuard内核修改保护技术分析

0x00 前言

本文详细分析了一种利用KPTI(Kernel Page Table Isolation)机制绕过Windows PatchGuard内核修改保护的技术。该技术由ensilo团队发现并于2018年报告给微软,微软在Windows 10 RS5中引入了修复补丁。

0x01 技术背景

1.1 推测执行漏洞

  • Meltdown(恶意数据缓存加载):利用指令执行与权限检查之间的CPU竞争条件
  • Spectre:利用分支预测和推测执行特性
  • 这些漏洞源自CPU硬件层面的侧信道缺陷

1.2 KPTI(内核页表隔离)

  • 软件缓解措施,需要大幅修改操作系统内核
  • Windows实现称为KVAS(Kernel Virtual Address Shadow)
  • 进程虚拟地址空间被分割为两个页表:
    • 内核模式页表:映射完整地址空间(用户+内核)
    • 用户模式页表:仅映射ring 3及ring 0转换所需的最小内核空间

0x02 KVAS实现细节

2.1 内存管理

  • KVASCODE section(位于ntoskrnl.exe):
    • 被映射到用户及内核页表的相同虚拟地址
    • 包含内核处理器控制块(KPRCB)末尾的栈空间及专用区域
  • 用户地址空间在两个页表间共享
  • 不同页表中的不同PML4表项指向相同的PDP表实现共享

2.2 权限转换流程

  • ring 3到ring 0转换新增间接跳转环节
  • 转换代码检查当前页表:
    • 若为用户页表,则切换到内核页表
    • 返回ring 3时执行相反操作

0x03 绕过PatchGuard原理

3.1 PatchGuard局限性

  • 传统上监控ntoskrnl、HAL、NDIS代码及关键结构(IDT、SSDT)
  • ring 3到ring 0转换的第一条和最后一条指令现在在用户页表中执行
  • 用户页表中的内核地址空间对PatchGuard透明

3.2 技术实现步骤

3.2.1 访问用户页表

  1. 内核模式下获取用户页表物理地址:
    • 通过EPROCESS.Pcb.UserDirectoryTableBase
    • 或直接读取CR3寄存器
  2. 使用PTE重映射和页表遍历技术完全控制用户页表

3.2.2 Hook技术实现

  1. 内存管理

    • 修改用户页表,使KVASCODE虚拟地址映射到不同物理页面
    • 不修改ntoskrnl实际页面,避免PatchGuard检测
  2. 代码执行

    • 在用户页表中映射额外页面
    • 创建CR3分配gadget,其ret指令在两个地址空间中重合
    • 修改代码逻辑,压入驱动地址并跳转到CR3分配gadget

3.2.3 处理VBS(Virtualization Based Security)

  • HVCI(HyperVisor代码完整性)
    • 阻止运行未签名代码
    • 需在驱动中预编译hook代码
    • 需预先知道函数位置或使用固定偏移存储数据结构
  • VBS主机使用int 2e指令而非syscall/sysenter

0x04 缓解措施

微软修复方案:

  • PatchGuard应检查内核和用户页表中KVASCODE页面PTE的PFN是否相同
  • 确保最小内核地址空间代码与实际内核空间代码匹配

0x05 影响范围

  • 最初在Windows 10 RS4 x64验证
  • 适用于所有支持KVAS的Windows版本(Win7/8.1及相应服务器版)
  • 技术原理可应用于其他使用KPTI的系统(Linux/macOS)

0x06 防御建议

  1. 确保系统更新至Windows 10 RS5或更高版本
  2. 启用VBS和HVCI提供额外保护
  3. 监控异常的内核内存修改行为

附录:关键技术点总结

技术点 描述
KVAS Windows的KPTI实现,分割用户/内核页表
KVASCODE 包含权限转换代码的特殊section
PTE重映射 修改用户页表映射关系的关键技术
CR3分配gadget 实现跨页表控制流转移的核心组件
HVCI限制 要求hook代码必须预编译和签名
利用KPTI绕过Windows PatchGuard内核修改保护技术分析 0x00 前言 本文详细分析了一种利用KPTI(Kernel Page Table Isolation)机制绕过Windows PatchGuard内核修改保护的技术。该技术由ensilo团队发现并于2018年报告给微软,微软在Windows 10 RS5中引入了修复补丁。 0x01 技术背景 1.1 推测执行漏洞 Meltdown (恶意数据缓存加载):利用指令执行与权限检查之间的CPU竞争条件 Spectre :利用分支预测和推测执行特性 这些漏洞源自CPU硬件层面的侧信道缺陷 1.2 KPTI(内核页表隔离) 软件缓解措施,需要大幅修改操作系统内核 Windows实现称为 KVAS (Kernel Virtual Address Shadow) 进程虚拟地址空间被分割为两个页表: 内核模式页表:映射完整地址空间(用户+内核) 用户模式页表:仅映射ring 3及ring 0转换所需的最小内核空间 0x02 KVAS实现细节 2.1 内存管理 KVASCODE section(位于ntoskrnl.exe): 被映射到用户及内核页表的相同虚拟地址 包含内核处理器控制块(KPRCB)末尾的栈空间及专用区域 用户地址空间在两个页表间共享 不同页表中的不同PML4表项指向相同的PDP表实现共享 2.2 权限转换流程 ring 3到ring 0转换新增间接跳转环节 转换代码检查当前页表: 若为用户页表,则切换到内核页表 返回ring 3时执行相反操作 0x03 绕过PatchGuard原理 3.1 PatchGuard局限性 传统上监控ntoskrnl、HAL、NDIS代码及关键结构(IDT、SSDT) ring 3到ring 0转换的第一条和最后一条指令现在在用户页表中执行 用户页表中的内核地址空间对PatchGuard透明 3.2 技术实现步骤 3.2.1 访问用户页表 内核模式下获取用户页表物理地址: 通过 EPROCESS.Pcb.UserDirectoryTableBase 或直接读取CR3寄存器 使用PTE重映射和页表遍历技术完全控制用户页表 3.2.2 Hook技术实现 内存管理 : 修改用户页表,使KVASCODE虚拟地址映射到不同物理页面 不修改ntoskrnl实际页面,避免PatchGuard检测 代码执行 : 在用户页表中映射额外页面 创建CR3分配gadget,其ret指令在两个地址空间中重合 修改代码逻辑,压入驱动地址并跳转到CR3分配gadget 3.2.3 处理VBS(Virtualization Based Security) HVCI(HyperVisor代码完整性) : 阻止运行未签名代码 需在驱动中预编译hook代码 需预先知道函数位置或使用固定偏移存储数据结构 VBS主机使用 int 2e 指令而非 syscall / sysenter 0x04 缓解措施 微软修复方案: PatchGuard应检查内核和用户页表中KVASCODE页面PTE的PFN是否相同 确保最小内核地址空间代码与实际内核空间代码匹配 0x05 影响范围 最初在Windows 10 RS4 x64验证 适用于所有支持KVAS的Windows版本(Win7/8.1及相应服务器版) 技术原理可应用于其他使用KPTI的系统(Linux/macOS) 0x06 防御建议 确保系统更新至Windows 10 RS5或更高版本 启用VBS和HVCI提供额外保护 监控异常的内核内存修改行为 附录:关键技术点总结 | 技术点 | 描述 | |--------|------| | KVAS | Windows的KPTI实现,分割用户/内核页表 | | KVASCODE | 包含权限转换代码的特殊section | | PTE重映射 | 修改用户页表映射关系的关键技术 | | CR3分配gadget | 实现跨页表控制流转移的核心组件 | | HVCI限制 | 要求hook代码必须预编译和签名 |