尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CTF-Wiki 系统虚拟化专题:CPU 虚拟化原理、x86 缺陷与硬件辅助虚拟化(Intel VT-x / KVM)实战解析

CTF-Wiki 系统虚拟化专题:CPU 虚拟化原理、x86 缺陷与硬件辅助虚拟化(Intel VT-x / KVM)实战解析 文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载CPU 虚拟化是系统虚拟化技术中最核心的一环内存虚拟化与 I/O 虚拟化都直接依赖 CPU 提供的地址转换与 I/O 访问能力因此理解 CPU 虚拟化的实现路径是掌握虚拟化原理、乃至后续进行虚拟机逃逸VM Escape类 PWN 研究的基石。本文以 CTF-Wiki 中文站 CPU 虚拟化 一章为主体系统梳理「Trap Emulate」经典模型、x86 架构的虚拟化缺陷、纯软件虚拟化模拟执行、扫描修补、二进制翻译以及 Intel VT-x 硬件辅助虚拟化的完整技术脉络并结合仓库中 QEMU/KVM 相关章节的源码级证据帮助你建立起从 VMM 设计到 KVM 运行框架的完整认知。CPU 虚拟化在系统虚拟化中的地位计算机系统中最核心的组件是 CPU它直接控制着整个系统的运行内存访问即内存虚拟化与 I/O 操作即 I/O 虚拟化也都直接依赖于 CPU。因此CPU 虚拟化是整个系统虚拟化技术的核心其余资源的虚拟化均建立在对 CPU 行为的正确隔离与模拟之上。在虚拟化理论的发展史上Gerald J. Popek 与 Robert P. Goldberg 于 1974 年发表的论文《Formal Requirements for Virtualizable Third Generation Architectures》提出了满足虚拟化系统结构的 VMM 的三个充分条件即著名的Popek and Goldberg virtualization requirements这一框架至今仍是判断一个架构是否「可虚拟化」的经典标尺等价性essentially identical运行于 VMM 下的程序其行为应与直接运行于等价物理机上的同程序行为完全一致资源控制resource controlVMM 对虚拟资源具有完全的控制能力包括资源的分配、监控与回收效率性efficiency机器指令中经常使用的那一部分应在没有 VMM 干预的情况下直接在硬件上执行。围绕这三个条件CPU 虚拟化采用的最经典模型是「Trap Emulate」其实现手段是特权级压缩Ring CompressionHypervisor 运行在最高特权级上Guest VM 运行在低特权级上Guest VM 在硬件上直接执行非敏感指令当执行到敏感指令时便会陷入位于最高特权级的 Hypervisor由 Hypervisor 模拟该敏感指令的行为当发生 virtual CPU 调度时将 vCPU 的状态保存、恢复 Hypervisor 状态Hypervisor 完成其行为后继续调度下一个 virtual CPU恢复下一 vCPU 的状态并恢复执行。读者可以结合仓库中 虚拟化技术简介 一章阅读该章从「虚拟化是资源的逻辑表示」这一抽象定义出发推导出 Host/Guest、Type I/Type II Hypervisor、敏感指令、Trap Emulate 等概念并给出了 CPU 虚拟化、内存虚拟化、I/O 虚拟化的分类框架是理解本文的前置基础。x86 架构的虚拟化难题非特权敏感指令在虚拟化技术发展初期个人计算机领域广泛使用的 x86 架构并没有为经典的「Trap Emulate」模型提供良好支持存在系统虚拟化的支持缺陷——系统虚拟化并不能直接而有效地实现。Intel 分级保护环Protection Ring将 CPU 权限分为 ring0ring3操作系统内核运行在 ring0 权限用户进程运行在 ring3 权限。在「Trap Emulate」经典架构中Guest OS 全部运行在 ring3当涉及敏感指令时VM 触发 General Protection 异常由 VMM 截获并处理。然而问题在于不是所有敏感指令都是特权指令不是所有敏感指令都有触发异常让 VMM 介入的机会。x86 架构中一共有17 条非特权敏感指令它们直接违反了Popek and Goldberg virtualization requirements使得 x86 在硬件辅助虚拟化出现之前不是一个「可以直接虚拟化」的架构。例如在 x86 下若想在用户态用popf修改 eflags 的中断开关位IF硬件会直接忽视该操作而不会引起异常这令 VMM 完全无法介入。既然「硬件不够软件来凑」在硬件还未对虚拟化提供足够支持之前Hypervisor 只能从软件层面下功夫由此诞生了两种纯软件虚拟化技术「模拟执行」代表为 VMWare与「直接源代码改写」代表为 Xen。直到软件虚拟化技术发展成熟多年之后x86 架构对虚拟化的硬件支持才姗姗来迟——「硬件辅助虚拟化」Intel VT开始出现在人们的视野中。纯软件实现 CPU 虚拟化模拟与解释执行「模拟」Emulate技术的出现其实早于虚拟化。纯软件的模拟本质上就是编写能够呈现出与被模拟对象相同行为的应用程序从而达成运行非同构平台应用程序的效果。模拟技术不仅能够应用于程序级模拟还能应用于系统级模拟。CPU 运行的本质行为就是从 PC 寄存器所指的内存区域中不断取出指令、解码并执行。因此实现一个虚拟机最简单粗暴的方法便是模拟每一条指令对应的行为使得 VM 的行为对 VMM 而言完全可控。实现模拟技术的原理最简单——通过解释执行的方式模拟器程序不断地从内存中读取指令并模拟出每一条指令的效果。从某种程度上说每一条指令在执行时都完成了「陷入」因此模拟技术既能解决虚拟化的漏洞还能模拟与物理机不同架构的虚拟机。例如QemuQuick Emulator本质上便是一个模拟器其完整地模拟了一套包括各种外设在内的计算机系统。但基于解释执行的模拟技术有着致命缺点——性能极差每一条指令都需要经过 VMM 解析后再模拟执行哪怕最简单的一条指令也可能需要分解成多个步骤与多次内存访问效率极低。让我们重新审视在 x86 上使用模拟技术的原因非特权敏感指令的存在打破了Popek and Goldberg virtualization requirements但非特权敏感指令仅是少数大部分指令仍能直接在物理硬件上运行。因此基于模拟技术改进的虚拟化技术出现了扫描 修补与二进制翻译。扫描 修补虚拟化场景下的虚拟机大都与物理机有着相同的 ISA因此并没有必要采用纯模拟技术实现虚拟机而是可以让非敏感指令直接在硬件上执行通过某种方式让非特权敏感指令陷入 VMM从而重新实现 Trap Emulate 模型。扫描 修补Scan Patch正是这样一种技术它让非敏感指令直接在硬件上执行同时将系统代码中的敏感指令替换为跳转指令等能陷入 VMM 的指令使得 VM 在执行敏感指令时陷入 VMM由 VMM 模拟执行敏感指令的效果。基本执行流程如下VMM 在 VM 执行每段代码之前对其进行扫描解析每一条指令查找特权与敏感指令VMM 动态生成相应指令的补丁代码并将原敏感指令替换为一个外跳转以陷入 VMM从而在 VMM 中执行动态生成的补丁代码补丁代码执行结束后再跳转回 VM 中继续执行下一条代码。在「扫描 修补」技术中大部分代码都可以直接在物理 CPU 上运行性能损失较小但它同样存在缺陷特权指令与敏感指令仍通过模拟执行完成仍可能造成一定的性能损失代码补丁引入了额外的跳转破坏了代码的局部性局部性原理CPU 存取指令/数据的内存单元应当趋向于聚集在一个较小的区域VMM 需要维护一份补丁代码对应的原始代码副本造成额外开销。二进制翻译为进一步提高虚拟化性能「二进制代码翻译」Binary TranslationBT技术应运而生。类似于「扫描 修补」BT 同样会在运行时动态地修改代码但不同之处在于BT 技术以基本块只有一个入口和一个出口的代码块作为翻译的单位Emulator 对读入的二进制代码翻译输出为对应 ISA 的一个不包含特权指令与敏感指令的子集所构成的代码使其可以在用户态下安全运行Emulator 动态地为当前要运行的基本块开辟一块空间称之为翻译缓存translation cache其中存放翻译后的代码每一块 TC 与原代码以某种映射关系例如哈希表进行关联。二进制翻译技术与扫描修补技术的原理大体类似但差异明显二进制翻译技术会对所有代码进行翻译而扫描修补技术只 patch 掉敏感指令与特权指令扫描修补技术不会改变代码的整体结构仅将敏感与特权指令替换为能触发陷入 VMM 的指令而二进制翻译技术会直接改变一个基本块的代码整体结构例如翻译前基本块可能长度 40B翻译后变成 100B内部代码的相对位置也会发生变化。翻译方法大致分为两种简单翻译可理解为等效代码模拟实现较为简单但会让指令数量大幅膨胀等值翻译翻译的原代码与结果代码相同。理论上大多数指令都可以使用等值翻译直接在硬件上执行但这需要更复杂的动态分析技术。在相同 ISA 架构上大部分指令都可以直接进行等值翻译但以下几类例外指令类型翻译难点PC 相对寻址指令寻址与 PC 相关翻译后基本块结构改变需额外插入补偿代码保证寻址准确造成性能损失直接控制转换函数调用与跳转指令的目标地址需要被替换为生成代码的地址间接控制转换间接调用、返回、间接跳转的目标地址在运行时动态得到翻译时无法确定跳转目标特权指令简单特权指令可直接翻译为等值代码例如cli可直接翻译为置 vCPU flags 寄存器 IF 位为 0复杂指令则需深度模拟、利用跳转指令陷入 VMM通常造成性能开销由于二进制翻译使用了更复杂的过程还会引入更多需要额外处理的情形自修改代码Self Modifying Code程序在运行时修改自身执行的代码需要 Emulator 对新生成的代码进行重翻译自参考代码Self Referential Code程序在运行中读取自己代码段的内容需要额外处理使其读取原代码段内容而非翻译后的代码精确异常Precise Exceptions翻译代码执行过程中发生中断或异常需要将运行状态恢复到原代码执行到异常点时的状态再交给 Guest OS 处理。BT 技术很难完美处理此情况因为翻译后的代码与原代码已失去逐条对应关系。一个可行的方案是发生异常时回滚之后重新使用解释执行实时代码对实时性要求较高在模拟环境下运行会损失时间精确性目前暂时无法解决。硬件辅助虚拟化Intel VT-x本节以 Intel VT-x 为例介绍硬件辅助虚拟化hardware-assisted virtualization技术。概述Intel VT 技术是 Intel 为 x86 虚拟化提供的硬件支持其中用于辅助 CPU 虚拟化的是Intel VT-x技术它扩展了传统的 IA32 处理器架构为 IA32 架构的 CPU 虚拟化提供硬件支持。VT-x 为 Intel CPU 额外引入了两种运行模式统称为VMX 操作模式Virtual Machine eXtensions通过vmxon指令开启。这两种运行模式都独立拥有自己的分级保护环VMX Root OperationHypervisor 所工作的模式在此模式下可以访问计算机的所有资源并对 VM 进行调度VMX Non-Root OperationVM 所工作的模式在此模式下仅能访问非敏感资源对敏感资源的访问例如 I/O 操作会使得 CPU 退出 Non-Root 模式并陷入 Hypervisor由 Hypervisor 处理后再重新进入 Non-Root 模式恢复 VM 运行。由此可以对 Root 模式与 Non-Root 模式间的切换行为进行定义VM-EntryHypervisor 保存自身状态信息切换到 VMX Non-Root 模式载入 VM 状态信息恢复 VM 执行流VM-ExitVM 运行暂停并保存自身状态信息切换到 VMX Root 模式载入 Hypervisor 状态信息执行相应的处理函数。由于 Non-Root 模式与 Root 模式都各自拥有分级保护环Host OS 与 Guest OS 都可以不加修改地在自己对应的模式下直接在硬件上运行只有在 Guest OS 访问敏感资源或 Host OS 调度 VM 时才发生切换。这在确保 VM 高性能的同时实现了Trap Emulate模型也解决了 x86 架构的虚拟化漏洞。VMCS虚拟机的控制状态结构VMCSVirtual-Machine Control Structure是用以保存 CPU 虚拟化所需相关状态的一块内存每个 virtual CPU 对应有一个 VMCS。同一时刻一个物理 CPU 只能与一个 VMCS 绑定反之亦然但在不同时刻可以将 VMCS 绑定到不同的物理 CPU 上这称之为 VMCS 的迁移Migration。与 VMCS 绑定、解绑相关的指令如下InstructionDescriptionVMPTRLD VMCS 地址将指定的 VMCS 与执行该指令的 CPU 进行绑定VMCLEAR将执行该指令的 CPU 与其 VMCS 进行解绑VT-x 将 VMCS 定义为一个最大不超过 4KB 的内存块且应与 4KB 对齐其内容格式可示意如下struct VMCS { /* 版本号4字节 */ uint32_t vmcs_revision_identifier:31, shadow_vmcs_indicator:1; /* 中止标识4字节 * 当 VM-Exit 失败时便会产生 VMX 中止并在此处存放原因 */ uint32_t vmx_abort_indicator; /* 数据域 */ struct VMCSData vmcs_data; };VMCS 数据域存放着 VMCS 的主要信息分为以下六个子域Guest-state area保存 VM 寄存器状态在 VM-entry 时加载在 VM-exit 时保存Host-state area保存 Hypervisor 寄存器状态在 VM-exit 时加载VM-execution control fields控制Non-Root模式下的处理器行为VM-entry control fields控制VM-Entry过程中的某些行为VM-exit control fields控制VM-Exit过程中的某些行为VM-exit information fields保存VM-Exit的基本原因及其他详细信息在一些处理器上该域为只读域。对 VMCS 的读写依靠以下两条指令InstructionDescriptionVMREAD 索引读 VMCS 中「索引」指定的域VMWRITE 索引 数据向 VMCS 中「索引」指定的域写入数据这里的索引并非偏移值而是 Intel 为数据域中每个字段定义的独特索引值例如 Guest State Area 中 ES 段选择子的索引值为0x00000800。把所有域的索引都背下来并不现实最好的办法还是多多查表——可查阅 Intel SDM 中《Intel 64 and IA-32 Architectures Software Developers Manual Volume 3C: System Programming Guide, Part 3》的 VMCS 字段定义部分。VMX 操作模式的生命周期作为传统 IA32 架构的扩展VMX 操作模式在默认下是关闭的只有当 VMM 需要使用硬件辅助虚拟化功能时才会使用 Intel 提供的两条新指令来开关 VMX 操作模式VMXON开启 VMX 操作模式VMXOFF关闭 VMX 操作模式。Intel SDM 中描述的 VMX 生命周期如下软件通过VMXON指令进入 VMX 操作模式VMM 通过VM entries进入 Guest VM单次只能执行一个 VM。VMM 通过VMLAUNCH第一次进入 VM与VMRESUME从 VMM 中恢复到 VM指令来使能VM entry通过VM exits重获控制权VM exits通过 VMM 指定的入口点移交控制权VMM 对 VM 的退出原因进行响应后通过VM entry返回到 VM 中当 VMM 想要停止自身运行并退出 VMX 操作模式时通过VMXOFF指令完成。深入VM entry与VM exit的实现细节它们分别进行了如下动作VM entry从 Hypervisor 切换到 VM检查 VMCS 合法性各字段值是否合法加载 VMCS 的Guest-state area中各字段到对应寄存器加载指定的 MSR设置 VMCS 的状态为launched根据需要通过写 VMCS 的VM-entry Interruption-Information向 VM 进行事件注入如异常、异步中断等。VM exit从 VM 切换到 Hypervisor将 VM 退出的原因与详细信息写入 VMCS 的VM-exit information fields将 VM 的寄存器保存至 VMCS 的Guest-state area从 VMCS 的Host-state area中恢复 Host 寄存器加载指定 MSR。补充概念MSRModel Specific Register是 x86 下一组用于控制 CPU 运行、功能开关、调试、跟踪程序执行、监测 CPU 性能等用途的寄存器。例如syscall指令便是通过 MSR 寄存器获取内核系统调用的入口点。每个 MSR 寄存器都有一个 idMSR Index可通过RDMSR与WRMSR指令读写指定的 MSR 寄存器其详细信息记录在 Intel SDM Volume 4 中。KVM 与 QEMU-KVM从硬件支持到完整虚拟化环境Kernel-based Virtual MachineKVM是一个自 Linux 2.6.20 后集成进 kernel 的开源系统虚拟化内核模块本质上是一个依赖于硬件辅助虚拟化、位于 kernel 中的 Hypervisor——或者说KVM 将 Linux kernel 变成了 Hypervisor并提供了用户态操作 VM 的接口/dev/kvm用户态程序可以通过 ioctl 指令操作 KVM。但 KVM 本身仅提供了 CPU 与内存的虚拟化不能构成一个完整的虚拟化环境。因此自然的思路是复用现有的全虚拟化方案将模拟 CPU 与内存的工作交由 KVM 完成从而直接借助硬件辅助虚拟化提升虚拟机性能。QEMU 便支持通过 KVM 创建与运行虚拟机。利用 QEMU KVM 进行虚拟化的方案如下QEMU 通过 ioctl 进入内核态将控制权移交 KVM由 KVM 进行 VM 的运行产生 VM-Exit 时KVM 接管判断原因并决定继续运行还是交由 QEMU 处理若是后者恢复到用户态 QEMU 中的处理代码进行相应处理之后退出或回到第一步。这个基本执行框架实际上对应 QEMU 源码accel/kvm/kvm-all.c中的kvm_cpu_exec()函数int kvm_cpu_exec(CPUState *cpu) { //... cpu_exec_start(cpu); do { //... /** * 开始运行 VM本质上就是 ioctl(kvm_fd, KVM_RUN) * 当产生 VM-Exit 时首先在 KVM 中完成处理 * 若产生 IO则退出内核态即恢复到这里接下来进入到用户态的处理 */ run_ret kvm_vcpu_ioctl(cpu, KVM_RUN, 0); //... if (run_ret 0) { /** * 返回值小于 0 说明 VM 运行出了些问题 * 这里会简单处理后 break 打破大循环 */ //... } trace_kvm_run_exit(cpu-cpu_index, run-exit_reason); /* 这里就是一个大的 switch根据退出的原因进行不同的处理就不放完整代码了 */ switch (run-exit_reason) { case KVM_EXIT_IO: DPRINTF(handle_io\n); /* Called outside BQL */ kvm_handle_io(run-io.port, attrs, (uint8_t *)run run-io.data_offset, run-io.direction, run-io.size, run-io.count); ret 0; break; case KVM_EXIT_MMIO: DPRINTF(handle_mmio\n); /* Called outside BQL */ address_space_rw(address_space_memory, run-mmio.phys_addr, attrs, run-mmio.data, run-mmio.len, run-mmio.is_write); ret 0; break; //... default: DPRINTF(kvm_arch_handle_exit\n); ret kvm_arch_handle_exit(cpu, run); break; } } while (ret 0); /* 运行结束收尾处理 */ // ...这段代码清晰地展示了 QEMU-KVM 的执行循环kvm_vcpu_ioctl(cpu, KVM_RUN, 0)触发 VM 运行VM-Exit 后依据run-exit_reason分派处理KVM_EXIT_IO走kvm_handle_io()、KVM_EXIT_MMIO走address_space_rw()其余退出原因交给kvm_arch_handle_exit()处理完毕后继续循环运行 VM。仓库中 QEMU 设备模拟 一章对KVM_EXIT_IO与KVM_EXIT_MMIO两条处理路径进行了更深一层的展开MMIO 处理会调用address_space_rw()先将全局地址空间address_space_memory展开成FlatView后再执行对应的读写操作。延伸阅读与参考内存虚拟化GPA→HVA→HPA 的多级地址转换、影子页表与 EPT 等技术细节见 内存虚拟化I/O 虚拟化平台设备模拟、用户空间设备模拟、设备直通与 virtio 半虚拟化模型见 IO 虚拟化虚拟化的总体框架与 Popek and Goldberg 三条件推导见 虚拟化技术简介QEMU 设备模拟与 MMIO 处理源码细节见 QEMU 设备模拟本文理论框架参考了《系统虚拟化原理与实现》Intel 开源软件技术中心及 Intel SDM Volume 3C 中关于 VMX、VMCS 与 VM-Entry/VM-Exit 的官方规范描述。赞分享文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载相关推荐ctf-wiki CPU 虚拟化从 Trap Emulate、Intel VT-x 到 KVM/QEMU-KVM 的完整技术脉络ctf wiki CPU 虚拟化从 Trap Emulate、Intel VT x 到 KVM/QEMU KVM 的完整技术脉络 CPU 虚拟化是系统虚拟文档网络安全教程ctf-wiki 虚拟化专题I/O 虚拟化——设备模拟、virtio 半虚拟化与 IOMMU 深度解析ctf wiki 虚拟化专题I/O 虚拟化——设备模拟、virtio 半虚拟化与 IOMMU 深度解析 现实的外设资源有限且虚拟机VM未必需要、甚至不应文档网络安全教程protobuf-ts完全指南TypeScript中的Protobuf与RPC终极解决方案protobuf ts完全指南TypeScript中的Protobuf与RPC终极解决方案 protobuf ts是TypeScript生态中处理Protoc上一篇MusicFree设置页面Setting组件的组织与实现下一篇如何安装 OrcaSlicerWindows/macOS/Linux 完整切片软件安装与配置教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表