zoukankan      html  css  js  c++  java
  • 3_基本框架_VMXON

    原理参考 3卷 23.7节等

    1570889738491

    本节实施流程参考Intel手册: 3卷 31.5节

    1 vt整体框架;

    1570803617636

     

    首先 开锁:

    1 开启 Cr4.[VMXE]:

    上一节,检测了 VMX 需要的环境;最后一个 CR4.[13/VMXE] 只检测了是否已经被开启(有别的虚拟机);

    但是 没有在 CR4.[13/VMXE] ==0 的时候去开启。

    所以 这里 开始 开锁;打开 CR4.[13]

    放在 驱动加载函数中。

    • 代码:

      NTSTATUS StartVirtualTechnology()

      {
      _CR4 uCr4;
      if(!IsVTEnabled())
      {
      return STATUS_UNSUCCESSFUL;
      }
      *((PULONG)&uCr4) = Asm_GetCr4();// 获取原来的 cr4;
      uCr4.VMXE =1;// VMXE =1 开启。
      Asm_SetCr4(*(PULONG)&uCr4); // 设置回去

      return STATUS_SUCCESS;
      }

     

     

    2开始 进入 VMXON:

    接下来的最简流程:(参考白皮书 3卷31.5节)

    1570806491191

    这里 红色部分是需要实现的部分:

    即:

    • 需要申请一块最大4kb对齐的非分页内存;并且 确保大小够(直接申请4kb,先不考虑效率)

    • 用 VMCS revision identifier (在capability MSRs // MSR 480h 的低32位) 初始化 WMXON region (the first 31 bits)

    • 清理 第 31 bit 位0

     

    首先需要一开内存来管理 host 信息(cpu 管理;我们提供内存即可)

    然后需要设置版本号

    1570805015453

    代码:

    NTSTATUS StartVirtualTechnology()

    {
    _CR4 uCr4;
    _EFLAGS uEflags;
    if(!IsVTEnabled())
    {
    return STATUS_UNSUCCESSFUL;
    }
    *((PULONG)&uCr4) = Asm_GetCr4();//get cr4;
    uCr4.VMXE =1;// VMXE =1 enable
    Asm_SetCr4(*(PULONG)&uCr4); // set

    g_VMXCPU.pVMXONRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmx');// para@3 is digit value
    RtlZeroMemory(g_VMXCPU.pVMXONRegion,0x1000);// initial memory
    *(PULONG)g_VMXCPU.pVMXONRegion =1;//set revision; -- the first 32bits of VMXONRegion; clear the no.32bit
    g_VMXCPU.pVMXONRegion_PA = MmGetPhysicalAddress(g_VMXCPU.pVMXONRegion);// get physical address


    Vmx_VmxOn(g_VMXCPU.pVMXONRegion_PA.LowPart,g_VMXCPU.pVMXONRegion_PA.HighPart);
    *((PULONG)&uEflags) = Asm_GetEflags();

    if(uEflags.CF!=0)// the flag to identify state of success or not
    {
    Log("ERROR:VMXON指令调用失败!",0);
    ExFreePool(g_VMXCPU.pVMXONRegion);
    return STATUS_UNSUCCESSFUL;
    }

    return STATUS_SUCCESS;
    }

     

    最后 关锁:

    1 关闭 VMXOFF:

     

    2 恢复 CR4.[VMXE]:

    设置 CR4.[13/VMXE] ==0 的时候关闭;

    放在驱动卸载函数中

    • 代码:

      NTSTATUS StopVirtualTechnology()

      {
      _CR4 uCr4;

      Vmx_VmxOff();

      *((PULONG)&uCr4) = Asm_GetCr4();// get cr4;
      uCr4.VMXE =0;// VMXE =0 disable
      Asm_SetCr4(*(PULONG)&uCr4); // set;

      // free page; in kernel nonpage its not freed automatic;
      ExFreePool(g_VMXCPU.pVMXONRegion);


      return  STATUS_SUCCESS;
      }

       

     

    初步效果:

    1570808638097

     

    整体代码:

    .cpp(开启 、关闭 VMX的函数实现)

    #include "stdafx.h"



    VMX_CPU g_VMXCPU;

    BOOLEAN IsVTEnabled()
    {
    ULONG uRet_EAX, uRet_RCX,uRet_EDX,uRet_EBX;
    _CPUID_ECX uCPUID;
    _CR0  uCr0;
    _CR4  uCr4;
    IA32_FEATURE_CONTROL_MSR msr;

    // 1. check CPUID .[5] VMXON is enabled?
    Asm_CPUID(1,&uRet_EAX,&uRet_EBX,&uRet_RCX,&uRet_EDX); // eax-->1 ; cpuid; check retRegValues;
    *((PULONG)&uCPUID) = uRet_RCX;
    if(uCPUID.VMX !=1)
    {
    Log("ERROR:当前 CPU 不支持VT",0);
    return FALSE;
    }

    // 2. check MSR 3ah 
    *((PULONG)&msr) = (ULONG) Asm_ReadMsr(MSR_IA32_FEATURE_CONTROL);// 0x3ah
    if(msr.Lock!=1)
    {
    Log("ERROR:VT 指令未被锁定",0);
    return FALSE;
    }

    // 3. check CR0CR4
    *((PULONG)&uCr0) = Asm_GetCr0();
    *((PULONG)&uCr4) = Asm_GetCr4();

    if(uCr0.PE!=1 || uCr0.PG!=1 || uCr0.NE!=1)
    {
    Log("ERROR:这个CPU 所处的环境不是页保护模式",0);
    return FALSE;
    }
    if(uCr4.VMXE ==1)
    {
    Log("ERROR:这个CPU 已经开启了VT,可能有别的驱动占用;请检查关闭再试!",0);
    return FALSE;

    }
    else
    {

    }
    Log("Checked, the Env is Prepared!",0);
    return TRUE;
    }

    NTSTATUS StartVirtualTechnology()
    {
    _CR4 uCr4;
    _EFLAGS uEflags;
    if(!IsVTEnabled())
    {
    return STATUS_UNSUCCESSFUL;
    }
    *((PULONG)&uCr4) = Asm_GetCr4();//get cr4;
    uCr4.VMXE =1;// VMXE =1 enable
    Asm_SetCr4(*(PULONG)&uCr4); // set

    g_VMXCPU.pVMXONRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmx');// para@3 is digit value
    RtlZeroMemory(g_VMXCPU.pVMXONRegion,0x1000);// initial memory
    *(PULONG)g_VMXCPU.pVMXONRegion =1;//set revision; -- the first 32bits of VMXONRegion; clear the no.32bit
    g_VMXCPU.pVMXONRegion_PA = MmGetPhysicalAddress(g_VMXCPU.pVMXONRegion);// get physical address


    Vmx_VmxOn(g_VMXCPU.pVMXONRegion_PA.LowPart,g_VMXCPU.pVMXONRegion_PA.HighPart);
    *((PULONG)&uEflags) = Asm_GetEflags();

    if(uEflags.CF!=0)// the flag to identify state of success or not
    {
    Log("ERROR:VMXON指令调用失败!",0);
    ExFreePool(g_VMXCPU.pVMXONRegion);
    return STATUS_UNSUCCESSFUL;
    }

    return STATUS_SUCCESS;
    }

    NTSTATUS StopVirtualTechnology()
    {
    _CR4 uCr4;

    Vmx_VmxOff();

    *((PULONG)&uCr4) = Asm_GetCr4();// get cr4;
    uCr4.VMXE =0;// VMXE =0 disable
    Asm_SetCr4(*(PULONG)&uCr4); // set;

    // free page; in kernel nonpage its not freed automatic;
    ExFreePool(g_VMXCPU.pVMXONRegion);


    return  STATUS_SUCCESS;

    }

    .c (驱动文件,调用VMX开启关闭函数)

    #include "stdafx.h"


    EXTERN_C void Asm_xx();
    EXTERN_C BOOLEAN IsVTEnabled();
    EXTERN_C NTSTATUS StartVirtualTechnology();
    EXTERN_C NTSTATUS StopVirtualTechnology();
    VOID DriverUnLoad(PDRIVER_OBJECT driver)
    {

    StopVirtualTechnology();
    DbgPrint("VT stopping ....! ");
    DbgPrint("Driver is unloading...r ");
    }
    NTSTATUS DriverEntry(
    PDRIVER_OBJECT driver ,
    PUNICODE_STRING RegistryPath)
    {
    Asm_xx();
    DbgPrint("Driver Entered! ");
    StartVirtualTechnology();
    DbgPrint("VT running....! ");
    driver->DriverUnload = DriverUnLoad;
    return STATUS_SUCCESS;
    }


    感谢 周壑老师的讲解

  • 相关阅读:
    KDJ回测
    利用网易获取所有股票数据
    利用东方财富网获取股票代码
    python发邮件
    用指针向数组插入元素
    冒泡排序
    Hadoop的安装与配置
    关于执行memcached报错问题
    tomcat Linux安装
    网易CentOS yum源
  • 原文地址:https://www.cnblogs.com/leibso-cy/p/VT_VMXON.html
Copyright © 2011-2022 走看看