深入解析Hyper-V虚拟机工作进程(VMWP)攻击面与漏洞挖掘

本文详细剖析了Hyper-V虚拟机工作进程(VMWP)的技术架构,包括其与虚拟化基础设施驱动(VID)的通信机制、指令模拟器工作原理、虚拟设备仿真实现,并通过CVE-2018-0888等实际案例演示了漏洞挖掘方法,最后介绍了微软为强化VMWP安全实施的CFG/ACG/CIG等缓解措施。

攻击虚拟机工作进程 | MSRC博客

在过去一年中,我们投入了大量时间使Hyper-V研究更易于开展。首篇博客《Hyper-V研究第一步》描述了调试管理程序的工具和设置,并分析了虚拟化堆栈组件的攻击面。随后发表的《Hyper-V中准虚拟化设备的模糊测试》聚焦于VSPs-VSCs通过VMBus的通信机制,披露了根分区内核(vpcivsp.sys)中vPCI VSP的客户机到主机漏洞。八月,Joe Bialek在Black Hat上的精彩演讲展示了如何利用虚拟机工作进程(VMWP)中IDE模拟器的另一个漏洞。现在,让我们深入探究VMWP内部机制。

虚拟机工作进程是什么?

虚拟化堆栈中最大的攻击面之一就实现在根分区的用户空间——虚拟机工作进程(VMWP.exe)。每个虚拟机对应一个VMWP.exe进程实例,其主要组件包括:

  • vSMB服务器
  • Plan9文件系统
  • 集成组件(IC)
  • 虚拟设备(模拟器/非模拟设备)

VMWP可视为微软的"QEMU"式进程,负责实现模拟/非模拟设备。这类组件通常非常复杂,而复杂实现往往容易出错…

VMWP内部机制

整体架构

工作进程通过虚拟化基础设施驱动(vid.sys)与hypervisor通信。VID使用hypercall向hypervisor发送管理命令,包括:

  • 创建/删除分区
  • 挂起/恢复分区
  • 动态内存管理
  • 添加/删除虚拟处理器

VID通知分发器(VND)是关键组件,允许客户端注册并接收来自客户机的动作通知。x64架构支持的VID通知类型包括:

1
2
3
4
5
6
7
8
typedef enum _VID_MESSAGE_TYPE {
    VidMessageMbpAccess = 0x0001,
    VidMessageException = 0x0002 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
    VidMessageTripleFault = 0x0003 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
    VidMessageExecuteInstruction = 0x0004 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
    VidMessageMmio = 0x0005 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
    //...共18种消息类型
} VID_MESSAGE_TYPE;

关键组件

指令模拟器

EmulatorVP类实现了x86/x64指令模拟,包含约250个函数,主要分为:

  • EmulatorVp::Execute*Instruction:指令执行模拟入口
  • EmulatorVP::Execute*Op:具体操作处理
  • EmulatorVp::ExecuteIs*:RFLAGS状态检查
  • EmulatorVP::Decode*:指令解码器

典型调用栈示例:

1
2
3
4
5
VndCompletionThread
└─VndCompletionHandler::HandleVndCallback
  └─EmulatorVp::DispatchMmioOperation

      └─EmulatorVp::ExecuteGEInstruction

虚拟设备

虚拟设备分为三类:

  1. 模拟设备:完整模拟硬件设备(如e1000网卡)
  2. 准虚拟化设备:专为虚拟环境设计的虚拟设备
  3. 直通设备:允许客户机直接访问物理硬件

主要设备模拟DLL及其功能:

DLL名称 功能范围 模拟设备示例
VmEmulatedDevices.dll 1500+函数 PIIX芯片组、DMA控制器、PS/2键盘
vmuidevices.dll 1500+函数 视频设备、输入管理器、HID设备
vmEmulatedNic.dll 网络设备 DEC 21041/21140A/21143网卡
VmEmulatedStorage.dll 存储设备 IDE控制器、光驱、软盘驱动器

PCI配置访问示例

1
2
3
4
5
6
7
8
STDMETHOD(NotifyPciConfigAccess)(
    _In_ PCI_BUS_NUMBER         Bus,
    _In_ PCI_DEVICE_NUMBER      DeviceNumber,
    _In_ PCI_FUNCTION_NUMBER    FunctionNumber,
    _In_ UINT16                 InRegAddress,
    _In_ BOOLEAN                InIsWrite,
    _Inout_ UINT32*             IoData
);

该接口由多个设备类实现,包括:

1
2
3
vmchipset!VmEmu::WCL::PciHandler::NotifyPciConfigAccess
VmEmulatedStorage!IdeControllerDevice::NotifyPciConfigAccess
vmemulateddevices!VideoS3Device::NotifyPciConfigAccess

调试实践

通过内核调试器执行out 0x1f0, 0x41414141指令,在VMWP中设置断点:

1
bp vmemulatedstorage!IdeControllerDevice::NotifyIoPortWrite

可观察到完整的IO端口写入调用链。

漏洞案例研究

CVE-2018-0888

电池模拟器中的未初始化内存漏洞:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void BatteryEmulator::MmioRead(
    std::uint64_t /* RangeBase */,
    std::uint64_t RangeOffset,
    std::uint64_t NumberOfBytes,
    _Out_writes_bytes_(NumberOfBytes) void* ReadBuffer
    ) noexcept
{
    UINT32 readValue = 0;
    
    if (NumberOfBytes != 4) {
        return; // 未初始化ReadBuffer
    }
    ...
}

攻击者可利用此漏洞读取主机内存敏感信息。

VMWP加固措施

微软实施了以下安全防护:

  1. 控制流防护(CFG)
    • 启用CFG导出抑制
    • 强制CFG校验
  2. 任意代码防护(ACG)
    • 禁止分配/映射可执行页面
    • 禁止修改可执行页面保护
  3. 代码完整性防护(CIG)
    • 禁止加载未签名DLL
  4. 移除SeImpersonatePrivilege权限

尽管有这些缓解措施,攻击者仍可能通过ROP链或文件系统API等途径实现利用。

通过本文分析,我们希望研究人员能更深入地探索虚拟化堆栈安全。如有问题,欢迎通过Twitter(@AmarSaar)联系作者Saar Amar。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计