首页
社区
课程
招聘
[原创]64位“最”简VT Demo code 一枚(1)
发表于: 2016-1-10 16:45 18414

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

2016-1-10 16:45
18414

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中,需要注意的是栈要平衡。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (9)
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
这个代码很眼熟。。要是NBP里面整出来的 挺辛苦的~~~。用VIRDBG 吧改改 还凑合
2016-1-10 19:32
0
雪    币: 24
活跃值: (1353)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
没看见源码
2016-1-12 21:05
0
雪    币: 284
活跃值: (3554)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
4
@正文第四行

“代码见:https://github.com/DeDf/nbp-0.32-plus”
2016-1-13 10:35
0
雪    币: 24
活跃值: (1353)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
非常感谢
2016-1-13 15:26
0
雪    币: 19
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢分享!
2016-2-12 21:23
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
其实你这个玩意是个“残品"不信你到win10 64上试试
先回导致vmtool崩溃
紧接着就是蓝屏
有的时候是直接蓝屏或者是假死
上传的附件:
2016-2-13 22:59
0
雪    币: 284
活跃值: (3554)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
8
我信~~
2016-2-15 00:25
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢楼主的分享
2017-6-28 15:17
0
雪    币: 870
活跃值: (2264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
谢谢分享
2018-7-26 16:39
0
游客
登录 | 注册 方可回帖
返回
//