VT虚拟化技术笔记(part 1)

2022-03-13 0 903

VT技术笔记(part 1)

  • 最近在学习VT技术,想把学习过程中记录的笔记分享出来。技术不精有不对的地方还望指正。代码会发到https://github.com/smallzhong/myvt这个仓库中,目前还在施工中,还没写完。欢迎star,预计这个月内完工。

VT概述

  • VT虚拟化技术笔记(part 1)

    VT技术的大致含义如上。一个CPU上有vm monitor和guest。在guest中感受不到自己跑在虚拟环境中。执行普通的操作时在guest中的操作和未开启vt时的操作并没有什么不同,但是在执行一些特殊的指令或者进行一些特殊的操作,如执行cpuid指令、切换cr3指令、读写msr寄存器指令、触发异常时,会将控制权交还给vm monitor,通过vm monitor确定应该如何让该指令或者操作得到执行。在云服务器的搭建中可以使用该技术让一台实体机上可以跑多台虚拟机。而该技术也可以做到无痕对一些指令进行高权限的hook。甚至可以通过ept技术进行对指定地址的无痕hook。

VT执行的大体流程

  • 该流程的描述出自B站周壑的VT教学视频中,讲得非常通俗易懂。VT的开启与关闭大致分为开锁、开柜门、拔电源、选中机器、装机、开机、拔电源、关柜门、关锁9个步骤。这9个步骤的具体描述如下。此处为大体的描述,在后面会对每一个步骤的具体细节进行具体的说明。

VT虚拟化技术笔记(part 1)

  1. 开锁:检测是否支持VT
  2. 开柜门:vmxon。需要申请一块内存然后把这块内存的lowpart和highpart作为参数调用vmxon。注意这块内存的开头要填入一个特定的msr寄存器中的值。注意这里vmxon修改cr4寄存器之后,cr0寄存器的页保护和段保护位都不能再置位,如果试图修改cr0的页保护或者段保护位,会触发异常蓝屏。
  3. 拔电源:vmclear
  4. 选中机器:vmptrload,相当于一个指针。需要通过vmptrload来指向某个机器。如果当前有多个机器的话,在各个机器之间的切换操作也需要用到vmptrload。
  5. 装机:设置vmcs。也是要申请一块内存,然后在这块内存里面填入开启虚拟机时虚拟机使用的一些寄存器。要注意这里不能直接操作这块内存区域,要用vmwrite来操作。因为随着版本的更新,原来在这块内存区域的东西可能后来就不在了。vmwrite保证兼容性。
  6. 开机vmlaunch
  7. 拔电源vmclear
  8. 关柜门vmoff

检测是否支持VT(开锁)

  • 在intel手册31.5章中详细描述了vmm的开启过程。

    VT虚拟化技术笔记(part 1)

    1. 通过cpuid指令查询CPU是否支持VT
    2. 通过一些特定的MSR寄存器(在31.5.1中有介绍)来确认是否支持开启VT。
    3. 申请一块非分页内存,用来存放vmxon区域。其大小在IA32_VMX_BASIC这个寄存器中指定。该内存要4kb对齐(后12位全为0)。实际申请时申请一个页的大小的非分页内存即可。
    4. 初始化vmxon区域的版本编号(前4个字节)。版本编号通过IA32_VMX_BASIC这个寄存器的低4字节获取。实际实验时发现这个数为1,理论上把上一步申请到的内存前四字节置1即可,但为了兼容最好还是从寄存器中取值出来。
    5. 给cr0和cr4寄存器的特定位置置位,使得其满足如下要求
      • IA32_VMX_CR0_FIXED0 寄存器中为1的位,在cr0中必须为1
      • IA32_VMX_CR0_FIXED1 寄存器中为0的位,在cr0中必须为0
      • IA32_VMX_CR4_FIXED0 寄存器中为1的位,在cr4中必须为1
      • IA32_VMX_CR4_FIXED1 寄存器中为0的位,在cr4中必须为0
    6. 确认IA32_FEATURE_CONTROL寄存器被正确置位。该寄存器的具体细节可以通过《处理器虚拟化技术》2.3.2.1找到。

      VT虚拟化技术笔记(part 1)

      也就是说,该寄存器的bit0是lock为,bit2是outside位。必须保证这两位均为1才可以开启VT。可以大致通过读取该寄存器后将其&5,判断是否两个位均为1。

    7. 执行vmxon指令,传进去的参数是一个指向存放vmxon区域的物理地址的指针。如果该指令成功,那么rflags.cf=0,否则rflags.cf=1。
  • 由上可写出检测是否支持VT的代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//检测Bios是否开启VT
