欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]64位“最”简VT Demo code 一枚(1)

[原创]64位“最”简VT Demo code 一枚(1)

64位“最”简VT Demo code 一枚(1)
“最”简意味着没有实际功能,但代码精简易读,在学习VT时可作参考。
test目录有cpuid.exe,加载编译后的sys后cpuid.exe输出不同。
代码见:https://github.com/DeDf/nbp-0.32-plus
编译说明:
WDK 7.1 “WIN7 x64 Checked Build Environment”,cd进源码目录,bld回车即可;
源码目录有amd64目录,里面放asm文件,配合sources里的:
AMD64_SOURCES=\
    vmx-asm.asm \
    common-asm.asm \
    regs.asm
可以编译asm,所以不要修改amd64目录名。
代码改自nbp-0.32-plus,Copyright holder: Invisible Things Lab
====== newbp.c ======
/* 
 * Copyright holder: Invisible Things Lab
 */
#include <ntddk.h>
#include "hvm.h"
VOID
DriverUnload (
    PDRIVER_OBJECT DriverObject
)
{
    if ( HvmSpitOutBluepill () )    // 吐出药丸子
        KdPrint (("[NEWBLUEPILL] HvmSpitOutBluepill() failed!\n"));
    else
        KdPrint (("[NEWBLUEPILL] Unloading finished~\n"));
}
NTSTATUS
DriverEntry (
    PDRIVER_OBJECT DriverObject,
    PUNICODE_STRING RegistryPath
)
{
    KdPrint (("\n[NEWBLUEPILL] DriverEntry~\n"));
    if (!VmxIsImplemented ())
    {
        KdPrint (("DriverEntry(): VMX is not supported!\n"));
        return STATUS_NOT_SUPPORTED;
    }
        
    if ( HvmSwallowBluepill () )    // 吞下药丸子
    {
        KdPrint (("[NEWBLUEPILL] HvmSwallowBluepill() failed!\n"));
        return STATUS_UNSUCCESSFUL;
    }
    DriverObject->DriverUnload = DriverUnload;
    KdPrint (("[NEWBLUEPILL] Initialization finished~\n"));
    return STATUS_SUCCESS;
}
VmxIsImplemented ()通过cpuid指令,探测CPU是否支持VMX,
"适用于cpu的intel虚拟化技术叫VT-x,通过VMX架构来实现VT-x"..
HvmSwallowBluepill() 初始化VT,
HvmSpitOutBluepill () 退出VT;
====== hvm.c ======
HvmSwallowBluepill():
在CPU每个核心分别执行CmSubvert;
HvmSpitOutBluepill ():
在CPU每个核心分别执行VmxVmCall (NBP_HYPERCALL_UNLOAD)来退出VT;
====== common-asm.asm ======
CmSubvert 里push了所有通用寄存器,然后把此时的esp作为参数call HvmSubvertCpu;
HvmSubvertCpu()->VmxSetupVMCS()会把这个esp写入VT里的GUEST_RSP,并把CmGuestEip函数地址写入VT里的GUEST_RIP;
CmGuestEip里会依序弹出所有的通用寄存器,然后ret.
当__vmx_vmlaunch()并且从VMM Exit到VM中,换句话说VT初始化完成第一次回到OS中,(VMM - VM monitor)
此时esp和eip会被CPU设置为GUEST_RSP和GUEST_RIP,
那么CmSubvert和CmGuestEip分别push和pop了通用寄存器,并且保证了栈平衡,VMM里做了什么处理,对OS是透明了。
====== hvm.c ======
HvmSubvertCpu()
关于VT开启的过程和各控制域后面说,先把外面的脉络理清楚;
这里申请了三块内存,存放于以下结构里,方便卸载时释放,每个CPU核心一个;
typedef struct _CPU
{
    PVOID OriginalVmcs;    // VMCS结构,每个guest OS 一个
    PVOID OriginaVmxonR;   // Vmxon结构,每个CPU核心一个
    PVOID VMM_Stack;       // VMM栈
} CPU, *PCPU;
其中前两者是用MmAllocateContiguousMemory申请的内存,貌似意味着需要4K对齐和物理上连续;
栈是向下增长的,所以这样:
VMM_Stack = (ULONG_PTR)pCpu->VMM_Stack + 2 * PAGE_SIZE - 8;
这个栈是当VMM Entry时的栈,由VmxSetupVMCS设置的:
// HOST_RSP与HOST_RIP决定进入VMM的地址
  __vmx_vmwrite (HOST_RSP, VMM_Stack);
  __vmx_vmwrite (HOST_RIP, (ULONG64) VmxVmexitHandler);
VmxVmexitHandler是进入到VMM时的eip,位于vmx-asm.asm中,需要注意的是栈要平衡。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功