x64VT虚拟化框架源码
#include "vtstart.h"#include "asm64.h"
#include "vmxstruct.h"
#include "mem.h"
LONG gvt_uSubvertedCPUs = 0;
static KMUTEX MY_HvmMutex;
BOOLEAN g_vt_SubvertedCPU = FALSE;
_TEPTPPML4T EPT_Ptable;
/********************************************************************
检测当前的处理器是否支持Vt
********************************************************************/
BOOLEAN NTAPI VmxIsImplemented(
)
{
ULONG32 eax, ebx, ecx, edx;
GetCpuIdInfo(0, &eax, &ebx, &ecx, &edx);
if (eax < 1)
{
DbgPrint("vmx:VmxIsImplemented(): Extended CPUID functions not implemented\n");
return FALSE;
}
if (!(ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69))
{
DbgPrint("vmx:VmxIsImplemented(): Not an INTEL processor\n");
return FALSE;
}
//intel cpu use fun_0x1 to test VMX.
GetCpuIdInfo(0x1, &eax, &ebx, &ecx, &edx);
return (BOOLEAN)(CmIsBitSet(ecx, 5));
}
// 开启Intel VT内核调试
NTSTATUS NTAPI StartVirtualTechnology()
{
CCHAR cProcessorNumber;
NTSTATUS Status, CallbackStatus;
if (g_vt_SubvertedCPU)
{
DbgPrint("vmx:已经开启过VT\n");
return STATUS_UNSUCCESSFUL;
}
if (!VmxIsImplemented())
{
return STATUS_UNSUCCESSFUL;
}
DbgPrint("vmx:在每隔核心上开启VT HvmSwallowBluepill(): Going to subvert %d processor%s\n",
KeNumberProcessors, KeNumberProcessors == 1 ? "" : "s");
MmInitManager();
MmInitEptPageTable();
KeInitializeMutex(&MY_HvmMutex, 0);
//
// 获得互斥体MY_HvmMutex对象, 保证一时间只有一个HvmSwallowBluepill函数在执行
//
KeWaitForSingleObject(&MY_HvmMutex, Executive, KernelMode, FALSE, NULL);
//
// 遍历所有处理器
//
for (cProcessorNumber = 0; cProcessorNumber < KeNumberProcessors; cProcessorNumber++)
{
DbgPrint("vmx:HvmSwallowBluepill(): CPU数量 #%d\n", cProcessorNumber);
//
// 向每个处理器投递消息,要求执行CmSubvert
// CmDeliverToProcessor通过KeSetSystemAffinityThread将代码运行在指定CPU上,并提升IRQL为DPC_LEVEL
// CmSubvert的流程是保存所有寄存器(除了段寄存器)的内容到栈里后,调用HvmSubvertCpu
//
Status = CmDeliverToProcessor(cProcessorNumber, CmSubvert, NULL, &CallbackStatus);
//
// 验证是否投递成功
//
if (!NT_SUCCESS(Status))
{
DbgPrint("vmx:StartVirtualTechnology() CmDeliverToProcessor failed with status 0x%08hX\n", Status);
KeReleaseMutex(&MY_HvmMutex, FALSE);
StopVirtualTechnology();
return Status;
}
//
// 验证HvmSubvertCpu是否成功
//
if (!NT_SUCCESS(CallbackStatus))
{
DbgPrint("vmx:StartVirtualTechnology() HvmSubvertCpu failed with status 0x%08hX\n", CallbackStatus);
KeReleaseMutex(&MY_HvmMutex, FALSE);
StopVirtualTechnology();
return CallbackStatus;
}
}
KeReleaseMutex(&MY_HvmMutex, FALSE);
//
// 如果没有对每个核都侵染成功,则撤销更改
//
if (KeNumberProcessors != gvt_uSubvertedCPUs)
{
g_vt_SubvertedCPU = FALSE;
DbgPrint("vmx:没有对每个核都侵染成功撤销更改 %d %d\n", KeNumberProcessors, gvt_uSubvertedCPUs);
StopVirtualTechnology();
return STATUS_UNSUCCESSFUL;
}
g_vt_SubvertedCPU = TRUE;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI CmDeliverToProcessor(
CCHAR cProcessorNumber,
PCALLBACK_PROC CallbackProc,
PVOID CallbackParam,
PNTSTATUS pCallbackStatus
)
{
NTSTATUS CallbackStatus;
KIRQL OldIrql;
if (!CallbackProc)
return STATUS_INVALID_PARAMETER;
if (pCallbackStatus)
*pCallbackStatus = STATUS_UNSUCCESSFUL;
KeSetSystemAffinityThread((KAFFINITY)(1 << cProcessorNumber));
// 提升IRQL至DISPATCH_LEVEL
OldIrql = KeRaiseIrqlToDpcLevel();
// 调用回调函数
CallbackStatus = CallbackProc(CallbackParam);
KeLowerIrql(OldIrql);
KeRevertToUserAffinityThread();
// 保存callback的返回值
// save the status of the callback which has run on the current core
if (pCallbackStatus)
*pCallbackStatus = CallbackStatus;
return STATUS_SUCCESS;
}
/* 关闭VT内核调试 */
NTSTATUS NTAPI StopVirtualTechnology()
{
CCHAR cProcessorNumber;
NTSTATUS Status, CallbackStatus;
if (g_vt_SubvertedCPU == FALSE)
{
return STATUS_UNSUCCESSFUL;
}
DbgPrint("vmx:HvmSpitOutBluepill(): Going to liberate %d processor%s\n",
KeNumberProcessors, KeNumberProcessors == 1 ? "" : "s");
//
// 获得互斥体MY_HvmMutex对象, 保证一时间只有一个HvmSpitOutBluepill函数在执行
//
KeWaitForSingleObject(&MY_HvmMutex, Executive, KernelMode, FALSE, NULL);
//
// 遍历所有处理器
//
for (cProcessorNumber = 0; cProcessorNumber < KeNumberProcessors; cProcessorNumber++)
{
DbgPrint("vmx:HvmSpitOutBluepill(): Liberating processor #%d\n", cProcessorNumber);
//
// 向每个处理器投递消息,要求执行HvmLiberateCpu, 来通知CPU退出Guest模式
//
Status = CmDeliverToProcessor(cProcessorNumber, LiberateCpu, NULL, &CallbackStatus);
//
// 验证是否投递成功
//
if (!NT_SUCCESS(Status)) {
DbgPrint("vmx:HvmSpitOutBluepill(): CmDeliverToProcessor() failed with status 0x%08hX\n", Status);
}
//
// 验证HvmLiberateCpu是否成功
//
if (!NT_SUCCESS(CallbackStatus)) {
DbgPrint("vmx:HvmSpitOutBluepill(): HvmLiberateCpu() failed with status 0x%08hX\n", CallbackStatus);
}
}
DbgPrint("vmx:HvmSpitOutBluepill(): Finished at irql %d\n", KeGetCurrentIrql());
KeReleaseMutex(&MY_HvmMutex, FALSE);
MmShutdownManager();
return STATUS_SUCCESS;
}
//===========================================================================
// 这就是解放CPU了.会在每个Processor上面都执行一遍
//===========================================================================
NTSTATUS NTAPI LiberateCpu(PVOID Param)
{
NTSTATUS Status;
ULONG64 Efer;
//
// 中断级判断, 必须处在 DPC 级别上
//
if (KeGetCurrentIrql() != DISPATCH_LEVEL)
{
return STATUS_UNSUCCESSFUL;
}
//
// 这个寄存器标示了是否开启了HVM.
//
Efer = MsrRead(MSR_EFER);
DbgPrint("vmx:Ddvp-> Reading MSR_EFER on entry: 0x%X\n", Efer);
if (g_vt_SubvertedCPU == FALSE)
{
DbgPrint("vmx:开启失败关闭CR4\n");
VmxDisable();
return STATUS_SUCCESS;
}
//
// 这个函数向 Hypervisor 发出申请卸载的NBP_HYPERCALL_UNLOAD消息
//
if (!NT_SUCCESS(Status = MakeHyperExitCall()))
{
DbgPrint("vmx:Ddvp-> MakeHyperExitCall() failed on processor #%d, status 0x%08hX\n",
KeGetCurrentProcessorNumber(), Status);
return Status;
}
Efer = MsrRead(MSR_EFER);
DbgPrint("vmx:Ddvp-> Reading MSR_EFER on exit: 0x%X\n", Efer);
return STATUS_SUCCESS;
}
NTSTATUS Virtualize(PCPU pCpu)
{
/* ULONG64 rsp;*/
ULONG32 i;
g_vt_SubvertedCPU = TRUE;
i = KeGetCurrentProcessorNumber();
DbgPrint("vmx:CPU: 0x%p \n", pCpu);
//DbgPrint(("rsp: 0x%llx \n", _Rsp()));
__vmx_vmlaunch();
//VmxLaunch();
/* never returns if successful */
DbgPrint("vmx:rflags after _VmLaunch: 0x%x\n", RegGetRflags());
if (_VmFailInvalid())
{
g_vt_SubvertedCPU = FALSE;
DbgPrint("vmx:no current VMCS\n");
return STATUS_UNSUCCESSFUL;
}
if (_VmFailValid())
{
g_vt_SubvertedCPU = FALSE;
DbgPrint("vmx:vmlaunch failed\n");
DbgPrint("vmx:_ReadVMCS: 0x%llx\n", ReadVMCS(VM_INSTRUCTION_ERROR));
return STATUS_UNSUCCESSFUL;
}
g_vt_SubvertedCPU = FALSE;
return STATUS_UNSUCCESSFUL;
}
NTSTATUS HvmSubvertCpu(PVOID GuestRsp)
{
NTSTATUS Status;
PVOID HostKernelStackBase;
PCPU pCpu;
Status = CheckIfVMXIsEnabled();
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
//HostKernelStackBase = ExAllocatePoolWithTag(NonPagedPool, 16 * 0x1000, 0x42424242);
HostKernelStackBase = MmAllocatePages(16, NULL);
RtlZeroMemory(HostKernelStackBase, 16 * 0x1000);
if (!HostKernelStackBase)
{
DbgPrint("vmx:can't allocate host kernel stack\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
pCpu = (PCPU)((PCHAR)HostKernelStackBase + 16 * 0x1000 - 8 - sizeof(CPU));
pCpu->pHostRsp = HostKernelStackBase;
pCpu->Self = pCpu;
pCpu->State = STATE_RUNNING;
pCpu->Mailbox = IPI_RUNNING;
Status = SetupVMX(pCpu);
// 当前处理器数量
pCpu->CpuIndex = KeGetCurrentProcessorNumber();
DbgPrint("vmx:Ddvp-> Vmx Cpu Address :%p HostKernelStackBase %p !\n", pCpu, HostKernelStackBase);
if (Status == STATUS_UNSUCCESSFUL)
{
return STATUS_UNSUCCESSFUL;
}
//_HvmSetupGdt (pCpu); // 配置Guest Gdt
//_HvmSetupIdt(pCpu); // 配置Guest Idt
Status = SetupVMCS(pCpu, GuestRsp);
//CmSetHookIdtEntry(0x3, (PVOID)InGeneralProtection);
//_HvmSetupIdt(pCpu); // 配置Guest Idt
if (Status == STATUS_UNSUCCESSFUL)
{
return STATUS_UNSUCCESSFUL;
}
InterlockedIncrement(&gvt_uSubvertedCPUs);
Status = Virtualize(pCpu);
if (Status == STATUS_UNSUCCESSFUL)
{
DbgPrint("vmx:开启虚拟化这个函数返回执行失败 !\n");
InterlockedDecrement(&gvt_uSubvertedCPUs);
g_vt_SubvertedCPU = FALSE;
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS CheckIfVMXIsEnabled()
{
ULONG64 cr4;
IA32_FEATURE_CONTROL_MSR msr;
CR0_REG cr0;
// 设置cr4位,为启用VM模式做准备
/* vmx desactived by bios ? */
/*msr = MsrRead(MSR_IA32_FEATURE_CONTROL);
if (!(msr & 4))
{
DbgPrint("vmx is disabled in bios: MSR_IA32_FEATURE_CONTROL is 0x%llx\n", msr);
return STATUS_UNSUCCESSFUL;
}*/
//bochs的bug,要改IA32_FEATURE_CONTROL的Lock为1
//#if bochsdebug
//MsrWrite(MSR_IA32_FEATURE_CONTROL, 5);
//#endif
TO_ULL(msr) = __readmsr(MSR_IA32_FEATURE_CONTROL);
if (msr.Lock == 1)
{
// If the MSR is locked, it can't be modified
// If 'EnableVmxon' is unset, virtualization is not possible
if (msr.EnableVmxon == 0)
{
DbgPrint("vmx:VMX is disabled in bios: MSR_IA32_FEATURE_CONTROL is 0x%llx\n", msr);
return STATUS_NOT_SUPPORTED;
}
}
else
{
// Force the lock to be on and enable VMXON
msr.Lock = 1;
msr.VmxonInSmx = 1;
msr.EnableVmxon = 1;
__writemsr(MSR_IA32_FEATURE_CONTROL, TO_ULL(msr));
}
TO_ULL(cr0) = __readcr0();
if (cr0.PE == 0 || cr0.PG == 0)
{
DbgPrint("vmx:Error: Protected mode or paging is not set in CR0\n");
return STATUS_NOT_SUPPORTED;
}
else
{
// Required by first processors that supported VMX
cr0.NE = 1;
}
__writecr0(TO_ULL(cr0));
set_in_cr4(X86_CR4_VMXE);
cr4 = RegGetCr4();
if (!(cr4 & X86_CR4_VMXE))
{
DbgPrint("vmx:error: VMXON not supported\n");
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS SetupVMX(PCPU pCpu)
{
// PHYSICAL_ADDRESS pa;
ULONG64 msr;
PVMX_BASIC_MSR pvmx;
// ULONG32 i;
// PVOID va;
ULONG size;
NTSTATUS Status = STATUS_SUCCESS;
pCpu->CpuIndex = KeGetCurrentProcessorNumber();
msr = MsrRead(MSR_IA32_VMX_BASIC);
pvmx = (PVMX_BASIC_MSR)&msr;
// Vmx结构体大小.
size = pvmx->szVmxOnRegion;
DbgPrint("vmx:VMXON region size: %p %p\n", size, msr);
DbgPrint("vmx:VMX revision ID: %p pCpu->CpuIndex %p\n", pvmx->RevId, pCpu->CpuIndex);
//
//
// Allocate memory for VMON, 然后执行vmxon指令
//
pCpu->pVMONVirtualAddress = MmAllocatePages(1, &pCpu->pVMONPyhicalAddress);
if (pCpu->pVMONVirtualAddress == 0)
{
DbgPrint(("vmx:Ddvp-> VMXON 内存分配失败 !\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> VMON 虚拟地址%p !\n", pCpu->pVMONVirtualAddress);
DbgPrint("vmx:Ddvp-> VMXON 内存物理地址:%p!\n", pCpu->pVMONPyhicalAddress);
// vmxon版本号.
//
*(ULONG32 *)pCpu->pVMONVirtualAddress = pvmx->RevId;
VmxTurnOn(pCpu->pVMONPyhicalAddress);
if (_VmFailInvalid())
{
DbgPrint("vmx:_VmxOn failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
}
pCpu->pVMCSVirtualAddress = MmAllocatePages(1, &pCpu->pVMCSPyhicalAddress);
if (pCpu->pVMCSVirtualAddress == 0)
{
DbgPrint("vmx:Ddvp-> 分配 VMCS结构内存失败!\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
*(ULONG32 *)pCpu->pVMCSVirtualAddress = pvmx->RevId;
DbgPrint("vmx:Ddvp-> VMCS 虚拟地址%p !\n", pCpu->pVMCSVirtualAddress);
DbgPrint("vmx:Ddvp-> VMCS 内存物理地址:%p !\n", pCpu->pVMCSPyhicalAddress);
// 这边是MSR位图.
//
pCpu->pMSRBitmapVirtualAddress = MmAllocatePages(4, &pCpu->pMSRBitmapPyhicalAddress);
if (pCpu->pMSRBitmapVirtualAddress == NULL)
{
DbgPrint(("vmx:Ddvp-> 分配 MSR Bitmap 结构内存失败!\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> MSR 虚拟地址%p !\n", pCpu->pMSRBitmapVirtualAddress);
DbgPrint("vmx:Ddvp-> MSR Bitmap 内存物理地址高位:%p, 低位:%p !\n",
pCpu->pMSRBitmapPyhicalAddress.HighPart, pCpu->pMSRBitmapPyhicalAddress.LowPart);
//
// 这边是 IOBitmapA
//
pCpu->pIOBitmapVirtualAddressA = MmAllocatePages(1, &pCpu->pIOBitmapPyhicalAddressA);
if (pCpu->pIOBitmapVirtualAddressA == NULL)
{
DbgPrint(("vmx:Ddvp-> 分配 IOBitmapA 结构内存失败!\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> IOBitmapA 虚拟地址%p !\n", pCpu->pIOBitmapVirtualAddressA);
DbgPrint("vmx:Ddvp-> IOBitmapA 内存物理地址高位:%p, 低位:%p !\n",
pCpu->pIOBitmapPyhicalAddressA.HighPart, pCpu->pIOBitmapPyhicalAddressA.LowPart);
//
// 这边是 IOBitmapB
//
pCpu->pIOBitmapVirtualAddressB = MmAllocatePages(1, &pCpu->pIOBitmapPyhicalAddressB);
if (pCpu->pIOBitmapVirtualAddressB == NULL)
{
DbgPrint(("vmx:Ddvp-> 分配 IOBitmapB 结构内存失败!\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> IOBitmaB 虚拟地址:%p !\n", pCpu->pIOBitmapVirtualAddressB);
DbgPrint("vmx:Ddvp-> IOBitmapB 内存物理地址高位:%p, 低位:%p !\n",
pCpu->pIOBitmapPyhicalAddressB.HighPart, pCpu->pIOBitmapPyhicalAddressB.LowPart);
pCpu->GdtArea = MmAllocatePages(BYTES_TO_PAGES(BP_GDT_LIMIT), NULL);
if (!pCpu->GdtArea) {
DbgPrint("vmx:HvmSubvertCpu(): Failed to allocate memory for GDT\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> pCpu->GdtArea内存地址%p !\n", pCpu->GdtArea);
pCpu->IdtArea = MmAllocatePages(BYTES_TO_PAGES(BP_IDT_LIMIT), NULL);
if (!pCpu->IdtArea)
{
DbgPrint("vmx:HvmSubvertCpu(): Failed to allocate memory for IDT\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto __Exit;
}
DbgPrint("vmx:Ddvp-> pCpu->IdtArea内存地址%p !\n", pCpu->IdtArea);
// 填写版本号
__Exit:
if (!NT_SUCCESS(Status))
{
DbgPrint("vmx:Ddvp-> 失败 释放内存!\n");
if (pCpu->pVMONVirtualAddress)
{
MmFreeNonCachedMemory(pCpu->pVMONVirtualAddress, 0x1000);
pCpu->pVMONVirtualAddress = NULL;
}
if (pCpu->pVMCSVirtualAddress)
{
MmFreeNonCachedMemory(pCpu->pVMCSVirtualAddress, 0x1000);
pCpu->pVMCSVirtualAddress = NULL;
}
if (pCpu->pIOBitmapVirtualAddressA)
{
MmFreeNonCachedMemory(pCpu->pIOBitmapVirtualAddressA, 0x1000);
pCpu->pIOBitmapVirtualAddressA = NULL;
}
if (pCpu->pIOBitmapVirtualAddressB)
{
MmFreeNonCachedMemory(pCpu->pIOBitmapVirtualAddressB, 0x1000);
pCpu->pIOBitmapVirtualAddressB = NULL;
}
if (pCpu->pMSRBitmapVirtualAddress)
{
MmFreeNonCachedMemory(pCpu->pMSRBitmapVirtualAddress, 0x1000);
pCpu->pMSRBitmapVirtualAddress = NULL;
}
if (pCpu->IdtArea)
{
MmFreeNonCachedMemory(pCpu->IdtArea, BYTES_TO_PAGES(BP_IDT_LIMIT));
pCpu->IdtArea = NULL;
}
if (pCpu->GdtArea)
{
MmFreeNonCachedMemory(pCpu->GdtArea, BYTES_TO_PAGES(BP_GDT_LIMIT));
pCpu->GdtArea = NULL;
}
}
return Status;
}
NTSTATUS SetupVMCS(PCPU pCpu, PVOID GuestRsp)
{
ULONG32 Interceptions, ExceptionBitmap, Cr0, Cr4;
PVOID GdtBase;
SEGMENT_SELECTOR SegmentSelector;
ULONG32 i;
PHYSICAL_ADDRESS pa;
ULONG64 ExceptionBit;
PTEPTPPML4T pPML4T;
//i = KeGetCurrentProcessorNumber();
//DbgPrint(("pCpu %p GuestRsp=%p\n", pCpu,GuestRsp));
pa = pCpu->pVMCSPyhicalAddress;
VmxClear(pa);
_VmxPtrLd(pa);
DbgPrint("vmx:RegGetCr0() %p\n", RegGetCr0());
Cr0 = (ULONG32)RegGetCr0();
CmSetBit32(&Cr0, 0); // PE
CmSetBit32(&Cr0, 5); // NE
CmSetBit32(&Cr0, 31); // PG
DbgPrint("vmx:CR0 %p\n", Cr0);
WriteVMCS(GUEST_CR0, Cr0);
WriteVMCS(GUEST_CR3, RegGetCr3());
//; DbgPrint((" RegGetCr3() %p\n", RegGetCr3()));
//; DbgPrint((" RegGetCr4() %p\n", RegGetCr4()));
Cr4 = RegGetCr4();
CmSetBit32(&Cr4, 13);// 一定要设置VMXE
WriteVMCS(GUEST_CR4, Cr4);
WriteVMCS(GUEST_DR7, 0x400);
WriteVMCS(GUEST_RSP, (ULONG64)GuestRsp);
WriteVMCS(GUEST_RIP, (ULONG64)_GuestEntryPoint);
WriteVMCS(GUEST_RFLAGS, RegGetRflags());
/*DbgPrint("RegGetRflags %p\n", RegGetRflags());
DbgPrint("DR7 %p\n", ReadVMCS(GUEST_DR7));
DbgPrint("GUEST_RSP %p\n", ReadVMCS(GUEST_RSP));
DbgPrint("GUEST_RIP %p\n", ReadVMCS(GUEST_RIP));
DbgPrint("GUEST_RFLAGS %p\n", ReadVMCS(GUEST_RFLAGS));*/
GdtBase = (PVOID)GetGdtBase();
//DbgPrint(("GdtBase %p\n", GdtBase));
FillGuestSelectorData(GdtBase, ES, RegGetEs());
FillGuestSelectorData(GdtBase, CS, RegGetCs());
FillGuestSelectorData(GdtBase, SS, RegGetSs());
FillGuestSelectorData(GdtBase, DS, RegGetDs());
FillGuestSelectorData(GdtBase, FS, RegGetFs());
FillGuestSelectorData(GdtBase, GS, RegGetGs());
FillGuestSelectorData(GdtBase, LDTR, GetLdtr());
FillGuestSelectorData(GdtBase, TR, GetTrSelector());
/*DbgPrint("ES %x CS %x SS %x DS %x FS %x GS %x LDTR %x TR %x \n", ES ,CS,SS,DS,FS,GS,LDTR,TR);
DbgPrint("RegGetEs() %p\n", RegGetEs());
DbgPrint("RegGetCs() %p\n", RegGetCs());
DbgPrint("RegGetSs() %p\n", RegGetSs());
DbgPrint("RegGetDs() %p\n", RegGetDs());
DbgPrint("RegGetFs() %p\n", RegGetFs());
DbgPrint("RegGetGs() %p\n", RegGetGs());
DbgPrint("GetLdtr() %p\n", GetLdtr());
DbgPrint("GetTrSelector() %p\n", GetTrSelector());*/
// 填写Guest段描述符基址
WriteVMCS(GUEST_ES_BASE, 0);
WriteVMCS(GUEST_CS_BASE, 0);
WriteVMCS(GUEST_SS_BASE, 0);
WriteVMCS(GUEST_DS_BASE, 0);
WriteVMCS(GUEST_FS_BASE, MsrRead(MSR_FS_BASE));
WriteVMCS(GUEST_GS_BASE, MsrRead(MSR_GS_BASE));
// 填写Guest GDTR/IDTR基址
WriteVMCS(GUEST_GDTR_BASE, GetGdtBase());
WriteVMCS(GUEST_IDTR_BASE, GetIdtBase());
// 填写Guest段描述符限长
WriteVMCS(GUEST_GDTR_LIMIT, GetGdtLimit());
WriteVMCS(GUEST_IDTR_LIMIT, GetIdtLimit());
/*DbgPrint("GetIdtBase() %p\n", GetIdtBase());
DbgPrint("GetGdtLimit() %p\n", GetGdtLimit());
DbgPrint("GetIdtLimit() %p\n", GetIdtLimit());
DbgPrint("MsrRead(MSR_FS_BASE) %p MsrRead(MSR_GS_BASE) %p\n", MsrRead(MSR_FS_BASE), MsrRead(MSR_GS_BASE));*/
// 填写Guest MSR IA32_DEBUGCTL 寄存器值
WriteVMCS(GUEST_IA32_DEBUGCTL, MsrRead(MSR_IA32_DEBUGCTL) & 0xffffffff);
WriteVMCS(GUEST_IA32_DEBUGCTL_HIGH, MsrRead(MSR_IA32_DEBUGCTL) >> 32);
//DbgPrint("MsrRead(GUEST_IA32_DEBUGCTL) %pMsrRead(GUEST_IA32_DEBUGCTL_HIGH) %p\n", MsrRead(MSR_IA32_DEBUGCTL), MsrRead(MSR_IA32_DEBUGCTL));
// 填写Guest MSR IA32_SYSENTER_CS
WriteVMCS(GUEST_SYSENTER_CS, MsrRead(MSR_IA32_SYSENTER_CS));
// 填写Guest MSR IA32_SYSENTER_ESP
WriteVMCS(GUEST_SYSENTER_ESP, MsrRead(MSR_IA32_SYSENTER_ESP));
// 填写Guest MSR IA32_SYSENTER_EIP
WriteVMCS(GUEST_SYSENTER_EIP, MsrRead(MSR_IA32_SYSENTER_EIP));
/*DbgPrint("MsrRead(MSR_IA32_SYSENTER_CS) %p MsrRead(MSR_IA32_SYSENTER_ESP) %p MsrRead(MSR_IA32_SYSENTER_ESP) % p", MsrRead(MSR_IA32_SYSENTER_CS),MsrRead(MSR_IA32_SYSENTER_ESP), MsrRead(MSR_IA32_SYSENTER_ESP));
DbgPrint(" ReadVMCS(GUEST_SYSENTER_CS) %pReadVMCS(GUEST_IA32_DEBUGCTL_HIGH) %p\n", ReadVMCS(GUEST_SYSENTER_CS), ReadVMCS(GUEST_SYSENTER_ESP));*/
// 填写 GUEST IA32_EFER
WriteVMCS(GUEST_IA32_EFER, MsrRead(MSR_EFER));
//DbgPrint(" ReadVMCS(GUEST_IA32_EFER) %pReadVMCS(GUEST_SYSENTER_EIP) %p\n", ReadVMCS(GUEST_IA32_EFER), ReadVMCS(GUEST_SYSENTER_EIP));
/* guest non register state */
// Guest中断能力状态
WriteVMCS(GUEST_INTERRUPTIBILITY_INFO, 0);
// Guest活动性状态
WriteVMCS(GUEST_ACTIVITY_STATE, 0);
// VMCS连接指针(保留)
WriteVMCS(VMCS_LINK_POINTER, 0xffffffff);
WriteVMCS(VMCS_LINK_POINTER_HIGH, 0xffffffff);
/* host state area */
// 控制寄存器 CR0, CR3, CR4
WriteVMCS(HOST_CR0, RegGetCr0());
WriteVMCS(HOST_CR3, RegGetCr3());
WriteVMCS(HOST_CR4, RegGetCr4());
// 设置Host ESP, EIP
WriteVMCS(HOST_RSP, (ULONG64)pCpu);
WriteVMCS(HOST_RIP, (ULONG64)_ExitHandler);
// 填写Host CS, SS, DS, ES, FS, GS和TR寄存器
WriteVMCS(HOST_ES_SELECTOR, KGDT64_R0_DATA);
WriteVMCS(HOST_CS_SELECTOR, KGDT64_R0_CODE);
WriteVMCS(HOST_SS_SELECTOR, KGDT64_R0_DATA);
WriteVMCS(HOST_DS_SELECTOR, KGDT64_R0_DATA);
WriteVMCS(HOST_FS_SELECTOR, (RegGetFs() & 0xf8));
WriteVMCS(HOST_GS_SELECTOR, (RegGetGs() & 0xf8));
WriteVMCS(HOST_TR_SELECTOR, (GetTrSelector() & 0xf8));
WriteVMCS(HOST_FS_BASE, MsrRead(MSR_FS_BASE));
WriteVMCS(HOST_GS_BASE, MsrRead(MSR_GS_BASE));
//DbgPrint(("MsrRead(MSR_GS_BASE) %p MsrRead(MSR_FS_BASE) %p\n", MsrRead(MSR_GS_BASE), MsrRead(MSR_FS_BASE)));
InitializeSegmentSelector(&SegmentSelector, GetTrSelector(), (PVOID)
GetGdtBase());
WriteVMCS(HOST_TR_BASE, SegmentSelector.base);
WriteVMCS(HOST_GDTR_BASE, (ULONG64)GetGdtBase());
WriteVMCS(HOST_IDTR_BASE, (ULONG64)GetIdtBase());
DbgPrint("vmx:GetGdtBase() %pGetIdtBase() %p\n", GetGdtBase(), GetIdtBase());
WriteVMCS(HOST_IA32_SYSENTER_ESP, MsrRead(MSR_IA32_SYSENTER_ESP));
WriteVMCS(HOST_IA32_SYSENTER_EIP, MsrRead(MSR_IA32_SYSENTER_EIP));
WriteVMCS(HOST_IA32_SYSENTER_CS, MsrRead(MSR_IA32_SYSENTER_CS));
// 填写 Host IA32_EFER
WriteVMCS(HOST_IA32_EFER, MsrRead(MSR_EFER));
/* VM Execution Control Fields */
WriteVMCS(PIN_BASED_VM_EXEC_CONTROL, VmxAdjustControls(0,
MSR_IA32_VMX_PINBASED_CTLS));
Interceptions = VmxAdjustControls(0, MSR_IA32_VMX_PROCBASED_CTLS);
//DbgPrint("Interceptions %p\n", Interceptions);
Interceptions |= CPU_BASED_ACTIVATE_MSR_BITMAP;
//Interceptions |= CPU_BASED_INVLPG_EXITING;
//Interceptions|=CPU_BASED_MTF_TRAP_EXITING;//启用MTF调试功能
Interceptions |= CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;//启用SECONDARY_VM_EXEC_CONTROL字段
//Interceptions |=CPU_BASED_MOV_DR_EXITING;//DR寄存器访问
Interceptions &= ~CPU_BASED_CR3_LOAD_EXITING;//关闭拦截CR3寄存器
Interceptions &= ~CPU_BASED_CR3_STORE_EXITING;//关闭拦截CR3寄存器
//Interceptions &= ~CPU_BASED_ACTIVATE_MSR_BITMAP;
WriteVMCS(CPU_BASED_VM_EXEC_CONTROL, Interceptions);
//DbgPrint("Interceptions%p\n", Interceptions);
ExceptionBitmap = 0;
ExceptionBitmap |= SECONDARY_EXEC_ENABLE_EPT;//启用EPT
ExceptionBitmap |= SECONDARY_EXEC_ENABLE_VPID;//启用虚拟VPID
WriteVMCS(SECONDARY_VM_EXEC_CONTROL, ExceptionBitmap);
ExceptionBitmap = 0;
ExceptionBitmap |= 1 << DEBUG_EXCEPTION;
ExceptionBitmap |= 1 << BREAKPOINT_EXCEPTION;
ExceptionBitmap |= 1 << PAGE_FAULT_EXCEPTION;
WriteVMCS(EXCEPTION_BITMAP, ExceptionBitmap);
// 配置页故障
WriteVMCS(PAGE_FAULT_ERROR_CODE_MASK, 0);
WriteVMCS(PAGE_FAULT_ERROR_CODE_MATCH, 0);
// 填写 3.4 I/O bitmap IO位图, 这里可以拦截了60号端口.. 也就是键盘输入
WriteVMCS(IO_BITMAP_A, pCpu->pIOBitmapPyhicalAddressA.LowPart);
WriteVMCS(IO_BITMAP_A_HIGH, pCpu->pIOBitmapPyhicalAddressA.HighPart);
WriteVMCS(IO_BITMAP_B, pCpu->pIOBitmapPyhicalAddressB.LowPart);
WriteVMCS(IO_BITMAP_B_HIGH, pCpu->pIOBitmapPyhicalAddressB.HighPart);
// 填写 3.5 时间戳计数器偏移(Time-Stamp Counter Offset )
WriteVMCS(TSC_OFFSET, 0);
WriteVMCS(TSC_OFFSET_HIGH, 0);
// 填写 3.7 CR3访问控制.
WriteVMCS(CR3_TARGET_COUNT, 0);
WriteVMCS(CR3_TARGET_VALUE0, 0); //no use
WriteVMCS(CR3_TARGET_VALUE1, 0); //no use
WriteVMCS(CR3_TARGET_VALUE2, 0); //no use
WriteVMCS(CR3_TARGET_VALUE3, 0); //no use
// 填写3.9 MSR 位图地址(MSR Bitmap Address)
// 这里我只需要截获 MSR_IA32_SYSENTER_EIP MSR寄存器的读写
// 对于其他优化现在还没有.. 先不管
//
WriteVMCS(MSR_BITMAP, pCpu->pMSRBitmapPyhicalAddress.LowPart);
WriteVMCS(MSR_BITMAP_HIGH, pCpu->pMSRBitmapPyhicalAddress.HighPart);
WriteVMCS(VM_ENTRY_CONTROLS, VmxAdjustControls(VM_ENTRY_IA32E_MODE | VM_ENTRY_LOAD_IA32_EFER, MSR_IA32_VMX_ENTRY_CTLS));
DbgPrint("vmx:VM_ENTRY行为控制域 %p\n", ReadVMCS(VM_ENTRY_CONTROLS));
WriteVMCS(VM_ENTRY_MSR_LOAD_COUNT, 0);
WriteVMCS(VM_ENTRY_INTR_INFO_FIELD, 0);
/* VM Exit Control */
WriteVMCS(VM_EXIT_CONTROLS, VmxAdjustControls(VM_EXIT_IA32E_MODE |
VM_EXIT_ACK_INTR_ON_EXIT, MSR_IA32_VMX_EXIT_CTLS));
WriteVMCS(VM_EXIT_MSR_STORE_COUNT, 0);
WriteVMCS(VM_EXIT_MSR_LOAD_COUNT, 0);
//WriteVMCS(VM_EXIT_CONTROLS,
//VmxAdjustControls(VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_IA32E_MODE | VM_EXIT_ACK_INTR_ON_EXIT | VM_EXIT_SAVE_IA32_EFER | VM_EXIT_LOAD_IA32_EFER, MSR_IA32_VMX_EXIT_CTLS));
//DbgPrint(("VMExit行为控制域 %p%p\n", ReadVMCS(VM_EXIT_CONTROLS), VmxAdjustControls(VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_IA32E_MODE | VM_EXIT_ACK_INTR_ON_EXIT | VM_EXIT_SAVE_IA32_EFER | VM_EXIT_LOAD_IA32_EFER, MSR_IA32_VMX_EXIT_CTLS)));
//WriteVMCS(CR0_GUEST_HOST_MASK, X86_CR0_PG);
//WriteVMCS(CR0_READ_SHADOW, (_Cr0() & X86_CR0_PG) | X86_CR0_PG);
//WriteVMCS(CR4_GUEST_HOST_MASK, X86_CR4_VMXE);
//WriteVMCS(CR4_READ_SHADOW, 0);
//3.11 EPT指针(Extended Page Table Pointer), 没有用
//检测并开启UG
// 读取cpu的MSR_IA32_VMX_PROCBASED_CTLS2(0x48B), 以检测cpu是否支持UC。
DbgPrint("vmx:检测是否支持EPT %p%p\n", MsrRead(MSR_IA32_VMX_PROCBASED_CTLS2), VmxAdjustControls(0, MSR_IA32_VMX_PROCBASED_CTLS2));
/*DbgPrint (("检测是否支持EPT %p%p\n",MsrRead(MSR_IA32_VMX_PROCBASED_CTLS), VmxAdjustControls (0, MSR_IA32_VMX_PROCBASED_CTLS)));
DbgPrint (("检测是否支持EPT %p%p\n",MsrRead(MSR_IA32_VMX_EPT_VPID_CAP), VmxAdjustControls (0, MSR_IA32_VMX_PROCBASED_CTLS)));*/
//在VMCS的SECONDARY_VM_EXEC_CONTROL(0x401E) 字段,对应的ENABLE_UC(0x80)标识位置1。
ExceptionBit = 0;
pPML4T = (PTEPTPPML4T)&ExceptionBit;
pPML4T->MEMORYTYPE = 6;//(内存类型)UD = 0,WB = 6
pPML4T->WalkLength = 3;//EPT页表结构的层级,这个值+1才是真正的层级(3)就代表有4层
pPML4T->reserved = 0;
pPML4T->D = 1;//代表EPT页表里access 与 dirty 标志位有效
pPML4T->PML4T = EPT_Ptable.PML4EPHY.QuadPart >> 12;//让开前面的12-1位域写入
//pPML4T->reserved2=0;
WriteVMCS(EPT_POINTER, ExceptionBit);
WriteVMCS(VIRTUAL_PROCESSOR_ID, 1);
return STATUS_SUCCESS;
}
NTSTATUS ResumeGuest()
{
DbgPrint("vmx:Resuming guest ok...\n");
return STATUS_SUCCESS;
}
NTSTATUS NTAPI VmxShutdown(
PCPU Cpu,
PGUEST_REGS GuestRegs
)
{
ULONG uTrampolineSize = 0;
ULONG64 NewRsp;
ULONG64 cr4;
UCHAR Trampoline;
DbgPrint("vmx:VmxShutdown(): CPU#%d\n", gvt_uSubvertedCPUs);
InterlockedDecrement(&gvt_uSubvertedCPUs);
// The code should be updated to build an approproate trampoline to exit to any guest mode.
VmxGenerateTrampolineToGuest(Cpu, GuestRegs, Trampoline);
DbgPrint("vmx:VmxShutdown(): Trampoline generate %d\n", gvt_uSubvertedCPUs);
VmxDisable();
((VOID(*)()) & Trampoline) ();
DbgPrint("vmx:never returns********************* CPU#%d\n", gvt_uSubvertedCPUs);
return STATUS_SUCCESS;
}
NTSTATUS NTAPI VmxDisable(
)
{
ULONG64 cr4;
VmxTurnOff();
cr4 = RegGetCr4();
clear_in_cr4(X86_CR4_VMXE);
//clear_in_cr4(X86_CR4_SMEP);
cr4 = RegGetCr4();
DbgPrint("vmx:VmxDisable(): CR4 after VmxDisable: 0x%llx\n", cr4);
return STATUS_SUCCESS;
}
VOID VmxGenerateTrampolineToGuest(
PCPU Cpu,
PGUEST_REGS GuestRegs,
PUCHAR Trampoline
)
{
ULONG uTrampolineSize = 0;
ULONG64 NewRsp;
// if (!Cpu || !GuestRegs)
// return;
// assume Trampoline buffer is big enough
WriteVMCS(GUEST_RFLAGS, ReadVMCS(GUEST_RFLAGS) & ~0x100); // disable TF
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RCX, GuestRegs->rcx);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RDX, GuestRegs->rdx);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RBX, GuestRegs->rbx);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RBP, GuestRegs->rbp);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RSI, GuestRegs->rsi);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RDI, GuestRegs->rdi);
#ifndef _X86_
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R8, GuestRegs->r8);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R9, GuestRegs->r9);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R10, GuestRegs->r10);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R11, GuestRegs->r11);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R12, GuestRegs->r12);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R13, GuestRegs->r13);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R14, GuestRegs->r14);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_R15, GuestRegs->r15);
#endif
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_CR0, ReadVMCS(GUEST_CR0));
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_CR3, ReadVMCS(GUEST_CR3));
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_CR4, ReadVMCS(GUEST_CR4));
NewRsp = ReadVMCS(GUEST_RSP);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RSP, NewRsp);
// construct stack frame for IRETQ:
// rip
// cs
// rflags
// rsp
// ss
// construct stack frame for IRETD:
// rip
// cs
// rflags
#ifndef _X86_
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_SS_SELECTOR));
CmGeneratePushReg(&Trampoline, &uTrampolineSize, REG_RAX);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX, NewRsp);
CmGeneratePushReg(&Trampoline, &uTrampolineSize, REG_RAX);
#endif
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_RFLAGS));
CmGeneratePushReg(&Trampoline, &uTrampolineSize, REG_RAX);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_CS_SELECTOR));
CmGeneratePushReg(&Trampoline, &uTrampolineSize, REG_RAX);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX,
ReadVMCS(GUEST_RIP) + ReadVMCS(VM_EXIT_INSTRUCTION_LEN));
CmGeneratePushReg(&Trampoline, &uTrampolineSize, REG_RAX);
CmGenerateMovReg(&Trampoline, &uTrampolineSize, REG_RAX, GuestRegs->rax);
#ifdef _X86_
CmGenerateIretd(&Trampoline, &uTrampolineSize);
#else
CmGenerateIretq(&Trampoline, &uTrampolineSize);
#endif
// restore old GDTR
CmReloadGdtr((PVOID)ReadVMCS(GUEST_GDTR_BASE), (ULONG)ReadVMCS(GUEST_GDTR_LIMIT));
MsrWrite(MSR_GS_BASE, ReadVMCS(GUEST_GS_BASE));
MsrWrite(MSR_FS_BASE, ReadVMCS(GUEST_FS_BASE));
// FIXME???
// restore ds, es
// CmSetDS((USHORT)ReadVMCS(GUEST_DS_SELECTOR));
// CmSetES((USHORT)ReadVMCS(GUEST_ES_SELECTOR));
// cs and ss must be the same with the guest OS in this implementation
DbgPrint("vmx:restore old IDTR\n");
// restore old IDTR
CmReloadIdtr((PVOID)ReadVMCS(GUEST_IDTR_BASE), (ULONG)ReadVMCS(GUEST_IDTR_LIMIT));
return;
}
NTSTATUS NTAPI CmGenerateIretq(
PUCHAR pCode,
PULONG pGeneratedCodeLength
)
{
if (!pCode || !pGeneratedCodeLength)
return STATUS_INVALID_PARAMETER;
pCode = 0x48;
pCode = 0xcf;
*pGeneratedCodeLength += 2;
//DbgPrint(("CmGenerateIretq\n"));
return STATUS_SUCCESS;
}
NTSTATUS NTAPI CmGenerateMovReg(
PUCHAR pCode,
PULONG pGeneratedCodeLength,
ULONG Register,
ULONG64 Value
)
{
ULONG uCodeLength;
if (!pCode || !pGeneratedCodeLength)
return STATUS_INVALID_PARAMETER;
switch (Register & ~REG_MASK) {
case REG_GP:
pCode = 0x48;
pCode = 0xb8 | (UCHAR)(Register & REG_MASK);
memcpy(&pCode, &Value, 8);
uCodeLength = 10;
break;
case REG_GP_ADDITIONAL:
pCode = 0x49;
pCode = 0xb8 | (UCHAR)(Register & REG_MASK);
memcpy(&pCode, &Value, 8);
uCodeLength = 10;
break;
case REG_CONTROL:
uCodeLength = *pGeneratedCodeLength;
CmGenerateMovReg(pCode, pGeneratedCodeLength, REG_RAX, Value);
// calc the size of the "mov rax, value"
uCodeLength = *pGeneratedCodeLength - uCodeLength;
pCode += uCodeLength;
uCodeLength = 0;
if (Register == (REG_CR8)) {
// build 0x44 0x0f 0x22 0xc0
pCode = 0x44;
uCodeLength = 1;
pCode++;
Register = 0;
}
// mov crX, rax
pCode = 0x0f;
pCode = 0x22;
pCode = 0xc0 | (UCHAR)((Register & REG_MASK) << 3);
// *pGeneratedCodeLength has already been adjusted to the length of the "mov rax"
uCodeLength += 3;
}
if (pGeneratedCodeLength)
*pGeneratedCodeLength += uCodeLength;
//DbgPrint((" CmGenerateMovReg\n"));
return STATUS_SUCCESS;
}
NTSTATUS NTAPI CmGeneratePushReg(
PUCHAR pCode,
PULONG pGeneratedCodeLength,
ULONG Register
)
{
if (!pCode || !pGeneratedCodeLength)
return STATUS_INVALID_PARAMETER;
if ((Register & ~REG_MASK) != REG_GP)
return STATUS_NOT_SUPPORTED;
pCode = 0x50 | (UCHAR)(Register & REG_MASK);
*pGeneratedCodeLength += 1;
//DbgPrint((" CmGeneratePushReg\n"));
return STATUS_SUCCESS;
}
NTSTATUS NTAPI MmInitEptPageTable()
{
PHYSICAL_ADDRESS FirstPtePA, FirstPdePA, FirstPdptePA, l1, l2, l3;
PULONG64 FirstPteVA, FirstPdeVA, FirstPdpteVA, FirstPml4eVA;
PULONG64 FirstPdeVa_Legacy;
ULONG64 i, j;
l1.QuadPart = 0;
l2.QuadPart = -1;
l3.QuadPart = 0x200000;
//FirstPteVA = (PULONG64)MmAllocateContiguousMemorySpecifyCache(64 * PAGE_SIZE, l1, l2, l3, MmCached);// MmAllocateContiguousPagesSpecifyCache(512, &FirstPtePA, MmCached);
//if (!FirstPteVA)
// return NULL;
//RtlZeroMemory(FirstPteVA, 64 * PAGE_SIZE);
//FirstPtePA = MmGetPhysicalAddress(FirstPteVA);
//KdPrint(("FirstPteVA 0x%p FirstPtePA 0x%llX\n", FirstPteVA, FirstPtePA.QuadPart));
//for (i = 0; i < 512; i++)
//{
// for (j = 0; j < 512; j++) {
// *FirstPteVA = ((i *0x200000) + j * 0x1000) | EPT_READ | EPT_WRIT | EPT_EXECUTE;
// FirstPteVA++;
// }
//}
DbgPrint("vmx:FirstPteVA 0x%p FirstPtePA 0x%llX\n", FirstPteVA, FirstPtePA.QuadPart);
//64*512 Pde
//FirstPdeVA = (PULONG64)MmAllocateContiguousMemorySpecifyCache(64 * PAGE_SIZE, l1, l2, l3, MmCached);
FirstPdeVA = AllocateContiguousMemory(64 * PAGE_SIZE);
if (!FirstPdeVA)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(FirstPdeVA, 64 * PAGE_SIZE);
FirstPdePA = MmGetPhysicalAddress(FirstPdeVA);
EPT_Ptable.PDE = (ULONG64)FirstPdeVA;
EPT_Ptable.PDEPHY = FirstPdePA;
DbgPrint("vmx:MmInitIdentityPageTable: FirstPdeVA 0x%p FirstPdePA 0x%llX\n", FirstPdeVA, FirstPdePA.QuadPart);
for (i = 0; i < 64; i++) {
for (j = 0; j < 512; j++) {
*FirstPdeVA = ((i * 0x40000000) + j * 0x200000) | EPT_READ | EPT_WRIT | EPT_EXECUTE | P_LARGE;
FirstPdeVA++;
}
}
DbgPrint("vmx:MmInitIdentityPageTable: FirstPdeVA 0x%p FirstPdePA 0x%llX\n", FirstPdeVA, FirstPdePA.QuadPart);
//////////////////////////////////////////
//64 Pdpte
//FirstPdpteVA = (PULONG64)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, l1, l2, l3, MmCached);
FirstPdpteVA = AllocateContiguousMemory(PAGE_SIZE);
if (!FirstPdpteVA)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(FirstPdpteVA, PAGE_SIZE);
FirstPdptePA = MmGetPhysicalAddress(FirstPdpteVA);
EPT_Ptable.PDPTE = (ULONG64)FirstPdpteVA;
EPT_Ptable.PDPTEPHY = FirstPdptePA;
DbgPrint("vmx:MmInitIdentityPageTable: FirstPdpteVA 0x%p FirstPdptePA 0x%llX\n", FirstPdpteVA, FirstPdptePA.QuadPart);
for (i = 0; i < 64; i++)
{
{
*FirstPdpteVA = (i * 0x1000 + FirstPdePA.QuadPart) | EPT_READ | EPT_WRIT | EPT_EXECUTE;
FirstPdpteVA++;
}
}
//Pml4e
//FirstPml4eVA = (PULONG64)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, l1, l2, l3, MmCached);
FirstPml4eVA = AllocateContiguousMemory(PAGE_SIZE);
if (!FirstPml4eVA)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(FirstPml4eVA, PAGE_SIZE);
EPT_Ptable.PML4E = (ULONG64)FirstPml4eVA;
EPT_Ptable.PML4EPHY = MmGetPhysicalAddress(FirstPml4eVA);
DbgPrint("vmx:MmInitIdentityPageTable: FirstPml4eVA 0x%p EPT_Ptable.PML4EPHY0x%llX\n", FirstPml4eVA,
EPT_Ptable.PML4EPHY.QuadPart);
*FirstPml4eVA = (FirstPdptePA.QuadPart) | EPT_READ | EPT_WRIT | EPT_EXECUTE;
//do_guest_physical_address_mapping(0x7409AF88,0x7409AF88);
return STATUS_SUCCESS;
}
**** Hidden Message *****
6666666666666666666666 学习了学习了 学习了! 66666666666666666666666666666 看看全不全吧。。哎 6666666666666666666666 文件已被分享者删除
6666666666666666666666
页:
[1]