BOOLEAN VmxIsCheckSupportVTBIOS()
{
    ULONG64 value = __readmsr(IA32_FEATURE_CONTROL);
    return (value & 0x5) == 0x5;
}
//检测CPU是否支持VT
BOOLEAN VmxIsCheckSupportVTCPUID()
{
    int cpuidinfo[4];
    __cpuidex(cpuidinfo, 1, 0);
    //CPUID 是否支持VT ecx.vmx第6位 如果为1,支持VT,否则不支持
    return (cpuidinfo[2] >> 5) & 1;
}
//检测CR4VT是否开启,如果为1 代表已经开启过了,否则没有开启
BOOLEAN VmxIsCheckSupportVTCr4()
{
    ULONG64 mcr4 = __readcr4();
    //检测CR4 VT是否开启,cr4.vmxe如果第14位为1,那么VT已经被开启,否则可以开启
    return ((mcr4 >> 13) & 1) == 0;
}
void checkVT()
{
    if (VmxIsCheckSupportVTCPUID())
    {
        DbgPrintEx(77, 0, "[db]:VmxIsCheckSupportVTCPUID  number = %drn", KeGetCurrentProcessorNumber());
    }
    if (VmxIsCheckSupportVTBIOS())
    {
        DbgPrintEx(77, 0, "[db]:VmxIsCheckSupportVTBIOS  number = %drn", KeGetCurrentProcessorNumber());
    }
    if (VmxIsCheckSupportVTCr4())
    {
        DbgPrintEx(77, 0, "[db]:VmxIsCheckSupportVTCr4  number = %drn", KeGetCurrentProcessorNumber());
    }
}

vmxon(开柜门)

  • 申请一块4KB对齐的非分页内存,作为vmxon的参数。
1
2
3
4
PHYSICAL_ADDRESS lowphys,heiPhy;
lowphys.QuadPart = 0;
heiPhy.QuadPart = -1;
pVcpu->VmxOnAddr = MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, lowphys, heiPhy, lowphys, MmCached);
  • 设置vmxon区域。这一块的说明在intel白皮书24.11.5中。这一块内存是操作系统使用的。在申请区域之后要rtlzeromemory一下,防止没有挂页。其他位都置零即可,之后操作系统进行虚拟机的管理的时候会使用到这块内存。我们需要设置的只有头四个字节。要把msr中 IA32_VMX_BASIC 这个寄存器的低4字节填入vmxon的头4字节。否则vmxon的执行会出错。基本上这个寄存器的低4字节会是1。之后随着版本的更新可能会有变化。

    VT虚拟化技术笔记(part 1)

    1
    2
    ULONG64 vmxBasic = __readmsr(IA32_VMX_BASIC);
    *(PULONG)pVcpu->VmxOnAddr = (ULONG)vmxBasic;
  • 在设置完vmxon区域之后,还需最后一步即可vmxon。需要根据msr寄存器中的指示进行cr0和cr4寄存器的设置。

    VT虚拟化技术笔记(part 1)

    具体解释在附录A中。

    VT虚拟化技术笔记(part 1)

    简单解释就是在进行vmxon之前, IA32_VMX_CR0_FIXED0 寄存器中为1的值,在cr0中必须为1、 IA32_VMX_CR0_FIXED1 寄存器中为0的值,在cr0中必须为0。cr4同理。那么可以通过 cr0 = cr0 | IA32_VMX_CR0_FIXED0 & IA32_VMX_CR0_FIXED1 操作将cr0和cr4进行置位。具体代码如下。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ULONG64 vcr00 = __readmsr(IA32_VMX_CR0_FIXED0);
    ULONG64 vcr01 = __readmsr(IA32_VMX_CR0_FIXED1);
    ULONG64 vcr04 = __readmsr(IA32_VMX_CR4_FIXED0);
    ULONG64 vcr14 = __readmsr(IA32_VMX_CR4_FIXED1);
    ULONG64 mcr4 = __readcr4();
    ULONG64 mcr0 = __readcr0();
    mcr4 |= vcr04;
    mcr4 &= vcr14;
    mcr0 |= vcr00;
    mcr0 &= vcr01;
    __writecr0(mcr0);
    __writecr4(mcr4);
  • 在进行以上步骤之后,可以通过vmxon打开柜门。
    1
    int error = __vmx_on(&pVcpu->VmxOnAddrPhys.QuadPart);

