登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 289|回复: 9

x64VT虚拟化框架源码

[复制链接]

171

主题

21

回帖

1048

积分

管理员

积分
1048
发表于 2025-2-22 23:11:14 | 显示全部楼层 |阅读模式
#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) %p  MsrRead(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) %p  ReadVMCS(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) %p  ReadVMCS(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() %p  GetIdtBase() %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[0x600];

        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], &uTrampolineSize, REG_RCX, GuestRegs->rcx);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RDX, GuestRegs->rdx);

        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RBX, GuestRegs->rbx);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RBP, GuestRegs->rbp);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RSI, GuestRegs->rsi);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RDI, GuestRegs->rdi);

#ifndef _X86_
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R8, GuestRegs->r8);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R9, GuestRegs->r9);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R10, GuestRegs->r10);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R11, GuestRegs->r11);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R12, GuestRegs->r12);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R13, GuestRegs->r13);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R14, GuestRegs->r14);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R15, GuestRegs->r15);
#endif

        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR0, ReadVMCS(GUEST_CR0));
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR3, ReadVMCS(GUEST_CR3));
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR4, ReadVMCS(GUEST_CR4));

        NewRsp = ReadVMCS(GUEST_RSP);

        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RSP, NewRsp);

        // construct stack frame for IRETQ:
        // [TOS]        rip
        // [TOS+0x08]   cs
        // [TOS+0x10]   rflags
        // [TOS+0x18]   rsp
        // [TOS+0x20]   ss

        // construct stack frame for IRETD:
        // [TOS]        rip
        // [TOS+0x4]    cs
        // [TOS+0x8]    rflags

#ifndef _X86_
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_SS_SELECTOR));
        CmGeneratePushReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, NewRsp);
        CmGeneratePushReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX);
#endif
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_RFLAGS));
        CmGeneratePushReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX);
        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, ReadVMCS(GUEST_CS_SELECTOR));
        CmGeneratePushReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX);

        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX,
                ReadVMCS(GUEST_RIP) + ReadVMCS(VM_EXIT_INSTRUCTION_LEN));

        CmGeneratePushReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX);

        CmGenerateMovReg(&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, GuestRegs->rax);

#ifdef _X86_
        CmGenerateIretd(&Trampoline[uTrampolineSize], &uTrampolineSize);
#else
        CmGenerateIretq(&Trampoline[uTrampolineSize], &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[0] = 0x48;
        pCode[1] = 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[0] = 0x48;
                pCode[1] = 0xb8 | (UCHAR)(Register & REG_MASK);
                memcpy(&pCode[2], &Value, 8);
                uCodeLength = 10;
                break;

        case REG_GP_ADDITIONAL:
                pCode[0] = 0x49;
                pCode[1] = 0xb8 | (UCHAR)(Register & REG_MASK);
                memcpy(&pCode[2], &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[0] = 0x44;
                        uCodeLength = 1;
                        pCode++;
                        Register = 0;
                }
                // mov crX, rax

                pCode[0] = 0x0f;
                pCode[1] = 0x22;
                pCode[2] = 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[0] = 0x50 | (UCHAR)(Register & REG_MASK);
        *pGeneratedCodeLength += 1;
        //DbgPrint((" CmGeneratePushReg\n"));
        return STATUS_SUCCESS;
}


NTSTATUS NTAPI MmInitEptPageTable()
{
        PHYSICAL_ADDRESS FirstPtePA[5], FirstPdePA, FirstPdptePA, l1, l2, l3;
        PULONG64 FirstPteVA[5], FirstPdeVA, FirstPdpteVA, FirstPml4eVA;
        PULONG64 FirstPdeVa_Legacy;
        ULONG64 i, j;
        l1.QuadPart = 0;
        l2.QuadPart = -1;
        l3.QuadPart = 0x200000;


        //FirstPteVA[0] = (PULONG64)MmAllocateContiguousMemorySpecifyCache(64 * PAGE_SIZE, l1, l2, l3, MmCached);// MmAllocateContiguousPagesSpecifyCache(512, &FirstPtePA[0], MmCached);
        //if (!FirstPteVA[0])
        //        return NULL;
        //RtlZeroMemory(FirstPteVA[0], 64 * PAGE_SIZE);
        //FirstPtePA[0] = MmGetPhysicalAddress(FirstPteVA[0]);
        //KdPrint(("FirstPteVA[0] 0x%p FirstPtePA[0] 0x%llX\n", FirstPteVA[0], FirstPtePA[0].QuadPart));
        //for (i = 0; i < 512; i++) 
        //{
        //        for (j = 0; j < 512; j++) {
        //                *FirstPteVA[0] = ((i *0x200000) + j * 0x1000) | EPT_READ | EPT_WRIT | EPT_EXECUTE;
        //                FirstPteVA[0]++;
        //        }
        //}

        DbgPrint("vmx:FirstPteVA[0] 0x%p FirstPtePA[0] 0x%llX\n", FirstPteVA[0], FirstPtePA[0].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.PML4EPHY  0x%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;
}


游客,如果您要查看本帖隐藏内容请回复



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2025-2-25 14:41:53 | 显示全部楼层
6666666666666666666666
回复

使用道具 举报

0

主题

1

回帖

2

积分

新手上路

积分
2
发表于 2025-2-25 14:44:23 | 显示全部楼层
学习了学习了
回复

使用道具 举报

0

主题

6

回帖

7

积分

新手上路

积分
7
发表于 2025-2-25 15:28:53 | 显示全部楼层
学习了!
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2025-2-25 15:33:06 | 显示全部楼层
66666666666666666666666666666
回复

使用道具 举报

0

主题

9

回帖

54

积分

新手上路

积分
54
发表于 2025-3-11 10:42:20 | 显示全部楼层
看看全不全吧。。哎
回复

使用道具 举报

0

主题

31

回帖

240

积分

注册会员

积分
240
发表于 2025-3-24 09:14:51 | 显示全部楼层
6666666666666666666666
回复

使用道具 举报

0

主题

31

回帖

240

积分

注册会员

积分
240
发表于 2025-3-24 09:15:22 | 显示全部楼层
文件已被分享者删除

点评

链接已经更新  发表于 2025-3-24 18:00
回复

使用道具 举报

0

主题

4

回帖

2

积分

新手上路

积分
2
发表于 昨天 21:02 | 显示全部楼层
6666666666666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-4-4 10:42 , Processed in 0.122424 second(s), 23 queries , Yac On.

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表