VT系列:VMCS表填写

本文介绍了VT系列中的VMCS表格填写,包括5个章节:客户机状态区、宿主机状态区、虚拟机运行控制域、VMENTRY和VMEXIT行为控制域。在使用VMLaunch指令时,需要确保VMCS正确设置,以便在虚拟机内部正确执行后续代码。文章详细阐述了开启和关闭VT的步骤,以及在处理VMCALL和VMOFF时如何控制EIP。代码来源于看雪小宝的教程,目前适用于单核x86 Intel CPU系统。
摘要由CSDN通过智能技术生成

一共有5章表要填 分别是:

1.Guest State Area (客户机) 填写虚拟机相关的信息

2.Host State Area(宿主机) 填写真实机的相关信息

3.VM-Execution Control Fields(虚拟机运行控制域) 定义了我们的VT能拦截什么东西 指令 异常 操作。

4.VMEntry Control Fields(VMENTRY行为控制域) 写死的 只有x86 x64的区别

5.VMExit Control Fields(VMEXIT行为控制域) 写死的 只有x86 x64的区别

 

在填写之前需要注意一件事 就是当我们使用VMLanuch指令的时候 在VMLanuch下面的指令是执行不到的了

 

比如:

VMLanuch

Mov eax,1

Ret

 

如果VMLanuch(VVMCALL后VMOFF)成功那么Mov eax,1 和Ret是不会执行了,因为这个时候已经跑到虚拟机里面去执行了

那么我们需要得到Mov eax,1的地址当调用VMLanuch(VMCALL后VMOFF)之后让虚拟机的EIP指向mov eax,1的地址继续执行后面的代码

 

在填写VMCS中有一部分是麻烦的 NewBuilePill里面将这块封装成了模块

这里我们直接使用Newbluepill里面的代码

Common.cpp 和 common.h

 

 

步骤为:

1.判断处理器是否支持虚拟化

2.申请VMXON和VMCS的内存区域

3.设置版本号信息以及开启虚拟机汇编指令

4.保存客户机原始寄存器、填写VMCS表项

5.测试

6.关闭虚拟化的代码 调用VMCall 设置返回EIP 关闭虚拟化指令(CR4) 释放申请到的内存

 

这些需要一个结构保存申请到的VMXON VMCS的内存地址

typedef struct _VMX_CPU
{
         PVOIDpVMXONRegion; //VMXON的虚拟地址
         PHYSICAL_ADDRESSpVMXONRegion_PA; //VMXON的物理地址
         PVOIDpVMCSRegion; //VMCS的虚拟地址
         PHYSICAL_ADDRESSpVMCSRegion_PA; //VMCS的物理地址
         PVOIDpHostEsp; //主机的Esp
 
         BOOLEANbVTStartSuccess; //用于记录是否开启成功
}VMX_CPU,*PVMX_CPU;

增加两个函数

开启VT和关闭VT

NTSTATUS StartVirtualTechnology();
NTSTATUS StopVirtualTechnology();

实现如下:

#include "stdafx.h"
#include "vtsystem.h"
#include "vtasm.h"
#include "exithandler.h"
#include "common.h"

VMX_CPU g_VMXCPU;

NTSTATUS AllocateVMXRegion()
{
	PVOID pVMXONRegion;
	PVOID pVMCSRegion;
	PVOID pHostEsp;

	//必须4kb
	pVMXONRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmon'); //4KB
	if (!pVMXONRegion)
	{
		Log("ERROR:申请VMXON内存区域失败!",0);
		return STATUS_MEMORY_NOT_ALLOCATED;
	}
	//最好zero
	RtlZeroMemory(pVMXONRegion,0x1000);

	//4kb就够了
	pVMCSRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmcs');
	if (!pVMCSRegion)
	{
		Log("ERROR:申请VMCS内存区域失败!",0);
		ExFreePoolWithTag(pVMXONRegion,0x1000);
		return STATUS_MEMORY_NOT_ALLOCATED;
	}
	//最好zero
	RtlZeroMemory(pVMCSRegion,0x1000);

	//用于给保存寄存器时当栈 0x2000后面会说
	pHostEsp = ExAllocatePoolWithTag(NonPagedPool,0x2000,'mini');
	if (!pHostEsp)
	{
		Log("ERROR:申请宿主机堆载区域失败!",0);
		ExFreePoolWithTag(pVMXONRegion,0x1000);
		ExFreePoolWithTag(pVMCSRegion,0x1000);
		return STATUS_MEMORY_NOT_ALLOCATED;
	}
	RtlZeroMemory(pHostEsp,0x2000);

	Log("TIP:VMXON内存区域地址",pVMXONRegion);
	Log("TIP:VMCS内存区域地址",pVMCSRegion);
	Log("TIP:宿主机堆载区域地址",pHostEsp);

	g_VMXCPU.pVMXONRegion = pVMXONRegion;
	g_VMXCPU.pVMXONRegion_PA = MmGetPhysicalAddress(pVMXONRegion);
	g_VMXCPU.pVMCSRegion = pVMCSRegion;
	g_VMXCPU.pVMCSRegion_PA = MmGetPhysicalAddress(pVMCSRegion);
	g_VMXCPU.pHostEsp = pHostEsp;
	return STATUS_SUCCESS;
}

//填写版本号信息和开启虚拟化汇编指令
void SetupVMXRegion()
{
	VMX_BASIC_MSR Msr;
	ULONG uRevId;
	_CR4 uCr4;
	_EFLAGS uEflags;

	RtlZeroMemory(&Msr,sizeof(Msr));

	*((PULONG)&Msr) = Asm_ReadMsr(MSR_IA32_VMX_BASIC);
	uRevId = Msr.RevId;

	//将Revid写入申请的到VMXON VMCS的前4个字节
	*((PULONG)g_VMXCPU.pVMXONRegion) = uRevId;
	*((PULONG)g_VMXCPU.pVMCSRegion) = uRevId;

	Log("TIP:VMX版本号信息",uRevId);

	//开启虚拟化汇编指令
	*((PULONG)&uCr4) = Asm_GetCr4();
	uCr4.VMXE = 1;
	Asm_SetCr4(*((PULONG)&uCr4));

	//调用VmxOn指令启动虚拟化指令
	Vmx_VmxOn(g_VMXCPU.pVMXONRegion_PA.LowPart,g_VMXCPU.pVMXONRegion_PA.HighPart);

	//检测Vmxon指令是否成功 见intel手册3.15
	*((PULONG)&uEflags) = Asm_GetEflags();
	if (uEflags.CF != 0)
	{
		Log("ERROR:VMXON指令调用失败!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值