申请vmcs内存并vmclear(拔电源)

  • 首先申请vmcs内存。和vmxon内存类似,这一块内存的头4个字节也要填入 IA32_VMX_BASIC 的低4个字节。vmcs中保存的是虚拟机的各种寄存器和控制区域、vmexit控制区域等。在装机过程中要通过vmwrite进行vmcs的设置。
  • 申请vmcs内存并设置头4字节为 IA32_VMX_BASIC 的低4字节之后,通过vmclear指令进行初始化。传入的参数与vmxon的参数类似,是指向申请的内存的物理地址的一个指针。vmclear的用法如下
    1
    __vmx_vmclear(&pVcpu->VmxcsAddrPhys.QuadPart);

vmptrload(选中机器)

  • vmptrload 指令和vmxon、vmclear类似,传入的是指向vmcs结构的物理地址的一个指针。只有执行了这行指令之后才能通过 vmwrite 进行vmcs结构的填写。代码如下
    1
    __vmx_vmptrld(&pVcpu->VmxcsAddrPhys.QuadPart);

设置vmcs(装机)

  • VT虚拟化技术笔记(part 1)

    24章中描述了需要设置的VMCS字段。大体包括如下几部分

    1. Guest state fields
    2. Host state fields
    3. vm-control fields
      1. vm execution control
      2. vm exit control
      3. vm entry control

​ 除这5个区域之外,vmcs还有一个区域是vm exit信息区域。这个区域是只读的,存储的是vmx指令失败后失败代码的编号。

  • VMCS字段的设置是VT中最为繁琐的一步。对于VMCS中一些具体字段应该如何进行设置,会在下一篇文章中进行说明。

参考文献

  1. intel白皮书
  2. 邓志《处理器虚拟化技术》
  3. B站周壑VT教学视频
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

注:在使用本系统时,使用方必须在国家相关法律法规范围内并经过国家相关部门的授权许可,禁止用于一切非法行为。使用用途仅限于测试、实验、研究为目的,禁止用于一切商业运营,本团队不承担使用者在使用过程中的任何违法行为负责。

83源码 技术教程 VT虚拟化技术笔记(part 1) https://www.83ym.com/151.html

认准唯一TG:@ym830

常见问题
  • 站内所有资源,针对不同等级VIP会员可直接下载,特殊资源商品会注明是否免费,指会员所享有根据选择购买的会员选项所享有的特殊服务,具体以本站公布的服务内容为准。
查看详情
  • 按照我国的法律规定,运营网络棋牌首先需要成立一个注册正规备案的公司,然后申请网站备案、文网文、ICP等等,这些证件缺一不可。 一.注册公司 在当地工商进行注册,公司名称以“XX科技有限公司”为名,如:富裕棋牌经营范围填写“计算机软硬件、网络设备的设计开发与购销”。 二.域名及网站备案 在国内从事网站经营活动就必须经过相关部门的备案,因此棋牌运营商在购买了域名后,就要到当地网监局办理网站备案,或者请服务器提供商代为备案。 三.申请文网文 文网文全称为网络文化经营许可证,是从事经营性互联网文化活动所必需的资质。一般是需要到当地省一级(省、直辖市、自治区)的文化行政部门提出申请,并经由当地的文化行政部门合法批准。次资质要求申请公司注册资金必需达到1000万,并提供游戏版权证明文件。 四.申请ICP ICP又称为增值电信业务许可证,所有网络游戏运营商均需要办理ICP许可证,此证件要求公司注册资金1000万,需到当地市级通讯管理局办理。 五.申请文网游——游戏备案 根据《网络游戏管理暂行办法》(文化部第49号)的规定,国产网络游戏在上网运营之日起30日内应当按规定向国务院文化行政部门履行备案手续。 以上就是网络棋牌游戏正规运营所必需的资质证明。一般作为正规有实力的棋牌游戏开发公司,不光要具备所有的正规资质,而且会对投资者、代理商等合作伙伴给予相关指导和协助,与合作伙伴携手共赢!
查看详情

相关文章

猜你喜欢
官方客服团队

为您解决烦忧 - 24小时在线 专业服务