Rusty Hypervisor - 基于 Rust 的 Windows UEFI 蓝药丸 Type-1 虚拟机监控程序(代号:Illusion)
博客:https://memn0ps.github.io/hypervisors-for-memory-introspection-and-reverse-engineering/
一个轻量级、内存安全且速度极快的基于 Rust 的 type-1 研究型虚拟机监控程序,带有 Intel VT-x 钩子,专注于研究虚拟化的核心概念。
注意: Illusion 虚拟机监控程序(Windows UEFI Blue Pill Type-1 虚拟机监控程序,Rust 实现)更加稳定,支持更多功能,整体设计也更好。Matrix 虚拟机监控程序(Windows 内核 Blue Pill Type-2 虚拟机监控程序,Rust 实现)是一个较旧的实验性版本,不适用于生产环境。这两个项目都作为模板,帮助人们开始使用 Rust 进行虚拟机监控程序开发。
分页:将 x64 虚拟地址转换为物理地址
此图展示了传统分页系统中将 x64 虚拟地址转换为物理地址的机制。在 x64 架构中,此转换涉及四级页表:PML4、PDPT、PDT 和 PT(页映射级别 4、页目录指针表、页目录表和页表)。每一级使用虚拟地址的 9 位来索引下一级,最终指向 RAM 中的特定物理地址。此过程由操作系统和内存管理单元(MMU)管理,MMU 将软件使用的虚拟地址转换为硬件使用的物理地址。

图 1:x64 虚拟地址转换(完整致谢:Guided Hacking)
扩展页表(EPT):二级地址转换(SLAT)
扩展页表(EPT)是硬件辅助虚拟化技术(如 Intel VT-x 和 AMD-V 的嵌套页表(NPT))的一项功能。EPT 实现了二级地址转换(SLAT),专为虚拟化环境设计。传统分页在客户机操作系统内将虚拟地址转换为物理地址,而 EPT 增加了一个额外的层,将客户机物理地址(客户机操作系统使用)转换为主机物理地址(虚拟机监控程序使用)。这第二层转换由虚拟机监控程序管理,允许客户机操作系统独立管理自己的页表。SLAT 通过最小化内存操作期间 VM 退出的需求来提高性能,从而减少开销并增强虚拟化效率。
下图展示了如何在用 Rust 编写的 Windows UEFI Blue Pill Type-1 虚拟机监控程序(代号:Illusion)中实现隐藏的 EPT 钩子。

图 2:扩展页表(EPT)钩子(Illusion)
ExceptionOrNmi (#GP, #PF, #BP, #UD) (0)、InitSignal (3)、StartupIpi (4)、Cpuid (10)、Getsec (11)、Hlt (12)、Invd (13)、Vmcall (18)、Vmclear (19)、Vmlaunch (20)、Vmptrld (21)、Vmptrst (22)、Vmresume (24)、Vmxon (27)、Vmxoff (26)、ControlRegisterAccesses (28)、Rdmsr (31)、Wrmsr (32)、MonitorTrapFlag (37)、Rdtsc (49)、EptViolation (48)、EptMisconfiguration (50)、Invept (53)、Invvpid (55)、Xsetbv (55)。UNUSABLE)。cargo install cargo-make。cargo make build-debug。cargo make build-release。cargo make run-debug。cargo make run-release。bcdedit.exe /set testsigning on 激活测试签名。bcdedit.exe /bootdebug {bootmgr} on
bcdedit.exe /bootdebug on
bcdedit.exe /debug on
bcdedit.exe /dbgsettings net hostip:w.x.y.z port:n。UEFI 蓝药丸虚拟机监控程序在以下条件下运行:
在设置此 UEFI 虚拟机监控程序时,根据系统的逻辑处理器/核心/线程数量配置文件非常重要。请编辑 global_const.rs 中的相关代码。
全局堆分配器在所有处理器/核心/线程之间共享,是一个预分配的内存池。栈大小按处理器/核心/线程分配。这种设计使得跟踪内存分配更加容易,特别是对于需要预分配缓冲区的钩子设置等任务。通过调整此文件中的设置,您可以确保分配足够的内存以容纳所有处理器,同时保持最佳性能和资源管理。
创建用于启动的虚拟 USB 驱动器
以管理员身份运行以下 PowerShell 脚本,在 USB 驱动器上创建新分区并将其格式化为 FAT32。此脚本将现有分区缩小 512 MB,并在 USB 驱动器上创建一个标签为“Hypervisor”的新分区。请根据您的环境修改驱动器号。或者,您也可以使用物理 USB 驱动器。
# Define the size to shrink in MB
$sizeToShrinkMB = 512
# Define the drive letter of the existing partition to shrink
$existingDriveLetter = "C"
# Define the drive letter and label for the new partition
$newDriveLetter = "D"
$newFileSystemLabel = "Hypervisor"
# Shrink the existing partition
$volume = Get-Volume -DriveLetter $existingDriveLetter
$partition = $volume | Get-Partition
Resize-Partition -DriveLetter $partition.DriveLetter -Size ($partition.Size - ($sizeToShrinkMB * 1MB))
# Create a new partition in the unallocated space
$disk = Get-Disk -Number $partition.DiskNumber
$newPartition = New-Partition -DiskNumber $disk.Number -UseMaximumSize -DriveLetter $newDriveLetter
# Format the new partition
Format-Volume -DriveLetter $newDriveLetter -FileSystem FAT32 -NewFileSystemLabel $newFileSystemLabel
Write-Output "Partition created and formatted successfully."
为 VMware Workstation 进行设置
设置 VMware Workstation
配置 VMware Workstation 在下次启动时进入固件设置,并使用物理 USB 驱动器作为启动设备:
VM -> Settings -> Hardware -> Add -> Hard Disk -> Next -> SCSI or NVMe (Recommended) -> Next -> Use a physical disk (for advanced users) -> Next -> Device: PhysicalDrive1 and Usage: Use entire disk -> Next -> Finish.VM -> Settings -> Hardware -> Add -> Hard Disk -> Next -> SCSI or NVMe (Recommended) -> Next -> Use a physical disk (for advanced users) -> Next -> Device: PhysicalDrive0 and Usage: Use individual partitions -> Select Partition -> Next -> Finish.VM -> Settings -> Add -> Serial Port -> Finish。Use output file: C:\Users\memN0ps\Documents\GitHub\illusion-rs\logs.txt 将 COM1 的串行端口输出重定向到 logs.txt 文件。(您可以选择任何位置,但首选项目目录内)。Power On to Firmware 启动虚拟机。Internal Shell (Unsupported option) 或 EFI VMware Virtual SCSI Hard Drive (1.0)。运行 PowerShell 脚本
执行以下 PowerShell 脚本以自动化设置过程。请根据您的环境修改路径。
### Change paths according to your environment ###
# Set build type to either 'debug' or 'release'
$buildType = "debug" # Use this line for a debug build
# $buildType = "release" # Uncomment this line and comment the above for a release build