基本信息
源码名称:vt开发源码
源码大小:0.53M
文件格式:.rar
开发语言:C/C++
更新时间:2015-07-04
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
extern "C"
{
#include <ntddk.h>
}
#include "ntiologc.h"
#include <windef.h>
#include <stdio.h>
#include <string.h>
#include "stdarg.h"
#include "ntimage.h"
#include "ntiologc.h"
#include <windef.h>
#include "jeinSysBase.H"
//////////////////////////////////////////////////////////////////////////
#define SEC_IMAGE 0x01000000
//////////////////////////////////////////////////////////////////////////
#define IOCTL_EVENT_MSG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x927, METHOD_BUFFERED , FILE_ANY_ACCESS)
#pragma warning(disable: 4047 4018)
#ifdef __cplusplus
extern "C"
#endif
char buf_gmifo[]= {0xBB,0xB6,0xD3,0xAD,0xBC,0xBC,0xCA,0xF5,0xBD,0xBB,0xC1,0xF7,0x20,0xCE,0xD2,0xB5, 0xC4,0x51,0x51,0x20,};
void ShowInfo()
{
DbgPrint("代码无卸载部分,驱动加载前请要保存好文档! \n");
DbgPrint("只支持单核测试,请在boot.ini中添加 /numproc=1 \n");
DbgPrint("%s %d\n\n",buf_gmifo,HOST_QQ_GM);
}
//////////////////////////////////////////////////////////////////////////
#pragma pack(1)
typedef struct
{
unsigned short LowOffset;
unsigned short selector;
unsigned char unused_lo;
unsigned char segment_type:4; //0x0E is an interrupt gate
unsigned char system_segment_flag:1;
unsigned char DPL:2; // descriptor privilege level
unsigned char P:1; /* present */
unsigned short HiOffset;
} IDTENTRY;
/* sidt returns idt in this format */
typedef struct
{
unsigned short IDTLimit;
unsigned short LowIDTbase;
unsigned short HiIDTbase;
} IDTINFO;
#define IDT_INFO IDTINFO
#define IDT_ENTRY IDTENTRY
#pragma pack()
//////////////////////////////////////////////////////////////////////////
VOID UnloadDriver(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS Dclose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS HideProcess_IoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS JeinIOControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp);
//////////////////////////////////////////////////////////////////////////
#define HIDE_PROCESS_WIN32_DEV_NAME L"\\Device\\VT"
#define HIDE_PROCESS_DEV_NAME L"\\DosDevices\\VT"
#define FILE_DEVICE_EXTNDDRV 0x00008300
#define EXTNDDRV_IOCTL_INDEX 0x830
#define IOCTL_EXTNDDRV_GET_STARTING_SERVICEID CTL_CODE(FILE_DEVICE_EXTNDDRV, \
EXTNDDRV_IOCTL_INDEX, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
UNICODE_STRING DeviceNameString;
UNICODE_STRING LinkDeviceNameString;
CCHAR outBuf[1024];
int * PRecvinteger;
//////////////////////////////////////////////////////////////////////////
NTSTATUS DCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
NTSTATUS Dclose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
VOID UnloadDriver(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("UnloadDriver ! ");
PDEVICE_OBJECT deviceObject;
deviceObject= DriverObject->DeviceObject;
IoDeleteSymbolicLink(&LinkDeviceNameString);
ASSERT(!deviceObject->AttachedDevice);
if (deviceObject != NULL )
{
IoDeleteDevice( deviceObject );
}
}
NTSTATUS JeinIOControl(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
ULONG info = 0;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = info; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return status;
}
#define Log( message, value ) { DbgPrint("[vmm] %-40s [%08X]\n", message, value ); }
///////////////
// //
// SET BIT //
// //
///////////////
VOID SetBit( ULONG * dword, ULONG bit )
{
ULONG mask = ( 1 << bit );
*dword = *dword | mask;
}
VOID ClearBit( ULONG * dword, ULONG bit )
{
ULONG mask = 0xFFFFFFFF;
ULONG sub = ( 1 << bit );
mask = mask - sub;
*dword = *dword & mask;
}
VOID ClearBit( VOID * dword_, ULONG bit )
{
ULONG mask = 0xFFFFFFFF;
ULONG sub = ( 1 << bit );
mask = mask - sub;
ULONG * dword = (ULONG*)dword_;
*dword = *dword & mask;
}
ULONG *pVMXONRegion = NULL; // Memory address of VMXON region.
ULONG *pVMCSRegion = NULL; // Memory address of VMCS region.
ULONG VMXONRegionSize = 0; // Size of of VMXON region.
ULONG VMCSRegionSize = 0; // Size of of VMCS region.
ULONG ErrorCode = 0;
EFLAGS eFlags = {0};
MSR msr = {0};
PVOID FakeStack = NULL;
ULONG HandlerLogging = 0;
ULONG ScrubTheLaunch = 0;
ULONG VMXIsActive = 0;
VOID WriteVMCS( ULONG encoding, ULONG value )
{
__asm
{
PUSHAD
PUSH value
MOV EAX, encoding
_emit 0x0F // VMWRITE EAX, [ESP]
_emit 0x79
_emit 0x04
_emit 0x24
POP EAX
POPAD
}
}
DWORD VmxRead(DWORD in_code)
{
DWORD m_vmread = 0;
__asm
{
PUSHAD
MOV EAX, in_code //ExitInterruptionInformation
_emit 0x0F // VMREAD EBX, EAX
_emit 0x78
_emit 0xC3
MOV m_vmread, EBX
POPAD
}
return m_vmread;
}
// Loads the contents of a 64-bit model specific register (MSR) specified
// in the ECX register into registers EDX:EAX. The EDX register is loaded
// with the high-order 32 bits of the MSR and the EAX register is loaded
// with the low-order 32 bits.
// msr.Hi --> EDX
// msr.Lo --> EAX
//
VOID ReadMSR( ULONG msrEncoding )
{
__asm
{
PUSHAD
MOV ECX, msrEncoding
RDMSR
MOV msr.Hi, EDX
MOV msr.Lo, EAX
POPAD
}
}
////////////////////////////////////
// //
// SEGMENT DESCRIPTOR OPERATORS //
// //
////////////////////////////////////
ULONG GetSegmentDescriptorBase( ULONG gdt_base , USHORT seg_selector )
{
ULONG base = 0;
SEG_DESCRIPTOR segDescriptor = {0};
RtlCopyBytes( &segDescriptor, (ULONG *)(gdt_base (seg_selector >> 3) * 8), 8 );
base = segDescriptor.BaseHi;
base <<= 8;
base |= segDescriptor.BaseMid;
base <<= 16;
base |= segDescriptor.BaseLo;
return base;
}
ULONG GetSegmentDescriptorDPL( ULONG gdt_base , USHORT seg_selector )
{
SEG_DESCRIPTOR segDescriptor = {0};
RtlCopyBytes( &segDescriptor, (ULONG *)(gdt_base (seg_selector >> 3) * 8), 8 );
return segDescriptor.DPL;
}
ULONG GetSegmentDescriptorLimit( ULONG gdt_base , USHORT seg_selector )
{
SEG_DESCRIPTOR segDescriptor = {0};
RtlCopyBytes( &segDescriptor, (ULONG *)(gdt_base (seg_selector >> 3) * 8), 8 );
return ( (segDescriptor.LimitHi << 16) | segDescriptor.LimitLo );
}
PHYSICAL_ADDRESS PhysicalVMXONRegionPtr;
PHYSICAL_ADDRESS PhysicalVMCSRegionPtr;
VMX_FEATURES vmxFeatures;
IA32_VMX_BASIC_MSR vmxBasicMsr ;
IA32_FEATURE_CONTROL_MSR vmxFeatureControl ;
CR0_REG cr0_reg = {0};
CR4_REG cr4_reg = {0};
ULONG temp32 = 0;
USHORT temp16 = 0;
GDTR gdt_reg = {0};
IDTR idt_reg = {0};
ULONG gdt_base = 0;
ULONG idt_base = 0;
USHORT mLDT = 0;
USHORT seg_selector = 0;
SEG_DESCRIPTOR segDescriptor = {0};
MISC_DATA misc_data = {0};
PVOID GuestReturn = NULL;
ULONG GuestStack = 0;
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
RtlInitUnicodeString( &DeviceNameString, HIDE_PROCESS_WIN32_DEV_NAME );
RtlInitUnicodeString( &LinkDeviceNameString,HIDE_PROCESS_DEV_NAME );
DbgPrint("--------------------------------- Intel VT ---------------------\n ");
status = IoCreateDevice(
DriverObject,
0,
&DeviceNameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
& deviceObject );
if (!NT_SUCCESS( status ))
{
DbgPrint("Error creating control device object");
return status;
}
status = IoCreateSymbolicLink(
(PUNICODE_STRING) &LinkDeviceNameString,
(PUNICODE_STRING) &DeviceNameString
);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(deviceObject);
return status;
}
ShowInfo();
DriverObject->MajorFunction[IRP_MJ_CREATE] = DCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dclose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = JeinIOControl;
DriverObject->DriverUnload = UnloadDriver;
//////////////////////////////////////////////////////////////////////////
ULONG EntryEFlags = 0;
ULONG cr4 = 0;
ULONG EntryEAX = 0;
ULONG EntryECX = 0;
ULONG EntryEDX = 0;
ULONG EntryEBX = 0;
ULONG EntryESP = 0;
ULONG EntryEBP = 0;
ULONG EntryESI = 0;
ULONG EntryEDI = 0;
__asm
{
PUSHAD
MOV EAX, 1
CPUID
// ECX contains the VMX_FEATURES FLAGS (VMX supported if bit 5 equals 1)
MOV vmxFeatures, ECX
MOV EAX, 0x80000008
CPUID
MOV temp32, EAX
POPAD
}
if( vmxFeatures.VMX == 0 )
{
Log( "CPU不支持!" , vmxFeatures );
return STATUS_UNSUCCESSFUL;
}
else
{
Log( "CPU支持VT!" , vmxFeatures );
}
//////////////////////////////////////////////////////////////////////////
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR4
_emit 0x20
_emit 0xE0
MOV cr4, EAX
POP EAX
}
//////////////////////////////////////////////////////////////////////////
pVMXONRegion = (ULONG*)MmAllocateNonCachedMemory( 4096 );
if( pVMXONRegion == NULL )
{
Log( "ERROR : Allocating VMXON Region memory." , 0 );
return STATUS_UNSUCCESSFUL;
}
Log( "VMXONRegion virtual address" , pVMXONRegion );
RtlZeroMemory( pVMXONRegion, 4096 );
PhysicalVMXONRegionPtr = MmGetPhysicalAddress( pVMXONRegion );
Log( "VMXONRegion physical address" , PhysicalVMXONRegionPtr.LowPart );
// Allocate the VMCS region memory.
//
pVMCSRegion = (ULONG*)MmAllocateNonCachedMemory( 4096 );
if( pVMCSRegion == NULL )
{
Log( "ERROR : Allocating VMCS Region memory." , 0 );
MmFreeNonCachedMemory( pVMXONRegion , 4096 );
return STATUS_UNSUCCESSFUL;
}
Log( "VMCSRegion virtual address" , pVMCSRegion );
RtlZeroMemory( pVMCSRegion, 4096 );
PhysicalVMCSRegionPtr = MmGetPhysicalAddress( pVMCSRegion );
Log( "VMCSRegion physical address" , PhysicalVMCSRegionPtr.LowPart );
// Allocate stack for the VM Exit Handler.
//
FakeStack = ExAllocatePoolWithTag( NonPagedPool , 0x2000, 'vmcs' );
if( FakeStack == NULL )
{
Log( "ERROR : Allocating VM Exit Handler stack memory." , 0 );
MmFreeNonCachedMemory( pVMXONRegion , 4096 );
MmFreeNonCachedMemory( pVMCSRegion , 4096 );
return STATUS_UNSUCCESSFUL;
}
Log( "FakeStack" , FakeStack );
//////////////////////////////////////////////////////////////////////////
__asm
{
CLI
MOV GuestStack, ESP
}
// Save the state of the architecture.
//
__asm
{
PUSHAD
POP EntryEDI
POP EntryESI
POP EntryEBP
POP EntryESP
POP EntryEBX
POP EntryEDX
POP EntryECX
POP EntryEAX
PUSHFD
POP EntryEFlags
}
//////////////////////////////////////////////////////////////////////////
DbgPrint("StartVMX() == %08X " , StartVMX );
//启动
StartVMX( );
// Restore the state of the architecture.
//
__asm
{
PUSH EntryEFlags
POPFD
PUSH EntryEAX
PUSH EntryECX
PUSH EntryEDX
PUSH EntryEBX
PUSH EntryESP
PUSH EntryEBP
PUSH EntryESI
PUSH EntryEDI
POPAD
}
__asm
{
STI
MOV ESP, GuestStack
}
if( ScrubTheLaunch == 1 )
{
Log( "ERROR : Launch aborted." , 0 );
MmFreeNonCachedMemory( pVMXONRegion , 4096 );
MmFreeNonCachedMemory( pVMCSRegion , 4096 );
//堆栈
ExFreePoolWithTag( FakeStack, 'vmcs' );
return STATUS_UNSUCCESSFUL;
}
Log( "VM is now executing." , 0 );
return STATUS_SUCCESS;
}
__declspec( naked ) VOID StartVMX( )
{
//
// Get the Guest Return EIP.
//
//
// Hi | |
// -----------
// | EIP |
// ----------- <-- ESP after the CALL
// Lo | |
//
//
__asm POP GuestReturn
Log("Guest Return EIP" , GuestReturn );
///////////////////////////
// //
// SET THREAD AFFINITY //
// //
///////////////////////////
// Log( "Enabling VMX mode on CPU 0", 0 );
// KeSetSystemAffinityThread( (KAFFINITY) 0x00000001 );
// Log( "Running on Processor" , KeGetCurrentProcessorNumber() );
////////////////
// //
// GDT Info //
// //
////////////////
__asm
{
SGDT gdt_reg
}
temp32 = 0;
temp32 = gdt_reg.BaseHi;
temp32 <<= 16;
temp32 |= gdt_reg.BaseLo;
gdt_base = temp32;
Log( "GDT Base", gdt_base );
Log( "GDT Limit", gdt_reg.Limit );
////////////////////////////
// //
// IDT Segment Selector //
// //
////////////////////////////
__asm SIDT idt_reg
temp32 = 0;
temp32 = idt_reg.BaseHi;
temp32 <<= 16;
temp32 |= idt_reg.BaseLo;
idt_base = temp32;
/*
[vmm] GDT Base [8003F000]
[vmm] GDT Limit [000003FF]
[vmm] IDT Base [8003F400]
*/
Log( "IDT Base", idt_base );
Log( "IDT Limit", idt_reg.Limit );
// (1) Check VMX support in processor using CPUID.
__asm
{
PUSHAD
MOV EAX, 1
CPUID
// ECX contains the VMX_FEATURES FLAGS (VMX supported if bit 5 equals 1)
MOV vmxFeatures, ECX
MOV EAX, 0x80000008
CPUID
MOV temp32, EAX
POPAD
}
if( vmxFeatures.VMX == 0 )
{
Log( "VMX Support Not Present." , vmxFeatures );
goto Abort;
}
Log( "VMX Support Present." , vmxFeatures );
// (2) Determine the VMX capabilities supported by the processor through
// the VMX capability MSRs.
__asm
{
PUSHAD
MOV ECX, IA32_VMX_BASIC_MSR_CODE
RDMSR
LEA EBX, vmxBasicMsr
MOV [EBX 4], EDX
MOV [EBX], EAX
MOV ECX, IA32_FEATURE_CONTROL_CODE
RDMSR
LEA EBX, vmxFeatureControl
MOV [EBX 4], EDX
MOV [EBX], EAX
POPAD
};
// (3) Create a VMXON region in non-pageable memory of a size specified by
// IA32_VMX_BASIC_MSR and aligned to a 4-byte boundary. The VMXON region
// must be hosted in cache-coherent memory.
Log( "VMXON Region Size" , vmxBasicMsr.szVmxOnRegion ) ;
Log( "VMXON Access Width Bit" , vmxBasicMsr.PhyAddrWidth );
Log( " [ 1] --> 32-bit" , 0 );
Log( " [ 0] --> 64-bit" , 0 );
Log( "VMXON Memory Type", vmxBasicMsr.MemType );
Log( " [ 0] --> Strong Uncacheable" , 0 );
Log( " [ 1-5] --> Unused" , 0 );
Log( " [ 6] --> Write Back" , 0 );
Log( " [7-15] --> Unused" , 0 );
VMXONRegionSize = vmxBasicMsr.szVmxOnRegion;
switch( vmxBasicMsr.MemType )
{
case 0:
Log( "Unsupported memory type." , vmxBasicMsr.MemType );
goto Abort;
break;
case 6:
break;
default:
Log( "ERROR : Unknown VMXON Region memory type." , 0);
goto Abort;
break;
}
// (4) Initialize the version identifier in the VMXON region (first 32 bits)
// with the VMCS revision identifier reported by capability MSRs.
*(pVMXONRegion) = vmxBasicMsr.RevId;
Log( "vmxBasicMsr.RevId" , vmxBasicMsr.RevId );
// (5) Ensure the current processor operating mode meets the required CR0
// fixed bits (CR0.PE=1, CR0.PG=1). Other required CR0 fixed bits can
// be detected through the IA32_VMX_CR0_FIXED0 and IA32_VMX_CR0_FIXED1
// MSRs.
__asm
{
PUSH EAX
MOV EAX, CR0
MOV cr0_reg, EAX
POP EAX
}
if( cr0_reg.PE != 1 )
{
Log( "ERROR : Protected Mode not enabled." , 0 );
Log( "Value of CR0" , cr0_reg );
goto Abort;
}
Log( "Protected Mode enabled." , 0 );
if( cr0_reg.PG != 1 )
{
Log( "ERROR : Paging not enabled." , 0 );
Log( "Value of CR0" , cr0_reg );
goto Abort;
}
Log( "Paging enabled." , 0 );
cr0_reg.NE = 1;
__asm
{
PUSH EAX
MOV EAX, cr0_reg
MOV CR0, EAX
POP EAX
}
// (6) Enable VMX operation by setting CR4.VMXE=1 [bit 13]. Ensure the
// resultant CR4 value supports all the CR4 fixed bits reported in
// the IA32_VMX_CR4_FIXED0 and IA32_VMX_CR4_FIXED1 MSRs.
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR4
_emit 0x20
_emit 0xE0
MOV cr4_reg, EAX
POP EAX
}
Log( "CR4" , cr4_reg );
cr4_reg.VMXE = 1;
Log( "CR4" , cr4_reg );
__asm
{
PUSH EAX
MOV EAX, cr4_reg
_emit 0x0F // MOV CR4, EAX
_emit 0x22
_emit 0xE0
POP EAX
}
// (7) Ensure that the IA32_FEATURE_CONTROL_MSR (MSR index 0x3A) has been
// properly programmed and that its lock bit is set (bit 0=1). This MSR
// is generally configured by the BIOS using WRMSR.
Log( "IA32_FEATURE_CONTROL Lock Bit" , vmxFeatureControl.Lock );
if( vmxFeatureControl.Lock != 1 )
{
Log( "ERROR : Feature Control Lock Bit != 1." , 0 );
goto Abort;
}
// (8) Execute VMXON with the physical address of the VMXON region as the
// operand. Check successful execution of VMXON by checking if
// RFLAGS.CF=0.
__asm
{
PUSH 0
PUSH PhysicalVMXONRegionPtr.LowPart
_emit 0xF3 // VMXON [ESP]
_emit 0x0F
_emit 0xC7
_emit 0x34
_emit 0x24
PUSHFD
POP eFlags
ADD ESP, 8
}
if( eFlags.CF == 1 )
{
Log( "ERROR : VMXON operation failed." , 0 );
goto Abort;
}
Log( "SUCCESS : VMXON operation completed." , 0 );
Log( "VMM is now running." , 0 );
VMXIsActive = 1;
//
// *** The processor is now in VMX root operation!
//
// (1) Create a VMCS region in non-pageable memory of size specified by
// the VMX capability MSR IA32_VMX_BASIC and aligned to 4-KBytes.
// Software should read the capability MSRs to determine width of the
// physical addresses that may be used for a VMCS region and ensure
// the entire VMCS region can be addressed by addresses with that width.
// The term "guest-VMCS address" refers to the physical address of the
// new VMCS region for the following steps.
VMCSRegionSize = vmxBasicMsr.szVmxOnRegion;
switch( vmxBasicMsr.MemType )
{
case 0:
Log( "Unsupported memory type." , vmxBasicMsr.MemType );
goto Abort;
break;
case 6:
break;
default:
Log( "ERROR : Unknown VMCS Region memory type." , 0 );
goto Abort;
break;
}
// (2) Initialize the version identifier in the VMCS (first 32 bits)
// with the VMCS revision identifier reported by the VMX
// capability MSR IA32_VMX_BASIC.
*(pVMCSRegion) = vmxBasicMsr.RevId;
// (3) Execute the VMCLEAR instruction by supplying the guest-VMCS address.
// This will initialize the new VMCS region in memory and set the launch
// state of the VMCS to "clear". This action also invalidates the
// working-VMCS pointer register to FFFFFFFF_FFFFFFFFH. Software should
// verify successful execution of VMCLEAR by checking if RFLAGS.CF = 0
// and RFLAGS.ZF = 0.
__asm
{
PUSH 0
PUSH PhysicalVMCSRegionPtr.LowPart
_emit 0x66 // VMCLEAR [ESP]
_emit 0x0F
_emit 0xc7
_emit 0x34
_emit 0x24
ADD ESP, 8
PUSHFD
POP eFlags
}
if( eFlags.CF != 0 || eFlags.ZF != 0 )
{
Log( "ERROR : VMCLEAR operation failed." , 0 );
goto Abort;
}
Log( "SUCCESS : VMCLEAR operation completed." , 0 );
// (4) Execute the VMPTRLD instruction by supplying the guest-VMCS address.
// This initializes the working-VMCS pointer with the new VMCS region抯
// physical address.
__asm
{
PUSH 0
PUSH PhysicalVMCSRegionPtr.LowPart
_emit 0x0F // VMPTRLD [ESP]
_emit 0xC7
_emit 0x34
_emit 0x24
ADD ESP, 8
}
//
// ***************************************
// * *
// * H.1.1 16-Bit Guest-State Fields *
// * *
// ***************************************
//
// Guest ES selector 00000800H
__asm MOV seg_selector, ES
Log( "Setting Guest ES Selector" , seg_selector );
WriteVMCS( 0x00000800, seg_selector );
// Guest CS selector 00000802H
__asm MOV seg_selector, CS
Log( "Setting Guest CS Selector" , seg_selector );
WriteVMCS( 0x00000802, seg_selector );
// Guest SS selector 00000804H
__asm MOV seg_selector, SS
Log( "Setting Guest SS Selector" , seg_selector );
WriteVMCS( 0x00000804, seg_selector );
// Guest DS selector 00000806H
__asm MOV seg_selector, DS
Log( "Setting Guest DS Selector" , seg_selector );
WriteVMCS( 0x00000806, seg_selector );
// Guest FS selector 00000808H
__asm MOV seg_selector, FS
Log( "Setting Guest FS Selector" , seg_selector );
WriteVMCS( 0x00000808, seg_selector );
// Guest GS selector 0000080AH
__asm MOV seg_selector, GS
Log( "Setting Guest GS Selector" , seg_selector );
WriteVMCS( 0x0000080A, seg_selector );
// Guest TR selector 0000080EH
__asm STR seg_selector
ClearBit( &seg_selector, 2 ); // TI Flag
Log( "Setting Guest TR Selector" , seg_selector );
WriteVMCS( 0x0000080E, seg_selector );
// **************************************
// * *
// * H.1.2 16-Bit Host-State Fields *
// * *
// **************************************
//
// Host ES selector 00000C00H
__asm MOV seg_selector, ES
seg_selector &= 0xFFFC;
Log( "Setting Host ES Selector" , seg_selector );
WriteVMCS( 0x00000C00, seg_selector );
// Host CS selector 00000C02H
__asm MOV seg_selector, CS
Log( "Setting Host CS Selector" , seg_selector );
WriteVMCS( 0x00000C02, seg_selector );
// Host SS selector 00000C04H
__asm MOV seg_selector, SS
Log( "Setting Host SS Selector" , seg_selector );
WriteVMCS( 0x00000C04, seg_selector );
// Host DS selector 00000C06H
__asm MOV seg_selector, DS
seg_selector &= 0xFFFC;
Log( "Setting Host DS Selector" , seg_selector );
WriteVMCS( 0x00000C06, seg_selector );
// Host FS selector 00000C08H
__asm MOV seg_selector, FS
Log( "Setting Host FS Selector" , seg_selector );
WriteVMCS( 0x00000C08, seg_selector );
// Host GS selector 00000C0AH
__asm MOV seg_selector, GS
seg_selector &= 0xFFFC;
Log( "Setting Host GS Selector" , seg_selector );
WriteVMCS( 0x00000C0A, seg_selector );
// Host TR selector 00000C0CH
__asm STR seg_selector
Log( "Setting Host TR Selector" , seg_selector );
WriteVMCS( 0x00000C0C, seg_selector );
// ***************************************
// * *
// * H.2.2 64-Bit Guest-State Fields *
// * *
// ***************************************
//
// VMCS Link Pointer (full) 00002800H
temp32 = 0xFFFFFFFF;
Log( "Setting VMCS Link Pointer (full)" , temp32 );
WriteVMCS( 0x00002800, temp32 );
// VMCS link pointer (high) 00002801H
temp32 = 0xFFFFFFFF;
Log( "Setting VMCS Link Pointer (high)" , temp32 );
WriteVMCS( 0x00002801, temp32 );
// Reserved Bits of IA32_DEBUGCTL MSR must be 0
// (1D9H)
ReadMSR( 0x000001D9 );
Log( "IA32_DEBUGCTL MSR" , msr.Lo );
// Guest IA32_DEBUGCTL (full) 00002802H
temp32 = msr.Lo;
Log( "Setting Guest IA32_DEBUGCTL (full)" , temp32 );
WriteVMCS( 0x00002802, temp32 );
// Guest IA32_DEBUGCTL (high) 00002803H
temp32 = msr.Hi;
Log( "Setting Guest IA32_DEBUGCTL (high)" , temp32 );
WriteVMCS( 0x00002803, temp32 );
// ***********************************
// * *
// * H.3.1 32-Bit Control Fields *
// * *
// ***********************************
//
// Pin-based VM-execution controls 00004000H
// IA32_VMX_PINBASED_CTLS MSR (index 481H)
ReadMSR( 0x481 );
Log( "Pin-based allowed-0" , msr.Lo );
Log( "Pin-based allowed-1" , msr.Hi );
temp32 = 0;
temp32 |= msr.Lo;
temp32 &= msr.Hi;
Log( "Setting Pin-Based Controls Mask" , temp32 );
WriteVMCS( 0x00004000, temp32 );
// Primary processor-based VM-execution controls 00004002H
// IA32_VMX_PROCBASED_CTLS MSR (index 482H)
ReadMSR( 0x482 );
Log( "Proc-based allowed-0" , msr.Lo );
Log( "Proc-based allowed-1" , msr.Hi );
temp32 = 0;
temp32 |= msr.Lo;
temp32 &= msr.Hi;
Log( "Setting Pri Proc-Based Controls Mask" , temp32 );
WriteVMCS( CPU_BASED_VM_EXEC_CONTROL, temp32 ); //4002
//异常位设置
//Exception bitmap 00004004H
temp32 = 0x00000000;
//SetBit( &temp32, 14 ); // Page Fault
//SetBit( &temp32, 3 ); // Software Interrupt (INT 3)
//SetBit( &temp32, 7 ); // No Math Co-Processor
//SetBit( &temp32, 8 ); // Doudle Fault
WriteVMCS( EXCEPTION_BITMAP, temp32 ); //0x00004004
// Page-fault error-code mask 00004006H
Log( "Page-Fault Error-Code Mask" , 0 );
WriteVMCS( PAGE_FAULT_ERROR_CODE_MASK, 0 );
// Page-fault error-code match 00004008H
Log( "Page-Fault Error-Code Match" , 0 );
WriteVMCS( PAGE_FAULT_ERROR_CODE_MATCH, 0 );
// Get the CR3-target count, MSR store/load counts, et cetera
//
// IA32_VMX_MISC MSR (index 485H)
ReadMSR( 0x485 );
//Log( "Misc Data" , msr.Lo );
//Log( "Misc Data" , msr.Hi );
RtlCopyBytes( &misc_data, &msr.Lo, 4 );
// Log( " ActivityStates" , misc_data.ActivityStates );
// Log( " CR3Targets" , misc_data.CR3Targets );
// Log( " MaxMSRs" , misc_data.MaxMSRs );
// VM-exit controls 0000400CH
// IA32_VMX_EXIT_CTLS MSR (index 483H)
ReadMSR( 0x483 );
Log( "Exit controls allowed-0" , msr.Lo );
Log( "Exit controls allowed-1" , msr.Hi );
temp32 = 0;
temp32 |= msr.Lo;
temp32 &= msr.Hi;
SetBit( &temp32, 15 ); // Acknowledge Interrupt On Exit
Log( "Setting VM-Exit Controls Mask" , temp32 );
WriteVMCS( VM_EXIT_CONTROLS, temp32 );
// VM-entry controls 00004012H
// IA32_VMX_ENTRY_CTLS MSR (index 484H)
ReadMSR( 0x484 );
Log( "VMX Entry allowed-0" , msr.Lo );
Log( "VMX Entry allowed-1" , msr.Hi );
temp32 = 0;
temp32 |= msr.Lo;
temp32 &= msr.Hi;
ClearBit( &temp32 , 9 ); // IA-32e Mode Guest Disable
Log( "Setting VM-Entry Controls Mask" , temp32 );
WriteVMCS( 0x00004012, temp32 );
// ***************************************
// * *
// * H.3.3 32-Bit Guest-State Fields *
// * *
// ***************************************
//
// Guest ES limit 00004800H
__asm MOV seg_selector, ES
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest ES limit" , 0xFFFFFFFF );
WriteVMCS( 0x00004800, 0xFFFFFFFF );
// Guest CS limit 00004802H
__asm MOV seg_selector, CS
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest CS limit" , 0xFFFFFFFF );
WriteVMCS( 0x00004802, 0xFFFFFFFF );
// Guest SS limit 00004804H
__asm MOV seg_selector, SS
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest SS limit" , 0xFFFFFFFF );
WriteVMCS( 0x00004804, 0xFFFFFFFF );
// Guest DS limit 00004806H
__asm MOV seg_selector, DS
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest DS limit" , 0xFFFFFFFF );
WriteVMCS( 0x00004806, 0xFFFFFFFF );
// Guest FS limit 00004808H
__asm MOV seg_selector, FS
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest FS limit" , 0x00001000 );
WriteVMCS( 0x00004808, 0x00001000 );
// Guest GS limit 0000480AH
__asm MOV seg_selector, GS
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, seg_selector );
Log( "Setting Guest GS limit" , 0xFFFFFFFF );
WriteVMCS( 0x0000480A, 0xFFFFFFFF );
// Guest TR limit 0000480EH
__asm
{
PUSH EAX
STR AX
MOV mLDT, AX
POP EAX
}
temp32 = 0;
temp32 = GetSegmentDescriptorLimit( gdt_base, mLDT );
Log( "Setting Guest TR limit" , temp32 );
WriteVMCS( 0x0000480E, temp32 );
// Guest GDTR limit 00004810H
Log( "Setting Guest GDTR limit" , gdt_reg.Limit );
WriteVMCS( 0x00004810, gdt_reg.Limit );
// Guest IDTR limit 00004812H
Log( "Setting Guest IDTR limit" , idt_reg.Limit );
WriteVMCS( GUEST_IDTR_LIMIT, idt_reg.Limit ); //0X4812
__asm MOV seg_selector, CS
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // CS Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
Log( "Setting Guest CS access rights" , temp32 );
WriteVMCS( 0x00004816, temp32 );
__asm MOV seg_selector, DS
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // DS Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
Log( "Setting Guest DS access rights" , temp32 );
WriteVMCS( 0x0000481A, temp32 );
__asm MOV seg_selector, ES
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // ES Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
Log( "Setting Guest ES access rights" , temp32 );
WriteVMCS( 0x00004814, temp32 );
__asm MOV seg_selector, FS
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // FS Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
temp32 &= 0xFFFF7FFF; // Granularity Bit = 0
Log( "Setting Guest FS access rights" , temp32 );
WriteVMCS( 0x0000481C, temp32 );
__asm MOV seg_selector, GS
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // GS Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
SetBit( &temp32, 16 ); // Unusable
Log( "Setting Guest GS access rights" , temp32 );
WriteVMCS( 0x0000481E, temp32 );
__asm MOV seg_selector, SS
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // SS Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
Log( "Setting Guest SS access rights" , temp32 );
WriteVMCS( 0x00004818, temp32 );
__asm STR seg_selector
temp32 = seg_selector;
temp32 >>= 3;
temp32 *= 8;
temp32 = (gdt_base 5); // TR Segment Descriptor
__asm
{
PUSHAD
MOV EAX, temp32
MOV EBX, [EAX]
MOV temp32, EBX
POPAD
}
temp32 &= 0x0000F0FF;
Log( "Setting Guest TR access rights" , temp32 );
WriteVMCS( 0x00004822, temp32 );
// Guest LDTR access rights 00004820H
temp32 = 0;
SetBit( &temp32, 16 ); // Unusable
Log( "Setting Guest LDTR access rights" , temp32 );
WriteVMCS( 0x00004820, temp32 );
// Guest IA32_SYSENTER_CS 0000482AH
// (174H)
ReadMSR( 0x174 );
Log( "Setting Guest IA32_SYSENTER_CS" , (ULONG)msr.Lo );
WriteVMCS( 0x0000482A, msr.Lo );
// **************************************
// * *
// * H.3.4 32-Bit Host-State Fields *
// * *
// **************************************
//
// Host IA32_SYSENTER_CS 00004C00H
// (174H)
ReadMSR( 0x174 );
Log( "Setting Host IA32_SYSENTER_CS" , (ULONG)msr.Lo );
WriteVMCS( 0x00004C00, msr.Lo );
// **********************************************
// * *
// * H.4.3 Natural-Width Guest-State Fields *
// * *
// **********************************************
//
// Guest CR0 00006800H
__asm
{
PUSH EAX
MOV EAX, CR0
MOV temp32, EAX
POP EAX
}
ReadMSR( 0x486 ); // IA32_VMX_CR0_FIXED0
Log( "IA32_VMX_CR0_FIXED0" , msr.Lo );
ReadMSR( 0x487 ); // IA32_VMX_CR0_FIXED1
Log( "IA32_VMX_CR0_FIXED1" , msr.Lo );
SetBit( &temp32, 0 ); // PE
SetBit( &temp32, 5 ); // NE
SetBit( &temp32, 31 ); // PG
Log( "Setting Guest CR0" , temp32 );
WriteVMCS( 0x00006800, temp32 );
// Guest CR3 00006802H
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR3
_emit 0x20
_emit 0xD8
MOV temp32, EAX
POP EAX
}
Log( "Setting Guest CR3" , temp32 );
WriteVMCS( GUEST_CR3, temp32 );
// Guest CR4 00006804H
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR4
_emit 0x20
_emit 0xE0
MOV temp32, EAX
POP EAX
}
ReadMSR( 0x488 ); // IA32_VMX_CR4_FIXED0
Log( "IA32_VMX_CR4_FIXED0" , msr.Lo );
ReadMSR( 0x489 ); // IA32_VMX_CR4_FIXED1
Log( "IA32_VMX_CR4_FIXED1" , msr.Lo );
SetBit( &temp32, 13 ); // VMXE
Log( "Setting Guest CR4" , temp32 );
WriteVMCS( 0x00006804, temp32 );
// Guest ES base 00006806H
__asm MOV seg_selector, ES
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Guest ES Base" , temp32 );
WriteVMCS( 0x00006806, temp32 );
// Guest CS base 00006808H
__asm MOV seg_selector, CS
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Guest CS Base" , temp32 );
WriteVMCS( 0x00006808, temp32 );
// Guest SS base 0000680AH
__asm MOV seg_selector, SS
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Guest SS Base" , temp32 );
WriteVMCS( 0x0000680A, temp32 );
// Guest DS base 0000680CH
__asm MOV seg_selector, DS
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Guest DS Base" , temp32 );
WriteVMCS( 0x0000680C, temp32 );
// Guest FS base 0000680EH
__asm MOV seg_selector, FS
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Guest FS Base" , temp32 );
WriteVMCS( 0x0000680E, temp32 );
// Guest TR base 00006814H
__asm
{
PUSH EAX
STR AX
MOV mLDT, AX
POP EAX
}
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , mLDT );
Log( "Setting Guest TR Base" , temp32 );
WriteVMCS( 0x00006814, temp32 );
// Guest GDTR base 00006816H
__asm
{
SGDT gdt_reg
}
temp32 = 0;
temp32 = gdt_reg.BaseHi;
temp32 <<= 16;
temp32 |= gdt_reg.BaseLo;
Log( "Setting Guest GDTR Base" , temp32 );
WriteVMCS( GUEST_GDTR_BASE, temp32 );
// Guest IDTR base 00006818H
__asm
{
SIDT idt_reg
}
temp32 = 0;
temp32 = idt_reg.BaseHi;
temp32 <<= 16;
temp32 |= idt_reg.BaseLo;
Log( "Setting Guest IDTR Base" , temp32 );
WriteVMCS( GUEST_IDTR_BASE, temp32 );
// Guest RFLAGS 00006820H
__asm
{
PUSHAD
PUSHFD
MOV EAX, 0x00006820
// VMWRITE EAX, [ESP]
_emit 0x0F
_emit 0x79
_emit 0x04
_emit 0x24
POP eFlags
POPAD
}
Log( "Guest EFLAGS" , eFlags );
// Guest IA32_SYSENTER_ESP 00006824H
// MSR (175H)
ReadMSR( 0x175 );
Log( "Setting Guest IA32_SYSENTER_ESP" , msr.Lo );
WriteVMCS( GUEST_SYSENTER_ESP, msr.Lo );
// Guest IA32_SYSENTER_EIP 00006826H
// MSR (176H)
ReadMSR( 0x176 );
Log( "Setting Guest IA32_SYSENTER_EIP" , msr.Lo );
WriteVMCS( GUEST_SYSENTER_EIP, msr.Lo ); //0x00006826
// *********************************************
// * *
// * H.4.4 Natural-Width Host-State Fields *
// * *
// *********************************************
//
// Host CR0 00006C00H
__asm
{
PUSH EAX
MOV EAX, CR0
MOV temp32, EAX
POP EAX
}
SetBit( &temp32, 5 ); // Set NE Bit
Log( "Setting Host CR0" , temp32 );
WriteVMCS( 0x00006C00, temp32 );
// Host CR3 00006C02H
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR3
_emit 0x20
_emit 0xD8
MOV temp32, EAX
POP EAX
}
Log( "Setting Host CR3" , temp32 );
WriteVMCS( 0x00006C02, temp32 );
// Host CR4 00006C04H
__asm
{
PUSH EAX
_emit 0x0F // MOV EAX, CR4
_emit 0x20
_emit 0xE0
MOV temp32, EAX
POP EAX
}
Log( "Setting Host CR4" , temp32 );
WriteVMCS( 0x00006C04, temp32 );
// Host FS base 00006C06H
__asm MOV seg_selector, FS
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , seg_selector );
Log( "Setting Host FS Base" , temp32 );
WriteVMCS( 0x00006C06, temp32 );
// Host TR base 00006C0AH
__asm
{
PUSH EAX
STR AX
MOV mLDT, AX
POP EAX
}
temp32 = 0;
temp32 = GetSegmentDescriptorBase( gdt_base , mLDT );
Log( "Setting Host TR Base" , temp32 );
WriteVMCS( 0x00006C0A, temp32 );
// Host GDTR base 00006C0CH
__asm
{
SGDT gdt_reg
}
temp32 = 0;
temp32 = gdt_reg.BaseHi;
temp32 <<= 16;
temp32 |= gdt_reg.BaseLo;
Log( "Setting Host GDTR Base" , temp32 );
WriteVMCS( HOST_GDTR_BASE, temp32 );
// Host IDTR base 00006C0EH
__asm
{
SIDT idt_reg
}
temp32 = 0;
temp32 = idt_reg.BaseHi;
temp32 <<= 16;
temp32 |= idt_reg.BaseLo;
Log( "Setting Host IDTR Base" , temp32 );
WriteVMCS( HOST_IDTR_BASE, temp32 );
// Host IA32_SYSENTER_ESP 00006C10H
// MSR (175H)
ReadMSR( 0x175 );
Log( "Setting Host IA32_SYSENTER_ESP" , msr.Lo );
WriteVMCS( 0x00006C10, msr.Lo );
// Host IA32_SYSENTER_EIP 00006C12H
// MSR (176H)
ReadMSR( 0x176 );
Log( "Setting Host IA32_SYSENTER_EIP" , msr.Lo );
WriteVMCS( 0x00006C12, msr.Lo );
// (5) Issue a sequence of VMWRITEs to initialize various host-state area
// fields in the working VMCS. The initialization sets up the context
// and entry-points to the VMM VIRTUAL-MACHINE MONITOR PROGRAMMING
// CONSIDERATIONS upon subsequent VM exits from the guest. Host-state
// fields include control registers (CR0, CR3 and CR4), selector fields
// for the segment registers (CS, SS, DS, ES, FS, GS and TR), and base-
// address fields (for FS, GS, TR, GDTR and IDTR; RSP, RIP and the MSRs
// that control fast system calls).
//
// (6) Use VMWRITEs to set up the various VM-exit control fields, VM-entry
// control fields, and VM-execution control fields in the VMCS. Care
// should be taken to make sure the settings of individual fields match
// the allowed 0 and 1 settings for the respective controls as reported
// by the VMX capability MSRs (see Appendix G). Any settings inconsistent
// with the settings reported by the capability MSRs will cause VM
// entries to fail.
// (7) Use VMWRITE to initialize various guest-state area fields in the
// working VMCS. This sets up the context and entry-point for guest
// execution upon VM entry. Chapter 22 describes the guest-state loading
// and checking done by the processor for VM entries to protected and
// virtual-8086 guest execution.
//
// Clear the VMX Abort Error Code prior to VMLAUNCH
//
RtlZeroMemory( (pVMCSRegion 4), 4 );
Log( "Clearing VMX Abort Error Code" , *(pVMCSRegion 4) );
// Set EIP, ESP for the Guest right before calling VMLAUNCH
// G、Guest的ESP和EIP
Log( "Setting Guest ESP" , GuestStack );
WriteVMCS( 0x0000681C, (ULONG)GuestStack );
Log( "Setting Guest EIP" , GuestReturn );
WriteVMCS( 0x0000681E, (ULONG)GuestReturn );
/*
// Allocate some stack space for the VMEntry and VMMHandler.
//
HighestAcceptableAddress.QuadPart = 0xFFFFFFFF;
FakeStack = MmAllocateContiguousMemory( 0x2000, HighestAcceptableAddress );
Log( "FakeStack" , FakeStack );
*/
// Set EIP, ESP for the Host right before calling VMLAUNCH
//
Log( "Setting Host ESP" , ((ULONG)FakeStack 0x1FFF) );
WriteVMCS( HOST_RSP, ((ULONG)FakeStack 0x1FFF) );//0x00006C14
Log( "Setting Host EIP" , VMMEntryPoint );
// 入口
WriteVMCS( HOST_RIP, (ULONG)VMMEntryPoint ); //6C16
////////////////
// //
// VMLAUNCH //
// //
////////////////
__asm
{
_emit 0x0F
_emit 0x01
_emit 0xC2
}
Log( "成功后不会在这里玩! \n" , 1907 );
__asm
{
PUSHFD
POP eFlags
}
Log( "VMLAUNCH 失败啦 !" , 0xDEADF00D );
/* Get the error number from VMCS */
ErrorCode = VmxRead(VM_INSTRUCTION_ERROR);
Log("VM Instruction Error", ErrorCode);
Abort:
ScrubTheLaunch = 1;
__asm
{
MOV ESP, GuestStack
JMP GuestReturn
}
}
//////////////////////////////////////////////////////////////////////////
ULONG ExitReason;
ULONG ExitQualification;
ULONG ExitInterruptionInformation;
ULONG ExitInterruptionErrorCode;
ULONG IDTVectoringInformationField;
ULONG IDTVectoringErrorCode;
ULONG ExitInstructionLength;
ULONG ExitInstructionInformation;
ULONG GuestEIP;
ULONG GuestResumeEIP;
ULONG GuestESP;
ULONG GuestCR3;
ULONG GuestEAX;
ULONG GuestEBX;
ULONG GuestECX;
ULONG GuestEDX;
ULONG GuestEDI;
ULONG GuestESI;
ULONG GuestEBP;
ULONG movcrControlRegister;
ULONG movcrAccessType;
ULONG movcrOperandType;
ULONG movcrGeneralPurposeRegister;
ULONG movcrLMSWSourceData;
////////////////虚拟机处理系统 ///////
__declspec( naked ) VOID VMMEntryPoint( )
{
//如果不关中断,则有可能在执行了mov ss之后,mov sp之前发生中断,会破坏此时ss:sp指向的数据。
__asm
{
CLI //屏蔽中断
PUSHAD
// 保存通用寄存器
MOV GuestEAX, EAX
MOV GuestEBX, EBX
MOV GuestECX, ECX
MOV GuestEDX, EDX
MOV GuestEDI, EDI
MOV GuestESI, ESI
MOV GuestEBP, EBP
}
VMMReadGuestState();
//////////////////////////////////////////////////////////////////////////
if (0 == ExitReason )
{
int IntrNo = ExitInterruptionInformation & 0xFF;
if ( 3 == IntrNo )
{
}
}//end if 0 reason
//////////////////////////////////////////////////////////////////////////
// Writing the Guest VMCS EIP uses general registers.
// Must complete this before setting general registers
// for guest return state.
//
GuestResumeEIP = GuestEIP ExitInstructionLength;
WriteVMCS(GUEST_RIP,(ULONG)GuestResumeEIP ); //0x0000681E
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////
// //
// *** EXIT REASON CHECKS START HERE *** //
// //
/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// //
// VMCLEAR, VMLAUNCH, VMPTRLD, VMPTRST, VMREAD, VMWRITE, VMRESUME, VMXOFF, VMXON //
// //
/////////////////////////////////////////////////////////////////////////////////////
if( ExitReason > 0x00000012 && ExitReason < 0x0000001C )
{
Log( "Request has been denied - CPU0", ExitReason );
__asm
{
POPAD
JMP Resume
}
}
//处理 CPUID 指令
if( ExitReason == VMX_EXIT_CPUID )
{
if( GuestEAX == 0 )
{
DbgPrint("CPUID EIP == %08X \n" , GuestEIP );
//ShowGuestState();
//0x34EC2B
__asm
{
POPAD
MOV EAX, 0
CPUID
//修改返回值
MOV EBX, 0x80808080
MOV ECX, 0x90909090
MOV EDX, 0x10101010
JMP Resume
}
}
else
{
__asm
{
POPAD
MOV EAX, GuestEAX
CPUID
JMP Resume
}
}
}//end if VMX_EXIT_CPUID
if( ExitReason == VMX_EXIT_VMCALL ) //VMCALL //0X12
{
Log( "VMCALL detected - CPU0" , 0 );
if( GuestEAX == 0x12345678 )
{
// Switch off VMX mode.
//
Log( "- Terminating VMX Mode.", 0xDEADDEAD );
__asm
{
_emit 0x0F // VMXOFF
_emit 0x01
_emit 0xC4
}
Log( "- Flow Control Return to Address" , GuestResumeEIP );
__asm
{
POPAD
MOV ESP, GuestESP
STI
JMP GuestResumeEIP
}
}
Log( "- Request has been denied." , ExitReason );
__asm
{
POPAD
JMP Resume
}
}
if( ExitReason == VMX_EXIT_INVD ) //0XD
{
Log( "INVD detected - CPU0" , 0 );
__asm
{
_emit 0x0F
_emit 0x08
POPAD
JMP Resume
}
}
if( ExitReason == VMX_EXIT_RDMSR ) //0X1F
{
__asm
{
POPAD
MOV ECX, GuestECX
_emit 0x0F
_emit 0x32
JMP Resume
}
}
if( ExitReason == VMX_EXIT_WRMSR ) //0x20
{
__asm
{
POPAD
MOV ECX, GuestECX
MOV EAX, GuestEAX
MOV EDX, GuestEDX
_emit 0x0F
_emit 0x30
JMP Resume
}
}
///////////////////////////////
// //
// Control Register Access //
// //
///////////////////////////////
if( ExitReason == VMX_EXIT_CRX_MOVE ) //0x1c
{
if( HandlerLogging ) Log( "Control Register Access detected.", 0 );
movcrControlRegister = ( ExitQualification & 0x0000000F );
movcrAccessType = ( ( ExitQualification & 0x00000030 ) >> 4 );
movcrOperandType = ( ( ExitQualification & 0x00000040 ) >> 6 );
movcrGeneralPurposeRegister = ( ( ExitQualification & 0x00000F00 ) >> 8 );
if( HandlerLogging )
{
Log( "- movcrControlRegister", movcrControlRegister );
Log( "- movcrAccessType", movcrAccessType );
Log( "- movcrOperandType", movcrOperandType );
Log( "- movcrGeneralPurposeRegister", movcrGeneralPurposeRegister );
}
// Control Register Access (CR3 <-- reg32)
//
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 0 )
{
WriteVMCS( GUEST_CR3, GuestEAX );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 1 )
{
WriteVMCS( GUEST_CR3, GuestECX );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 2 )
{
WriteVMCS( GUEST_CR3, GuestEDX );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 3 )
{
WriteVMCS( GUEST_CR3, GuestEBX );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 4 )
{
WriteVMCS( GUEST_CR3, GuestESP );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 5 )
{
WriteVMCS( GUEST_CR3, GuestEBP );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 6 )
{
WriteVMCS( GUEST_CR3, GuestESI );
__asm POPAD
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 7 )
{
WriteVMCS( GUEST_CR3, GuestEDI );
__asm POPAD
goto Resume;
}
// Control Register Access (reg32 <-- CR3)
//
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 0 )
{
__asm POPAD
__asm MOV EAX, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 1 )
{
__asm POPAD
__asm MOV ECX, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 2 )
{
__asm POPAD
__asm MOV EDX, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 3 )
{
__asm POPAD
__asm MOV EBX, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 4 )
{
__asm POPAD
__asm MOV ESP, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 5 )
{
__asm POPAD
__asm MOV EBP, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 6 )
{
__asm POPAD
__asm MOV ESI, GuestCR3
goto Resume;
}
if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 7 )
{
__asm POPAD
__asm MOV EDI, GuestCR3
goto Resume;
}
}//end VMX_EXIT_CRX_MOVE
Exit:
__asm
{
_emit 0x0F // VMXOFF
_emit 0x01
_emit 0xC4
}
VMXIsActive = 0;
Log( "Flow Control Return to Address" , GuestEIP );
__asm
{
POPAD
MOV ESP, GuestESP
STI
JMP GuestEIP
}
Resume:
//恢复
// Need to execute the VMRESUME without having changed
// the state of the GPR and ESP et cetera.
__asm
{
STI
_emit 0x0F // VMRESUME
_emit 0x01
_emit 0xC3
}
}
VOID VMMReadGuestState( )
{
HandlerLogging = 0;
ExitReason = VmxRead(VM_EXIT_REASON); //0x4402
ExitInterruptionInformation = VmxRead( VM_EXIT_INTR_INFO); //0x4404
ExitInstructionLength = VmxRead(VM_EXIT_INSTRUCTION_LEN); //0x440c
ExitQualification = VmxRead(EXIT_QUALIFICATION) ; //0x6400
ExitInterruptionInformation = VmxRead(VM_EXIT_INTR_INFO); //0x4404
ExitInterruptionErrorCode = VmxRead(VM_EXIT_INTR_ERROR_CODE); //0x4406
IDTVectoringInformationField = VmxRead(IDT_VECTORING_INFO); //0X00004408 // IDT-Vectoring Information Field
IDTVectoringErrorCode = VmxRead(IDT_VECTORING_ERROR_CODE); //0X0000440A // IDT-Vectoring Error Code
ExitInstructionLength = VmxRead(VM_EXIT_INSTRUCTION_LEN); //0x0000440C // VM-Exit Instruction Length
ExitInstructionInformation = VmxRead(VMX_INSTRUCTION_INFO) ; //0x0000440E //VM-Exit Instruction Information
GuestEIP = VmxRead(GUEST_RIP); //0x0000681E; //GuestEIP
GuestESP = VmxRead(GUEST_RSP); //0x0000681c //esp
GuestCR3 = VmxRead(GUEST_CR3); //0X6802 GuestCR3
}
void ShowGuestState()
{
Log( "----- VMM Guest -----", 0 );
Log( "Guest EAX" , GuestEAX );
Log( "Guest EBX" , GuestEBX );
Log( "Guest ECX" , GuestECX );
Log( "Guest EDX" , GuestEDX );
Log( "Guest EDI" , GuestEDI );
Log( "Guest ESI" , GuestESI );
Log( "Guest EBP" , GuestEBP );
Log( "Exit Reason" , ExitReason );
Log( "Exit Qualification" , ExitQualification );
Log( "Exit Interruption Information" , ExitInterruptionInformation );
Log( "Exit Interruption Error Code" , ExitInterruptionErrorCode );
Log( "IDT-Vectoring Information Field" , IDTVectoringInformationField );
Log( "IDT-Vectoring Error Code" , IDTVectoringErrorCode );
Log( "VM Exit CR3" , GuestCR3 );
Log( "VM Exit EIP" , GuestEIP );
Log( "VM Exit ESP" , GuestESP );
Log( "VM-Exit Instruction Information" , ExitInstructionInformation );
Log( "VM-Exit Instruction Length" , ExitInstructionLength );
}