README.md
Rendering markdown...
#include "hypervbsod.h"
//
// thanks to Hypervisor from scratch project (developed by @Intel80x86) to provide some piece of driver code examples:
// https://github.com/SinaKarvandi/Hypervisor-From-Scratch/tree/master/Part%208%20-%20How%20To%20Do%20Magic%20With%20Hypervisor!/Hypervisor%20From%20Scratch/MyHypervisorDriver
//
PVOID AllocatePageAlignedMemory(ULONG64 size)
{
PHYSICAL_ADDRESS PhysicalMax = { 0 };
PVOID pBuffer = NULL;
UINT64 AlignedBuffer;
PhysicalMax.QuadPart = MAXULONG64;
pBuffer = MmAllocateContiguousMemory(size + PAGE_SIZE, PhysicalMax);
if (!pBuffer)
return NULL;
RtlSecureZeroMemory(pBuffer, size + PAGE_SIZE);
AlignedBuffer = (BYTE*)((ULONG_PTR)((UINT64)pBuffer + size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
return (PVOID)AlignedBuffer;
}
BOOLEAN FillBuffer(PCHAR buffer, ULONG64 len, CHAR symbol)
{
for (ULONG i = 0; i < len; i++)
{
buffer[i] = symbol;
}
return TRUE;
}
BOOLEAN HvActivateVpPages()
{
PHYSICAL_ADDRESS physAddr;
IA32_VMX_BASIC_MSR VmxBasicMsr = { 0 };
int Vmxon = 0;
PVOID pVmxon = NULL;
PHV_VP_ASSIST_PAGE pHvVpPage = NULL;
UINT64 physHvVpPage = 0;
//
// Enable VMX operations
//
ArchEnableVmx();
//
// Allocate VMXON region
//
pVmxon = AllocatePageAlignedMemory(PAGE_SIZE);
if (!pVmxon)
{
DbgPrint("VMXON region allocation failed\n");
return FALSE;
}
physAddr = MmGetPhysicalAddress(pVmxon);
VmxBasicMsr.All = __readmsr(MSR_IA32_VMX_BASIC);
*(UINT64*)pVmxon = VmxBasicMsr.Fields.RevisionIdentifier;
Vmxon = __vmx_on(&physAddr.QuadPart);
if (Vmxon)
{
DbgPrint("Executing Vmxon instruction failed with status : %d\n", Vmxon);
return FALSE;
}
//
// Allocate HV_VP_ASSIST_PAGE for specific processor
//
pHvVpPage = AllocatePageAlignedMemory(PAGE_SIZE);
if (!pHvVpPage)
{
DbgPrint("Hyper-V VP page allocation failed\n");
return FALSE;
}
physAddr = MmGetPhysicalAddress(pHvVpPage);
physHvVpPage = physAddr.QuadPart;
//
// Set PFN of VP page and Enable it
//
VIRTUAL_VP_ASSIST_PAGE_PFN guestPFN = { 0 };
guestPFN.PFN = physHvVpPage / PAGE_SIZE;
guestPFN.Enable = 1;
//
// Allocate enlightened VMCS
//
PHV_VMX_ENLIGHTENED_VMCS pEnlVMCS = AllocatePageAlignedMemory(PAGE_SIZE);
if (!pEnlVMCS)
{
DbgPrint("Hyper-V enligthened VMCS page allocation failed\n");
__vmx_off();
return FALSE;
}
physAddr = MmGetPhysicalAddress(pEnlVMCS);
UINT64 physHvEnlVMCS = physAddr.QuadPart;
//
// Configure enlightened VMCS. If we write to HV_X64_MSR_APIC_ASSIST_PAGE after configuring, we get BSOD
//
//DbgBreakPoint();
pHvVpPage->EnlightenVmEntry = TRUE;
pHvVpPage->CurrentNestedVmcs = physHvEnlVMCS;
//FillBuffer((PCHAR)pHvVpPage, PAGE_SIZE, 0x11);
//__writemsr(HV_X64_MSR_APIC_ASSIST_PAGE, guestPFN.AsUINT64);
//If next 2 string will be uncomment, BSOD will not be generated.
//pHvVpPage->EnlightenVmEntry = TRUE;
//pHvVpPage->CurrentNestedVmcs = physHvEnlVMCS;
//
// Prepare to vmlaunch
//
int Vmclear = 0;
Vmclear = __vmx_vmclear(&physHvEnlVMCS);
if (Vmclear)
{
__vmx_off();
return FALSE;
}
__vmx_vmlaunch();
__vmx_off();
return TRUE;
}