├── newbp.c ├── common.h ├── test ├── cpuid.exe └── cpuid.c ├── new-blue-pill.zip ├── amd64 ├── common-asm.asm ├── regs.asm └── vmx-asm.asm ├── sources ├── makefile ├── regs.h ├── hvm.h ├── common.c ├── vmx.h ├── hvm.c ├── vmcs.h ├── vmxdebug.c └── vmx.c /newbp.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeDf/nbp-0.32-plus/HEAD/newbp.c -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeDf/nbp-0.32-plus/HEAD/common.h -------------------------------------------------------------------------------- /test/cpuid.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeDf/nbp-0.32-plus/HEAD/test/cpuid.exe -------------------------------------------------------------------------------- /new-blue-pill.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeDf/nbp-0.32-plus/HEAD/new-blue-pill.zip -------------------------------------------------------------------------------- /amd64/common-asm.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeDf/nbp-0.32-plus/HEAD/amd64/common-asm.asm -------------------------------------------------------------------------------- /sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=newbp 2 | TARGETPATH=. 3 | TARGETTYPE=DRIVER 4 | 5 | SOURCES=\ 6 | newbp.c \ 7 | hvm.c \ 8 | common.c \ 9 | vmx.c \ 10 | vmxdebug.c 11 | 12 | AMD64_SOURCES=\ 13 | vmx-asm.asm \ 14 | common-asm.asm \ 15 | regs.asm -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the components of NT OS/2 5 | # 6 | ! INCLUDE $(NTMAKEENV)\makefile.def 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/cpuid.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | unsigned long ddeax,ddebx,ddecx,ddedx; 6 | 7 | _asm 8 | { 9 | mov eax, 0xbabecafe 10 | cpuid 11 | mov ddeax, eax 12 | mov ddebx, ebx 13 | mov ddecx, ecx 14 | mov ddedx, edx 15 | } 16 | 17 | printf("---- cpuid ----\n"); 18 | 19 | printf("eax == %08X \n" ,ddeax); 20 | printf("ebx == %08X \n" ,ddebx); 21 | printf("ecx == %08X \n" ,ddecx); 22 | printf("edx == %08X \n" ,ddedx); 23 | getchar(); 24 | return 0; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #pragma once 6 | #include 7 | 8 | USHORT RegGetCs (); 9 | USHORT RegGetDs (); 10 | USHORT RegGetEs (); 11 | USHORT RegGetSs (); 12 | USHORT RegGetFs (); 13 | USHORT RegGetGs (); 14 | 15 | ULONG64 RegGetRflags (); 16 | ULONG64 RegGetRsp (); 17 | 18 | ULONG64 GetIdtBase (); 19 | USHORT GetIdtLimit (); 20 | ULONG64 GetGdtBase (); 21 | USHORT GetGdtLimit (); 22 | 23 | USHORT GetTrSelector (); 24 | USHORT GetLdtr (); 25 | 26 | ULONG64 RegGetDr0 (); 27 | ULONG64 RegGetDr1 (); 28 | ULONG64 RegGetDr2 (); 29 | ULONG64 RegGetDr3 (); 30 | // 31 | ULONG64 RegSetDr0 (); 32 | ULONG64 RegSetDr1 (); 33 | ULONG64 RegSetDr2 (); 34 | ULONG64 RegSetDr3 (); -------------------------------------------------------------------------------- /hvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "common.h" 9 | #include "vmx.h" 10 | #include "regs.h" 11 | 12 | // ntamd64_x.h 13 | #define KGDT64_NULL (0 * 16) // NULL descriptor 14 | #define KGDT64_R0_CODE (1 * 16) // kernel mode 64-bit code 15 | #define KGDT64_R0_DATA (1 * 16) + 8 // kernel mode 64-bit data (stack) 16 | #define KGDT64_R3_CMCODE (2 * 16) // user mode 32-bit code 17 | #define KGDT64_R3_DATA (2 * 16) + 8 // user mode 32-bit data 18 | #define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code 19 | #define KGDT64_SYS_TSS (4 * 16) // kernel mode system task state 20 | #define KGDT64_R3_CMTEB (5 * 16) // user mode 32-bit TEB 21 | #define KGDT64_R0_CMCODE (6 * 16) // kernel mode 32-bit code 22 | 23 | // this must be synchronized with CmSetBluepillSelectors() (common-asm.asm) 24 | #define BP_GDT64_CODE KGDT64_R0_CODE // cs 25 | #define BP_GDT64_DATA KGDT64_R0_DATA // ds, es, ss 26 | #define BP_GDT64_SYS_TSS KGDT64_SYS_TSS // tr 27 | #define BP_GDT64_PCR KGDT64_R0_DATA // gs 28 | 29 | NTSTATUS HvmSwallowBluepill (); 30 | 31 | NTSTATUS HvmSpitOutBluepill (); 32 | -------------------------------------------------------------------------------- /amd64/regs.asm: -------------------------------------------------------------------------------- 1 | 2 | .CODE 3 | 4 | RegGetCs PROC 5 | mov rax, cs 6 | ret 7 | RegGetCs ENDP 8 | 9 | RegGetDs PROC 10 | mov rax, ds 11 | ret 12 | RegGetDs ENDP 13 | 14 | RegGetEs PROC 15 | mov rax, es 16 | ret 17 | RegGetEs ENDP 18 | 19 | RegGetSs PROC 20 | mov rax, ss 21 | ret 22 | RegGetSs ENDP 23 | 24 | RegGetFs PROC 25 | mov rax, fs 26 | ret 27 | RegGetFs ENDP 28 | 29 | RegGetGs PROC 30 | mov rax, gs 31 | ret 32 | RegGetGs ENDP 33 | 34 | 35 | RegGetDr0 PROC 36 | mov rax, dr0 37 | ret 38 | RegGetDr0 ENDP 39 | 40 | RegGetDr1 PROC 41 | mov rax, dr1 42 | ret 43 | RegGetDr1 ENDP 44 | 45 | RegGetDr2 PROC 46 | mov rax, dr2 47 | ret 48 | RegGetDr2 ENDP 49 | 50 | RegGetDr3 PROC 51 | mov rax, dr3 52 | ret 53 | RegGetDr3 ENDP 54 | 55 | RegSetDr0 PROC 56 | mov dr0, rcx 57 | ret 58 | RegSetDr0 ENDP 59 | 60 | RegSetDr1 PROC 61 | mov dr1, rcx 62 | ret 63 | RegSetDr1 ENDP 64 | 65 | RegSetDr2 PROC 66 | mov dr2, rcx 67 | ret 68 | RegSetDr2 ENDP 69 | 70 | RegSetDr3 PROC 71 | mov dr3, rcx 72 | ret 73 | RegSetDr3 ENDP 74 | 75 | 76 | RegGetRflags PROC 77 | pushfq 78 | pop rax 79 | ret 80 | RegGetRflags ENDP 81 | 82 | RegGetRsp PROC 83 | mov rax, rsp 84 | add rax, 8 85 | ret 86 | RegGetRsp ENDP 87 | 88 | GetIdtBase PROC 89 | LOCAL idtr[10]:BYTE 90 | 91 | sidt idtr 92 | mov rax, QWORD PTR idtr[2] 93 | ret 94 | GetIdtBase ENDP 95 | 96 | GetIdtLimit PROC 97 | LOCAL idtr[10]:BYTE 98 | 99 | sidt idtr 100 | mov ax, WORD PTR idtr[0] 101 | ret 102 | GetIdtLimit ENDP 103 | 104 | GetGdtBase PROC 105 | LOCAL gdtr[10]:BYTE 106 | 107 | sgdt gdtr 108 | mov rax, QWORD PTR gdtr[2] 109 | ret 110 | GetGdtBase ENDP 111 | 112 | GetGdtLimit PROC 113 | LOCAL gdtr[10]:BYTE 114 | 115 | sgdt gdtr 116 | mov ax, WORD PTR gdtr[0] 117 | ret 118 | GetGdtLimit ENDP 119 | 120 | 121 | GetLdtr PROC 122 | sldt rax 123 | ret 124 | GetLdtr ENDP 125 | 126 | GetTrSelector PROC 127 | str rax 128 | ret 129 | GetTrSelector ENDP 130 | 131 | 132 | END 133 | -------------------------------------------------------------------------------- /amd64/vmx-asm.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright holder: Invisible Things Lab 3 | ; 4 | 5 | EXTERN VmExitHandler:PROC 6 | 7 | HVM_SAVE_ALL_NOSEGREGS MACRO 8 | push r15 9 | push r14 10 | push r13 11 | push r12 12 | push r11 13 | push r10 14 | push r9 15 | push r8 16 | push rdi 17 | push rsi 18 | push rbp 19 | push rbp ; rsp 20 | push rbx 21 | push rdx 22 | push rcx 23 | push rax 24 | ENDM 25 | 26 | HVM_RESTORE_ALL_NOSEGREGS MACRO 27 | pop rax 28 | pop rcx 29 | pop rdx 30 | pop rbx 31 | pop rbp ; rsp 32 | pop rbp 33 | pop rsi 34 | pop rdi 35 | pop r8 36 | pop r9 37 | pop r10 38 | pop r11 39 | pop r12 40 | pop r13 41 | pop r14 42 | pop r15 43 | ENDM 44 | 45 | .CODE 46 | 47 | set_in_cr4 PROC 48 | mov rax,cr4 49 | or rcx,rax 50 | mov cr4,rcx 51 | ret 52 | set_in_cr4 ENDP 53 | 54 | clear_in_cr4 PROC 55 | mov rax,cr4 56 | not rcx 57 | and rcx,rax 58 | mov cr4,rcx 59 | ret 60 | clear_in_cr4 ENDP 61 | 62 | 63 | VmxRead PROC 64 | vmread rax, rcx 65 | ret 66 | VmxRead ENDP 67 | 68 | VmxVmCall PROC 69 | vmcall 70 | ret 71 | VmxVmCall ENDP 72 | 73 | 74 | ; Stack layout for vmxLaunch() call: 75 | ; 76 | ; ^ ^ 77 | ; | | 78 | ; | lots of pages for host stack | 79 | ; | | 80 | ; |------------------------------| <- HostStackBottom(rcx) points here 81 | ; | struct CPU | 82 | ; -------------------------------- 83 | 84 | ;====== VmxVMexitHandler ====== 85 | 86 | VmxVmexitHandler PROC 87 | 88 | HVM_SAVE_ALL_NOSEGREGS 89 | 90 | mov rcx, rsp ;GuestRegs 91 | 92 | sub rsp, 28h 93 | call VmExitHandler 94 | add rsp, 28h 95 | 96 | HVM_RESTORE_ALL_NOSEGREGS 97 | vmresume 98 | ret 99 | 100 | VmxVmexitHandler ENDP 101 | 102 | END 103 | -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #include "common.h" 6 | #include "hvm.h" 7 | 8 | NTSTATUS CmInitializeSegmentSelector ( 9 | SEGMENT_SELECTOR * SegmentSelector, 10 | USHORT Selector, 11 | PUCHAR GdtBase 12 | ) 13 | { 14 | PSEGMENT_DESCRIPTOR SegDesc; 15 | 16 | if (!SegmentSelector) 17 | return STATUS_INVALID_PARAMETER; 18 | 19 | if (Selector & 0x4) { 20 | KdPrint (("CmInitializeSegmentSelector(): Given selector (0x%X) points to LDT\n", Selector)); 21 | return STATUS_INVALID_PARAMETER; 22 | } 23 | 24 | SegDesc = (PSEGMENT_DESCRIPTOR) ((PUCHAR) GdtBase + (Selector & ~0x7)); 25 | 26 | SegmentSelector->sel = Selector; 27 | SegmentSelector->base = SegDesc->BaseLow | SegDesc->BaseMid << 16 | SegDesc->BaseHigh << 24; 28 | SegmentSelector->limit = SegDesc->LimitLow | SegDesc->LimitHigh << 16; 29 | SegmentSelector->attributes = SegDesc->AttributesLow | SegDesc->AttributesHigh << 8; 30 | 31 | if (!(SegDesc->AttributesLow & LA_STANDARD)) { 32 | ULONG64 tmp; 33 | // this is a TSS or callgate etc, save the base high part 34 | tmp = (*(PULONG64) ((PUCHAR) SegDesc + 8)); 35 | SegmentSelector->base = (SegmentSelector->base & 0xffffffff) | (tmp << 32); 36 | } 37 | 38 | #define IS_GRANULARITY_4KB (1 << 0xB) 39 | 40 | if ( SegmentSelector->attributes & IS_GRANULARITY_4KB ) { 41 | // 4096-bit granularity is enabled for this segment, scale the limit 42 | SegmentSelector->limit = (SegmentSelector->limit << 12) | 0xfff; 43 | } 44 | 45 | return STATUS_SUCCESS; 46 | } 47 | 48 | 49 | NTSTATUS CmGenerateMovReg ( 50 | PUCHAR pCode, 51 | PULONG pGeneratedCodeLength, 52 | ULONG Register, 53 | ULONG64 Value 54 | ) 55 | { 56 | ULONG uCodeLength; 57 | 58 | if (!pCode || !pGeneratedCodeLength) 59 | return STATUS_INVALID_PARAMETER; 60 | 61 | switch (Register & ~REG_MASK) { 62 | case REG_GP: 63 | pCode[0] = 0x48; 64 | pCode[1] = 0xb8 | (UCHAR) (Register & REG_MASK); 65 | memcpy (&pCode[2], &Value, 8); 66 | uCodeLength = 10; 67 | break; 68 | 69 | case REG_GP_ADDITIONAL: 70 | pCode[0] = 0x49; 71 | pCode[1] = 0xb8 | (UCHAR) (Register & REG_MASK); 72 | memcpy (&pCode[2], &Value, 8); 73 | uCodeLength = 10; 74 | break; 75 | 76 | case REG_CONTROL: 77 | uCodeLength = *pGeneratedCodeLength; 78 | CmGenerateMovReg (pCode, pGeneratedCodeLength, REG_RAX, Value); 79 | // calc the size of the "mov rax, value" 80 | uCodeLength = *pGeneratedCodeLength - uCodeLength; 81 | pCode += uCodeLength; 82 | 83 | uCodeLength = 0; 84 | 85 | if (Register == (REG_CR8)) { 86 | // build 0x44 0x0f 0x22 0xc0 87 | pCode[0] = 0x44; 88 | uCodeLength = 1; 89 | pCode++; 90 | Register = 0; 91 | } 92 | // mov crX, rax 93 | 94 | pCode[0] = 0x0f; 95 | pCode[1] = 0x22; 96 | pCode[2] = 0xc0 | (UCHAR) ((Register & REG_MASK) << 3); 97 | 98 | // *pGeneratedCodeLength has already been adjusted to the length of the "mov rax" 99 | uCodeLength += 3; 100 | } 101 | 102 | if (pGeneratedCodeLength) 103 | *pGeneratedCodeLength += uCodeLength; 104 | 105 | return STATUS_SUCCESS; 106 | } 107 | 108 | 109 | NTSTATUS CmGenerateCallReg ( 110 | PUCHAR pCode, 111 | PULONG pGeneratedCodeLength, 112 | ULONG Register 113 | ) 114 | { 115 | ULONG uCodeLength; 116 | 117 | if (!pCode || !pGeneratedCodeLength) 118 | return STATUS_INVALID_PARAMETER; 119 | 120 | switch (Register & ~REG_MASK) { 121 | case REG_GP: 122 | pCode[0] = 0xff; 123 | pCode[1] = 0xd0 | (UCHAR) (Register & REG_MASK); 124 | uCodeLength = 2; 125 | break; 126 | 127 | case REG_GP_ADDITIONAL: 128 | pCode[0] = 0x41; 129 | pCode[1] = 0xff; 130 | pCode[1] = 0xd0 | (UCHAR) (Register & REG_MASK); 131 | uCodeLength = 3; 132 | break; 133 | } 134 | 135 | if (pGeneratedCodeLength) 136 | *pGeneratedCodeLength += uCodeLength; 137 | 138 | return STATUS_SUCCESS; 139 | } 140 | 141 | NTSTATUS CmGeneratePushReg ( 142 | PUCHAR pCode, 143 | PULONG pGeneratedCodeLength, 144 | ULONG Register 145 | ) 146 | { 147 | if (!pCode || !pGeneratedCodeLength) 148 | return STATUS_INVALID_PARAMETER; 149 | 150 | if ((Register & ~REG_MASK) != REG_GP) 151 | return STATUS_NOT_SUPPORTED; 152 | 153 | pCode[0] = 0x50 | (UCHAR) (Register & REG_MASK); 154 | *pGeneratedCodeLength += 1; 155 | 156 | return STATUS_SUCCESS; 157 | } 158 | 159 | 160 | NTSTATUS CmGenerateIretq ( 161 | PUCHAR pCode, 162 | PULONG pGeneratedCodeLength 163 | ) 164 | { 165 | if (!pCode || !pGeneratedCodeLength) 166 | return STATUS_INVALID_PARAMETER; 167 | 168 | pCode[0] = 0x48; 169 | pCode[1] = 0xcf; 170 | *pGeneratedCodeLength += 2; 171 | 172 | return STATUS_SUCCESS; 173 | } 174 | -------------------------------------------------------------------------------- /vmx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "common.h" 9 | #include "vmcs.h" 10 | #include "hvm.h" 11 | 12 | /* 13 | * VMX Exit Reasons 14 | */ 15 | 16 | #define EXIT_REASON_EXCEPTION_NMI 0 17 | #define EXIT_REASON_EXTERNAL_INTERRUPT 1 18 | #define EXIT_REASON_TRIPLE_FAULT 2 19 | #define EXIT_REASON_INIT 3 20 | #define EXIT_REASON_SIPI 4 21 | #define EXIT_REASON_IO_SMI 5 22 | #define EXIT_REASON_OTHER_SMI 6 23 | #define EXIT_REASON_PENDING_INTERRUPT 7 24 | 25 | #define EXIT_REASON_TASK_SWITCH 9 26 | #define EXIT_REASON_CPUID 10 27 | #define EXIT_REASON_HLT 12 28 | #define EXIT_REASON_INVD 13 29 | #define EXIT_REASON_INVLPG 14 30 | #define EXIT_REASON_RDPMC 15 31 | #define EXIT_REASON_RDTSC 16 32 | #define EXIT_REASON_RSM 17 33 | #define EXIT_REASON_VMCALL 18 34 | #define EXIT_REASON_VMCLEAR 19 35 | #define EXIT_REASON_VMLAUNCH 20 36 | #define EXIT_REASON_VMPTRLD 21 37 | #define EXIT_REASON_VMPTRST 22 38 | #define EXIT_REASON_VMREAD 23 39 | #define EXIT_REASON_VMRESUME 24 40 | #define EXIT_REASON_VMWRITE 25 41 | #define EXIT_REASON_VMXOFF 26 42 | #define EXIT_REASON_VMXON 27 43 | #define EXIT_REASON_CR_ACCESS 28 44 | #define EXIT_REASON_DR_ACCESS 29 45 | #define EXIT_REASON_IO_INSTRUCTION 30 46 | #define EXIT_REASON_MSR_READ 31 47 | #define EXIT_REASON_MSR_WRITE 32 48 | 49 | #define EXIT_REASON_INVALID_GUEST_STATE 33 50 | #define EXIT_REASON_MSR_LOADING 34 51 | 52 | #define EXIT_REASON_MWAIT_INSTRUCTION 36 53 | #define EXIT_REASON_MONITOR_INSTRUCTION 39 54 | #define EXIT_REASON_PAUSE_INSTRUCTION 40 55 | 56 | #define EXIT_REASON_MACHINE_CHECK 41 57 | 58 | #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 59 | 60 | #define VMX_MAX_GUEST_VMEXIT EXIT_REASON_TPR_BELOW_THRESHOLD 61 | 62 | enum SEGREGS 63 | { 64 | ES = 0, 65 | CS, 66 | SS, 67 | DS, 68 | FS, 69 | GS, 70 | LDTR, 71 | TR 72 | }; 73 | 74 | /* 75 | * Exit Qualifications for MOV for Control Register Access 76 | */ 77 | #define CONTROL_REG_ACCESS_NUM 0xf /* 3:0, number of control register */ 78 | #define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ 79 | #define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */ 80 | #define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */ 81 | 82 | /* XXX these are really VMX specific */ 83 | #define TYPE_MOV_TO_DR (0 << 4) 84 | #define TYPE_MOV_FROM_DR (1 << 4) 85 | #define TYPE_MOV_TO_CR (0 << 4) 86 | #define TYPE_MOV_FROM_CR (1 << 4) 87 | #define TYPE_CLTS (2 << 4) 88 | #define TYPE_LMSW (3 << 4) 89 | 90 | #define X86_CR0_PG 0x80000000 /* Paging */ 91 | #define X86_CR4_VMXE 0x2000 /* enable VMX */ 92 | 93 | /* 94 | * Intel CPU MSR 95 | */ 96 | #define BTS64(b) (1i64 << b) 97 | #define FEATURE_CONTROL_LOCKED BTS64(0) 98 | #define FEATURE_CONTROL_VMXON_ENABLED BTS64(2) 99 | 100 | /* MSRs & bits used for VMX enabling */ 101 | #define MSR_IA32_FEATURE_CONTROL 0x03a 102 | #define MSR_IA32_VMX_BASIC 0x480 103 | #define MSR_IA32_VMX_PINBASED_CTLS 0x481 104 | #define MSR_IA32_VMX_PROCBASED_CTLS 0x482 105 | #define MSR_IA32_VMX_EXIT_CTLS 0x483 106 | #define MSR_IA32_VMX_ENTRY_CTLS 0x484 107 | 108 | #define MSR_IA32_SYSENTER_CS 0x174 109 | #define MSR_IA32_SYSENTER_ESP 0x175 110 | #define MSR_IA32_SYSENTER_EIP 0x176 111 | #define MSR_IA32_DEBUGCTL 0x1d9 112 | 113 | #define MSR_LSTAR 0xC0000082 114 | 115 | #define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ 116 | #define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ 117 | #define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */ 118 | 119 | VOID set_in_cr4 ( 120 | ULONG32 mask 121 | ); 122 | 123 | VOID clear_in_cr4 ( 124 | ULONG32 mask 125 | ); 126 | 127 | //Implemented in vmx-asm.asm 128 | VOID VmxVmCall ( 129 | ULONG32 HypercallNumber 130 | ); 131 | 132 | ULONG64 VmxRead ( 133 | ULONG64 field 134 | ); 135 | 136 | VOID VmxVmexitHandler (); 137 | 138 | VOID VmxDumpVmcs (); 139 | 140 | BOOLEAN VmxIsImplemented (); 141 | 142 | NTSTATUS VmxSetupVMCS ( 143 | ULONG_PTR VMM_Stack, 144 | PVOID GuestRip, 145 | PVOID GuestRsp 146 | ); 147 | 148 | NTSTATUS VmxShutdown ( 149 | PGUEST_REGS GuestRegs 150 | ); 151 | 152 | NTSTATUS VmxFillGuestSelectorData ( 153 | PVOID GdtBase, 154 | ULONG Segreg, 155 | USHORT Selector 156 | ); 157 | 158 | -------------------------------------------------------------------------------- /hvm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #include "hvm.h" 6 | 7 | ULONG g_uSubvertedCPUs; 8 | 9 | NTSTATUS HvmSubvertCpu ( 10 | PVOID GuestRsp 11 | ) 12 | { 13 | CPU cpu; 14 | PCPU pCpu = &cpu; 15 | ULONG_PTR VMM_Stack; 16 | PHYSICAL_ADDRESS PhyAddr; 17 | 18 | KdPrint (("HvmSubvertCpu(): Running on processor #%d\n", KeGetCurrentProcessorNumber ())); 19 | 20 | // 检查IA32_FEATURE_CONTROL寄存器的Lock位 21 | if (!(__readmsr(MSR_IA32_FEATURE_CONTROL) & FEATURE_CONTROL_LOCKED)) 22 | { 23 | KdPrint(("VmxInitialize() IA32_FEATURE_CONTROL bit[0] = 0!\n")); 24 | return STATUS_UNSUCCESSFUL; 25 | } 26 | 27 | // 检查IA32_FEATURE_CONTROL寄存器的Enable VMX outside SMX位 28 | if (!(__readmsr(MSR_IA32_FEATURE_CONTROL) & FEATURE_CONTROL_VMXON_ENABLED)) 29 | { 30 | KdPrint(("VmxInitialize() IA32_FEATURE_CONTROL bit[2] = 0!\n")); 31 | return STATUS_UNSUCCESSFUL; 32 | } 33 | 34 | PhyAddr.QuadPart = -1; 35 | // 36 | // 为VMXON结构分配空间 (Allocate VMXON region) 37 | // 38 | pCpu->OriginaVmxonR = MmAllocateContiguousMemory(2*PAGE_SIZE, PhyAddr); 39 | if (!pCpu->OriginaVmxonR) 40 | { 41 | KdPrint (("VmxInitialize(): Failed to allocate memory for original VMXON\n")); 42 | return STATUS_INSUFFICIENT_RESOURCES; 43 | } 44 | RtlZeroMemory (pCpu->OriginaVmxonR, 2*PAGE_SIZE); 45 | 46 | // 47 | // 为VMCS结构分配空间 (Allocate VMCS) 48 | // 49 | pCpu->OriginalVmcs = MmAllocateContiguousMemory(PAGE_SIZE, PhyAddr); 50 | if (!pCpu->OriginalVmcs) 51 | { 52 | KdPrint (("VmxInitialize(): Failed to allocate memory for original VMCS\n")); 53 | return STATUS_INSUFFICIENT_RESOURCES; 54 | } 55 | RtlZeroMemory (pCpu->OriginalVmcs, PAGE_SIZE); 56 | 57 | // 为Guest分配内核栈(按页分配), 大小与Host相同 58 | pCpu->VMM_Stack = ExAllocatePoolWithTag (NonPagedPool, 8 * PAGE_SIZE, MEM_TAG); 59 | if (!pCpu->VMM_Stack) 60 | { 61 | KdPrint (("HvmSubvertCpu(): Failed to allocate host stack!\n")); 62 | return STATUS_INSUFFICIENT_RESOURCES; 63 | } 64 | RtlZeroMemory (pCpu->VMM_Stack, 8 * PAGE_SIZE); 65 | //KdPrint(("CPU [%d] VMM_Stack : %p\n", cpu_i, pCpu->VMM_Stack)); 66 | 67 | // 68 | // 准备VM要用到的数据结构 (VMXON & VMCS ) 69 | // GuestRip和GuestRsp会被填进VMCS结构,代表Guest原本的代码位置和栈顶指针 70 | // 71 | 72 | set_in_cr4 (X86_CR4_VMXE); 73 | *(ULONG64 *) pCpu->OriginaVmxonR = (__readmsr(MSR_IA32_VMX_BASIC) & 0xffffffff); //set up vmcs_revision_id 74 | *(ULONG64 *) pCpu->OriginalVmcs = (__readmsr(MSR_IA32_VMX_BASIC) & 0xffffffff); 75 | 76 | PhyAddr = MmGetPhysicalAddress(pCpu->OriginaVmxonR); 77 | if (__vmx_on (&PhyAddr)) 78 | { 79 | KdPrint (("VmxOn Failed!\n")); 80 | return STATUS_UNSUCCESSFUL; 81 | } 82 | 83 | //============================= 配置VMCS ================================ 84 | PhyAddr = MmGetPhysicalAddress(pCpu->OriginalVmcs); 85 | __vmx_vmclear (&PhyAddr); // 取消当前的VMCS的激活状态 86 | __vmx_vmptrld (&PhyAddr); // 加载新的VMCS并设为激活状态 87 | 88 | VMM_Stack = (ULONG_PTR)pCpu->VMM_Stack + 8 * PAGE_SIZE - 8; 89 | if ( VmxSetupVMCS (VMM_Stack, CmGuestEip, GuestRsp) ) 90 | { 91 | KdPrint (("VmxSetupVMCS() failed!")); 92 | __vmx_off (); 93 | clear_in_cr4 (X86_CR4_VMXE); 94 | return STATUS_UNSUCCESSFUL; 95 | } 96 | 97 | InterlockedIncrement (&g_uSubvertedCPUs); // 已侵染的CPU数+=1 98 | 99 | // 一切准备工作完毕,使该CPU进入虚拟机 100 | __vmx_vmlaunch(); 101 | 102 | // never reached 103 | InterlockedDecrement (&g_uSubvertedCPUs); 104 | return STATUS_SUCCESS; 105 | } 106 | 107 | NTSTATUS 108 | HvmSpitOutBluepill () 109 | { 110 | KIRQL OldIrql; 111 | CHAR i; 112 | 113 | // 遍历所有处理器 114 | for (i = 0; i < KeNumberProcessors; i++) 115 | { 116 | KeSetSystemAffinityThread ((KAFFINITY) ((ULONG_PTR)1 << i)); // 将代码运行在指定CPU 117 | OldIrql = KeRaiseIrqlToDpcLevel (); 118 | 119 | VmxVmCall (NBP_HYPERCALL_UNLOAD); 120 | 121 | KeLowerIrql (OldIrql); 122 | KeRevertToUserAffinityThread (); 123 | } 124 | 125 | return STATUS_SUCCESS; 126 | } 127 | 128 | NTSTATUS 129 | HvmSwallowBluepill () 130 | { 131 | NTSTATUS Status; 132 | KIRQL OldIrql; 133 | CHAR i; 134 | 135 | // 遍历所有处理器 136 | for (i = 0; i < KeNumberProcessors; i++) 137 | { 138 | KeSetSystemAffinityThread ((KAFFINITY) ((ULONG_PTR)1 << i)); // 将代码运行在指定CPU 139 | OldIrql = KeRaiseIrqlToDpcLevel (); 140 | 141 | Status = CmSubvert (NULL); // CmSubvert的流程是保存所有寄存器(除了段寄存器)的内容到栈里后,调用HvmSubvertCpu 142 | 143 | KeLowerIrql (OldIrql); 144 | KeRevertToUserAffinityThread (); 145 | 146 | if (Status) 147 | { 148 | KdPrint (("HvmSwallowBluepill(): CmSubvert() failed with status 0x%08hX\n", Status)); 149 | break; 150 | } 151 | } 152 | 153 | if (KeNumberProcessors != g_uSubvertedCPUs) // 如果没有对每个核都侵染成功,则撤销更改 154 | { 155 | HvmSpitOutBluepill (); 156 | return STATUS_UNSUCCESSFUL; 157 | } 158 | 159 | return Status; 160 | } 161 | -------------------------------------------------------------------------------- /vmcs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shamelessly stolen from XEN-3.1 3 | */ 4 | 5 | #pragma once 6 | 7 | #define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 8 | #define CPU_BASED_USE_TSC_OFFSETING 0x00000008 9 | #define CPU_BASED_HLT_EXITING 0x00000080 10 | #define CPU_BASED_INVDPG_EXITING 0x00000200 11 | #define CPU_BASED_MWAIT_EXITING 0x00000400 12 | #define CPU_BASED_RDPMC_EXITING 0x00000800 13 | #define CPU_BASED_RDTSC_EXITING 0x00001000 14 | #define CPU_BASED_CR8_LOAD_EXITING 0x00080000 15 | #define CPU_BASED_CR8_STORE_EXITING 0x00100000 16 | #define CPU_BASED_TPR_SHADOW 0x00200000 17 | #define CPU_BASED_MOV_DR_EXITING 0x00800000 18 | #define CPU_BASED_UNCOND_IO_EXITING 0x01000000 19 | #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 20 | #define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000 21 | #define CPU_BASED_MONITOR_EXITING 0x20000000 22 | #define CPU_BASED_PAUSE_EXITING 0x40000000 23 | 24 | #define PIN_BASED_EXT_INTR_MASK 0x00000001 25 | #define PIN_BASED_NMI_EXITING 0x00000008 26 | 27 | #define VM_EXIT_IA32E_MODE 0x00000200 28 | #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 29 | 30 | #define VM_ENTRY_IA32E_MODE 0x00000200 31 | #define VM_ENTRY_SMM 0x00000400 32 | #define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 33 | 34 | /* VMCS Encordings */ 35 | enum 36 | { 37 | GUEST_ES_SELECTOR = 0x00000800, 38 | GUEST_CS_SELECTOR = 0x00000802, 39 | GUEST_SS_SELECTOR = 0x00000804, 40 | GUEST_DS_SELECTOR = 0x00000806, 41 | GUEST_FS_SELECTOR = 0x00000808, 42 | GUEST_GS_SELECTOR = 0x0000080a, 43 | GUEST_LDTR_SELECTOR = 0x0000080c, 44 | GUEST_TR_SELECTOR = 0x0000080e, 45 | HOST_ES_SELECTOR = 0x00000c00, 46 | HOST_CS_SELECTOR = 0x00000c02, 47 | HOST_SS_SELECTOR = 0x00000c04, 48 | HOST_DS_SELECTOR = 0x00000c06, 49 | HOST_FS_SELECTOR = 0x00000c08, 50 | HOST_GS_SELECTOR = 0x00000c0a, 51 | HOST_TR_SELECTOR = 0x00000c0c, 52 | IO_BITMAP_A = 0x00002000, 53 | IO_BITMAP_A_HIGH = 0x00002001, 54 | IO_BITMAP_B = 0x00002002, 55 | IO_BITMAP_B_HIGH = 0x00002003, 56 | MSR_BITMAP = 0x00002004, 57 | MSR_BITMAP_HIGH = 0x00002005, 58 | VM_EXIT_MSR_STORE_ADDR = 0x00002006, 59 | VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007, 60 | VM_EXIT_MSR_LOAD_ADDR = 0x00002008, 61 | VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009, 62 | VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a, 63 | VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b, 64 | TSC_OFFSET = 0x00002010, 65 | TSC_OFFSET_HIGH = 0x00002011, 66 | VIRTUAL_APIC_PAGE_ADDR = 0x00002012, 67 | VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013, 68 | VMCS_LINK_POINTER = 0x00002800, 69 | VMCS_LINK_POINTER_HIGH = 0x00002801, 70 | GUEST_IA32_DEBUGCTL = 0x00002802, 71 | GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, 72 | PIN_BASED_VM_EXEC_CONTROL = 0x00004000, 73 | CPU_BASED_VM_EXEC_CONTROL = 0x00004002, 74 | EXCEPTION_BITMAP = 0x00004004, 75 | PAGE_FAULT_ERROR_CODE_MASK = 0x00004006, 76 | PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008, 77 | CR3_TARGET_COUNT = 0x0000400a, 78 | VM_EXIT_CONTROLS = 0x0000400c, 79 | VM_EXIT_MSR_STORE_COUNT = 0x0000400e, 80 | VM_EXIT_MSR_LOAD_COUNT = 0x00004010, 81 | VM_ENTRY_CONTROLS = 0x00004012, 82 | VM_ENTRY_MSR_LOAD_COUNT = 0x00004014, 83 | VM_ENTRY_INTR_INFO_FIELD = 0x00004016, 84 | VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018, 85 | VM_ENTRY_INSTRUCTION_LEN = 0x0000401a, 86 | TPR_THRESHOLD = 0x0000401c, 87 | SECONDARY_VM_EXEC_CONTROL = 0x0000401e, 88 | VM_INSTRUCTION_ERROR = 0x00004400, 89 | VM_EXIT_REASON = 0x00004402, 90 | VM_EXIT_INTR_INFO = 0x00004404, 91 | VM_EXIT_INTR_ERROR_CODE = 0x00004406, 92 | IDT_VECTORING_INFO_FIELD = 0x00004408, 93 | IDT_VECTORING_ERROR_CODE = 0x0000440a, 94 | VM_EXIT_INSTRUCTION_LEN = 0x0000440c, 95 | VMX_INSTRUCTION_INFO = 0x0000440e, 96 | GUEST_ES_LIMIT = 0x00004800, 97 | GUEST_CS_LIMIT = 0x00004802, 98 | GUEST_SS_LIMIT = 0x00004804, 99 | GUEST_DS_LIMIT = 0x00004806, 100 | GUEST_FS_LIMIT = 0x00004808, 101 | GUEST_GS_LIMIT = 0x0000480a, 102 | GUEST_LDTR_LIMIT = 0x0000480c, 103 | GUEST_TR_LIMIT = 0x0000480e, 104 | GUEST_GDTR_LIMIT = 0x00004810, 105 | GUEST_IDTR_LIMIT = 0x00004812, 106 | GUEST_ES_AR_BYTES = 0x00004814, 107 | GUEST_CS_AR_BYTES = 0x00004816, 108 | GUEST_SS_AR_BYTES = 0x00004818, 109 | GUEST_DS_AR_BYTES = 0x0000481a, 110 | GUEST_FS_AR_BYTES = 0x0000481c, 111 | GUEST_GS_AR_BYTES = 0x0000481e, 112 | GUEST_LDTR_AR_BYTES = 0x00004820, 113 | GUEST_TR_AR_BYTES = 0x00004822, 114 | GUEST_INTERRUPTIBILITY_STATE = 0x00004824, 115 | GUEST_ACTIVITY_STATE = 0x00004826, 116 | GUEST_SM_BASE = 0x00004828, 117 | GUEST_SYSENTER_CS = 0x0000482A, 118 | HOST_IA32_SYSENTER_CS = 0x00004c00, 119 | CR0_GUEST_HOST_MASK = 0x00006000, 120 | CR4_GUEST_HOST_MASK = 0x00006002, 121 | CR0_READ_SHADOW = 0x00006004, 122 | CR4_READ_SHADOW = 0x00006006, 123 | CR3_TARGET_VALUE0 = 0x00006008, 124 | CR3_TARGET_VALUE1 = 0x0000600a, 125 | CR3_TARGET_VALUE2 = 0x0000600c, 126 | CR3_TARGET_VALUE3 = 0x0000600e, 127 | EXIT_QUALIFICATION = 0x00006400, 128 | GUEST_LINEAR_ADDRESS = 0x0000640a, 129 | GUEST_CR0 = 0x00006800, 130 | GUEST_CR3 = 0x00006802, 131 | GUEST_CR4 = 0x00006804, 132 | GUEST_ES_BASE = 0x00006806, 133 | GUEST_CS_BASE = 0x00006808, 134 | GUEST_SS_BASE = 0x0000680a, 135 | GUEST_DS_BASE = 0x0000680c, 136 | GUEST_FS_BASE = 0x0000680e, 137 | GUEST_GS_BASE = 0x00006810, 138 | GUEST_LDTR_BASE = 0x00006812, 139 | GUEST_TR_BASE = 0x00006814, 140 | GUEST_GDTR_BASE = 0x00006816, 141 | GUEST_IDTR_BASE = 0x00006818, 142 | GUEST_DR7 = 0x0000681a, 143 | GUEST_RSP = 0x0000681c, 144 | GUEST_RIP = 0x0000681e, 145 | GUEST_RFLAGS = 0x00006820, 146 | GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822, 147 | GUEST_SYSENTER_ESP = 0x00006824, 148 | GUEST_SYSENTER_EIP = 0x00006826, 149 | HOST_CR0 = 0x00006c00, 150 | HOST_CR3 = 0x00006c02, 151 | HOST_CR4 = 0x00006c04, 152 | HOST_FS_BASE = 0x00006c06, 153 | HOST_GS_BASE = 0x00006c08, 154 | HOST_TR_BASE = 0x00006c0a, 155 | HOST_GDTR_BASE = 0x00006c0c, 156 | HOST_IDTR_BASE = 0x00006c0e, 157 | HOST_IA32_SYSENTER_ESP = 0x00006c10, 158 | HOST_IA32_SYSENTER_EIP = 0x00006c12, 159 | HOST_RSP = 0x00006c14, 160 | HOST_RIP = 0x00006c16, 161 | }; -------------------------------------------------------------------------------- /vmxdebug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #include "vmx.h" 6 | 7 | VOID VmxDumpVmcs () 8 | { 9 | ULONG32 addr; 10 | 11 | KdPrint (("\n/*****16-bit Guest-State Fields*****/\n")); 12 | KdPrint (("GUEST_ES_SELECTOR 0x%X: 0x%llx\n", GUEST_ES_SELECTOR, VmxRead (GUEST_ES_SELECTOR))); 13 | KdPrint (("GUEST_CS_SELECTOR 0x%X: 0x%llx\n", GUEST_CS_SELECTOR, VmxRead (GUEST_CS_SELECTOR))); 14 | KdPrint (("GUEST_SS_SELECTOR 0x%X: 0x%llx\n", GUEST_SS_SELECTOR, VmxRead (GUEST_SS_SELECTOR))); 15 | KdPrint (("GUEST_DS_SELECTOR 0x%X: 0x%llx\n", GUEST_DS_SELECTOR, VmxRead (GUEST_DS_SELECTOR))); 16 | KdPrint (("GUEST_FS_SELECTOR 0x%X: 0x%llx\n", GUEST_FS_SELECTOR, VmxRead (GUEST_FS_SELECTOR))); 17 | KdPrint (("GUEST_GS_SELECTOR 0x%X: 0x%llx\n", GUEST_GS_SELECTOR, VmxRead (GUEST_GS_SELECTOR))); 18 | KdPrint (("GUEST_LDTR_SELECTOR 0x%X: 0x%llx\n", GUEST_LDTR_SELECTOR, VmxRead (GUEST_LDTR_SELECTOR))); 19 | KdPrint (("GUEST_TR_SELECTOR 0x%X: 0x%llx\n", GUEST_TR_SELECTOR, VmxRead (GUEST_TR_SELECTOR))); 20 | 21 | KdPrint (("\n/*****16-bit Host-State Fields*****/\n")); 22 | KdPrint (("HOST_ES_SELECTOR 0x%X: 0x%llx\n", HOST_ES_SELECTOR, VmxRead (HOST_ES_SELECTOR))); 23 | KdPrint (("HOST_CS_SELECTOR 0x%X: 0x%llx\n", HOST_CS_SELECTOR, VmxRead (HOST_CS_SELECTOR))); 24 | KdPrint (("HOST_SS_SELECTOR 0x%X: 0x%llx\n", HOST_SS_SELECTOR, VmxRead (HOST_SS_SELECTOR))); 25 | KdPrint (("HOST_DS_SELECTOR 0x%X: 0x%llx\n", HOST_DS_SELECTOR, VmxRead (HOST_DS_SELECTOR))); 26 | KdPrint (("HOST_FS_SELECTOR 0x%X: 0x%llx\n", HOST_FS_SELECTOR, VmxRead (HOST_FS_SELECTOR))); 27 | KdPrint (("HOST_GS_SELECTOR 0x%X: 0x%llx\n", HOST_GS_SELECTOR, VmxRead (HOST_GS_SELECTOR))); 28 | KdPrint (("HOST_TR_SELECTOR 0x%X: 0x%llx\n", HOST_TR_SELECTOR, VmxRead (HOST_TR_SELECTOR))); 29 | 30 | KdPrint (("\n/*****64-bit Control Fields*****/\n")); 31 | KdPrint (("IO_BITMAP_A 0x%X: 0x%llx\n", IO_BITMAP_A, VmxRead (IO_BITMAP_A))); 32 | KdPrint (("IO_BITMAP_A_HIGH 0x%X: 0x%llx\n", IO_BITMAP_A_HIGH, VmxRead (IO_BITMAP_A_HIGH))); 33 | KdPrint (("IO_BITMAP_B 0x%X: 0x%llx\n", IO_BITMAP_B, VmxRead (IO_BITMAP_B))); 34 | KdPrint (("IO_BITMAP_B_HIGH 0x%X: 0x%llx\n", IO_BITMAP_B_HIGH, VmxRead (IO_BITMAP_B_HIGH))); 35 | // 36 | KdPrint (("MSR_BITMAP 0x%X: 0x%llx\n", MSR_BITMAP, VmxRead (MSR_BITMAP))); 37 | KdPrint (("MSR_BITMAP_HIGH 0x%X: 0x%llx\n", MSR_BITMAP_HIGH, VmxRead (MSR_BITMAP_HIGH))); 38 | // 39 | KdPrint (("VM_EXIT_MSR_STORE_ADDR 0x%X: 0x%llx\n", VM_EXIT_MSR_STORE_ADDR, VmxRead (VM_EXIT_MSR_STORE_ADDR))); 40 | KdPrint (("VM_EXIT_MSR_STORE_ADDR_HIGH 0x%X: 0x%llx\n", VM_EXIT_MSR_STORE_ADDR_HIGH, VmxRead (VM_EXIT_MSR_STORE_ADDR_HIGH))); 41 | KdPrint (("VM_EXIT_MSR_LOAD_ADDR 0x%X: 0x%llx\n", VM_EXIT_MSR_LOAD_ADDR, VmxRead (VM_EXIT_MSR_LOAD_ADDR))); 42 | KdPrint (("VM_EXIT_MSR_LOAD_ADDR_HIGH 0x%X: 0x%llx\n", VM_EXIT_MSR_LOAD_ADDR_HIGH, VmxRead (VM_EXIT_MSR_LOAD_ADDR_HIGH))); 43 | KdPrint (("VM_ENTRY_MSR_LOAD_ADDR 0x%X: 0x%llx\n", VM_ENTRY_MSR_LOAD_ADDR, VmxRead (VM_ENTRY_MSR_LOAD_ADDR))); 44 | KdPrint (("VM_ENTRY_MSR_LOAD_ADDR_HIGH 0x%X: 0x%llx\n", VM_ENTRY_MSR_LOAD_ADDR_HIGH, VmxRead (VM_ENTRY_MSR_LOAD_ADDR_HIGH))); 45 | // 46 | KdPrint (("TSC_OFFSET 0x%X: 0x%llx\n", TSC_OFFSET, VmxRead (TSC_OFFSET))); 47 | KdPrint (("TSC_OFFSET_HIGH 0x%X: 0x%llx\n", TSC_OFFSET_HIGH, VmxRead (TSC_OFFSET_HIGH))); 48 | // 49 | KdPrint (("VIRTUAL_APIC_PAGE_ADDR 0x%X: 0x%llx\n", VIRTUAL_APIC_PAGE_ADDR, VmxRead (VIRTUAL_APIC_PAGE_ADDR))); 50 | KdPrint (("VIRTUAL_APIC_PAGE_ADDR_HIGH 0x%X: 0x%llx\n", VIRTUAL_APIC_PAGE_ADDR_HIGH, VmxRead (VIRTUAL_APIC_PAGE_ADDR_HIGH))); 51 | 52 | KdPrint (("\n/*****64-bit Guest-State Fields*****/\n")); 53 | KdPrint (("VMCS_LINK_POINTER 0x%X: 0x%llx\n", VMCS_LINK_POINTER, VmxRead (VMCS_LINK_POINTER))); 54 | KdPrint (("VMCS_LINK_POINTER_HIGH 0x%X: 0x%llx\n", VMCS_LINK_POINTER_HIGH, VmxRead (VMCS_LINK_POINTER_HIGH))); 55 | KdPrint (("GUEST_IA32_DEBUGCTL 0x%X: 0x%llx\n", GUEST_IA32_DEBUGCTL, VmxRead (GUEST_IA32_DEBUGCTL))); 56 | KdPrint (("GUEST_IA32_DEBUGCTL_HIGH 0x%X: 0x%llx\n", GUEST_IA32_DEBUGCTL_HIGH, VmxRead (GUEST_IA32_DEBUGCTL_HIGH))); 57 | 58 | KdPrint (("\n\n\n/*****32-bit Control Fields*****/\n")); 59 | addr = PIN_BASED_VM_EXEC_CONTROL; 60 | KdPrint (("PIN_BASED_VM_EXEC_CONTROL 0x%X: 0x%llx\n", addr, VmxRead (addr))); 61 | addr = CPU_BASED_VM_EXEC_CONTROL; 62 | KdPrint (("CPU_BASED_VM_EXEC_CONTROL 0x%X: 0x%llx\n", addr, VmxRead (addr))); 63 | addr = EXCEPTION_BITMAP; 64 | KdPrint (("EXCEPTION_BITMAP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 65 | addr = PAGE_FAULT_ERROR_CODE_MASK; 66 | KdPrint (("PAGE_FAULT_ERROR_CODE_MASK 0x%X: 0x%llx\n", addr, VmxRead (addr))); 67 | addr = PAGE_FAULT_ERROR_CODE_MATCH; 68 | KdPrint (("PAGE_FAULT_ERROR_CODE_MATCH 0x%X: 0x%llx\n", addr, VmxRead (addr))); 69 | addr = CR3_TARGET_COUNT; 70 | KdPrint (("CR3_TARGET_COUNT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 71 | addr = VM_EXIT_CONTROLS; 72 | KdPrint (("VM_EXIT_CONTROLS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 73 | addr = VM_EXIT_MSR_STORE_COUNT; 74 | KdPrint (("VM_EXIT_MSR_STORE_COUNT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 75 | addr = VM_EXIT_MSR_LOAD_COUNT; 76 | KdPrint (("VM_EXIT_MSR_LOAD_COUNT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 77 | addr = VM_ENTRY_CONTROLS; 78 | KdPrint (("VM_ENTRY_CONTROLS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 79 | addr = VM_ENTRY_MSR_LOAD_COUNT; 80 | KdPrint (("VM_ENTRY_MSR_LOAD_COUNT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 81 | addr = VM_ENTRY_INTR_INFO_FIELD; 82 | KdPrint (("VM_ENTRY_INTR_INFO_FIELD 0x%X: 0x%llx\n", addr, VmxRead (addr))); 83 | addr = VM_ENTRY_EXCEPTION_ERROR_CODE; 84 | KdPrint (("VM_ENTRY_EXCEPTION_ERROR_CODE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 85 | addr = VM_ENTRY_INSTRUCTION_LEN; 86 | KdPrint (("VM_ENTRY_INSTRUCTION_LEN 0x%X: 0x%llx\n", addr, VmxRead (addr))); 87 | addr = TPR_THRESHOLD; 88 | KdPrint (("TPR_THRESHOLD 0x%X: 0x%llx\n", addr, VmxRead (addr))); 89 | addr = SECONDARY_VM_EXEC_CONTROL; 90 | KdPrint (("SECONDARY_VM_EXEC_CONTROL 0x%X: 0x%llx\n", addr, VmxRead (addr))); 91 | 92 | KdPrint (("\n\n\n/*****32-bit RO Data Fields*****/\n")); 93 | addr = VM_INSTRUCTION_ERROR; 94 | KdPrint (("VM_INSTRUCTION_ERROR 0x%X: 0x%llx\n", addr, VmxRead (addr))); 95 | addr = VM_EXIT_REASON; 96 | KdPrint (("VM_EXIT_REASON 0x%X: 0x%llx\n", addr, VmxRead (addr))); 97 | addr = VM_EXIT_INTR_INFO; 98 | KdPrint (("VM_EXIT_INTR_INFO 0x%X: 0x%llx\n", addr, VmxRead (addr))); 99 | addr = VM_EXIT_INTR_ERROR_CODE; 100 | KdPrint (("VM_EXIT_INTR_ERROR_CODE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 101 | addr = IDT_VECTORING_INFO_FIELD; 102 | KdPrint (("IDT_VECTORING_INFO_FIELD 0x%X: 0x%llx\n", addr, VmxRead (addr))); 103 | addr = IDT_VECTORING_ERROR_CODE; 104 | KdPrint (("IDT_VECTORING_ERROR_CODE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 105 | addr = VM_EXIT_INSTRUCTION_LEN; 106 | KdPrint (("VM_EXIT_INSTRUCTION_LEN 0x%X: 0x%llx\n", addr, VmxRead (addr))); 107 | addr = VMX_INSTRUCTION_INFO; 108 | KdPrint (("VMX_INSTRUCTION_INFO 0x%X: 0x%llx\n", addr, VmxRead (addr))); 109 | 110 | KdPrint (("\n\n\n/*****32-bit Guest-State Fields*****/\n")); 111 | addr = GUEST_ES_LIMIT; 112 | KdPrint (("GUEST_ES_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 113 | addr = GUEST_CS_LIMIT; 114 | KdPrint (("GUEST_CS_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 115 | addr = GUEST_SS_LIMIT; 116 | KdPrint (("GUEST_SS_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 117 | addr = GUEST_DS_LIMIT; 118 | KdPrint (("GUEST_DS_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 119 | addr = GUEST_FS_LIMIT; 120 | KdPrint (("GUEST_FS_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 121 | addr = GUEST_GS_LIMIT; 122 | KdPrint (("GUEST_GS_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 123 | addr = GUEST_LDTR_LIMIT; 124 | KdPrint (("GUEST_LDTR_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 125 | addr = GUEST_TR_LIMIT; 126 | KdPrint (("GUEST_TR_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 127 | addr = GUEST_GDTR_LIMIT; 128 | KdPrint (("GUEST_GDTR_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 129 | addr = GUEST_IDTR_LIMIT; 130 | KdPrint (("GUEST_IDTR_LIMIT 0x%X: 0x%llx\n", addr, VmxRead (addr))); 131 | addr = GUEST_ES_AR_BYTES; 132 | KdPrint (("GUEST_ES_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 133 | addr = GUEST_CS_AR_BYTES; 134 | KdPrint (("GUEST_CS_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 135 | addr = GUEST_SS_AR_BYTES; 136 | KdPrint (("GUEST_SS_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 137 | addr = GUEST_DS_AR_BYTES; 138 | KdPrint (("GUEST_DS_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 139 | addr = GUEST_FS_AR_BYTES; 140 | KdPrint (("GUEST_FS_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 141 | addr = GUEST_GS_AR_BYTES; 142 | KdPrint (("GUEST_GS_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 143 | addr = GUEST_LDTR_AR_BYTES; 144 | KdPrint (("GUEST_LDTR_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 145 | addr = GUEST_TR_AR_BYTES; 146 | KdPrint (("GUEST_TR_AR_BYTES 0x%X: 0x%llx\n", addr, VmxRead (addr))); 147 | addr = GUEST_INTERRUPTIBILITY_STATE; 148 | KdPrint (("GUEST_INTERRUPTIBILITY_INFO 0x%X: 0x%llx\n", addr, VmxRead (addr))); 149 | addr = GUEST_ACTIVITY_STATE; 150 | KdPrint (("GUEST_ACTIVITY_STATE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 151 | addr = GUEST_SM_BASE; 152 | KdPrint (("GUEST_SM_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 153 | addr = GUEST_SYSENTER_CS; 154 | KdPrint (("GUEST_SYSENTER_CS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 155 | 156 | KdPrint (("\n\n\n/*****32-bit Host-State Fields*****/\n")); 157 | addr = HOST_IA32_SYSENTER_CS; 158 | KdPrint (("HOST_IA32_SYSENTER_CS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 159 | 160 | KdPrint (("\n\n\n/*****Natural 64-bit Control Fields*****/\n")); 161 | addr = CR0_GUEST_HOST_MASK; 162 | KdPrint (("CR0_GUEST_HOST_MASK 0x%X: 0x%llx\n", addr, VmxRead (addr))); 163 | addr = CR4_GUEST_HOST_MASK; 164 | KdPrint (("CR4_GUEST_HOST_MASK 0x%X: 0x%llx\n", addr, VmxRead (addr))); 165 | addr = CR0_READ_SHADOW; 166 | KdPrint (("CR0_READ_SHADOW 0x%X: 0x%llx\n", addr, VmxRead (addr))); 167 | addr = CR4_READ_SHADOW; 168 | KdPrint (("CR4_READ_SHADOW 0x%X: 0x%llx\n", addr, VmxRead (addr))); 169 | addr = CR3_TARGET_VALUE0; 170 | KdPrint (("CR3_TARGET_VALUE0 0x%X: 0x%llx\n", addr, VmxRead (addr))); 171 | addr = CR3_TARGET_VALUE1; 172 | KdPrint (("CR3_TARGET_VALUE1 0x%X: 0x%llx\n", addr, VmxRead (addr))); 173 | addr = CR3_TARGET_VALUE2; 174 | KdPrint (("CR3_TARGET_VALUE2 0x%X: 0x%llx\n", addr, VmxRead (addr))); 175 | addr = CR3_TARGET_VALUE3; 176 | KdPrint (("CR3_TARGET_VALUE3 0x%X: 0x%llx\n", addr, VmxRead (addr))); 177 | 178 | KdPrint (("\n\n\n/*****Natural 64-bit RO Data Fields*****/\n")); 179 | addr = EXIT_QUALIFICATION; 180 | KdPrint (("EXIT_QUALIFICATION 0x%X: 0x%llx\n", addr, VmxRead (addr))); 181 | addr = GUEST_LINEAR_ADDRESS; 182 | KdPrint (("GUEST_LINEAR_ADDRESS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 183 | 184 | KdPrint (("\n\n\n/*****Natural 64-bit Guest-State Fields*****/\n")); 185 | addr = GUEST_CR0; 186 | KdPrint (("GUEST_CR0 0x%X: 0x%llx\n", addr, VmxRead (addr))); 187 | addr = GUEST_CR3; 188 | KdPrint (("GUEST_CR3 0x%X: 0x%llx\n", addr, VmxRead (addr))); 189 | addr = GUEST_CR4; 190 | KdPrint (("GUEST_CR4 0x%X: 0x%llx\n", addr, VmxRead (addr))); 191 | addr = GUEST_ES_BASE; 192 | KdPrint (("GUEST_ES_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 193 | addr = GUEST_CS_BASE; 194 | KdPrint (("GUEST_CS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 195 | addr = GUEST_SS_BASE; 196 | KdPrint (("GUEST_SS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 197 | addr = GUEST_DS_BASE; 198 | KdPrint (("GUEST_DS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 199 | addr = GUEST_FS_BASE; 200 | KdPrint (("GUEST_FS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 201 | addr = GUEST_GS_BASE; 202 | KdPrint (("GUEST_GS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 203 | addr = GUEST_LDTR_BASE; 204 | KdPrint (("GUEST_LDTR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 205 | addr = GUEST_TR_BASE; 206 | KdPrint (("GUEST_TR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 207 | addr = GUEST_GDTR_BASE; 208 | KdPrint (("GUEST_GDTR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 209 | addr = GUEST_IDTR_BASE; 210 | KdPrint (("GUEST_IDTR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 211 | addr = GUEST_DR7; 212 | KdPrint (("GUEST_DR7 0x%X: 0x%llx\n", addr, VmxRead (addr))); 213 | addr = GUEST_RSP; 214 | KdPrint (("GUEST_RSP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 215 | addr = GUEST_RIP; 216 | KdPrint (("GUEST_RIP 0x%X: 0x%llX\n", addr, VmxRead (addr))); 217 | addr = GUEST_RFLAGS; 218 | KdPrint (("GUEST_RFLAGS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 219 | addr = GUEST_PENDING_DBG_EXCEPTIONS; 220 | KdPrint (("GUEST_PENDING_DBG_EXCEPTIONS 0x%X: 0x%llx\n", addr, VmxRead (addr))); 221 | addr = GUEST_SYSENTER_ESP; 222 | KdPrint (("GUEST_SYSENTER_ESP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 223 | addr = GUEST_SYSENTER_EIP; 224 | KdPrint (("GUEST_SYSENTER_EIP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 225 | 226 | KdPrint (("\n\n\n/*****Natural 64-bit Host-State Fields*****/\n")); 227 | addr = HOST_CR0; 228 | KdPrint (("HOST_CR0 0x%X: 0x%llx\n", addr, VmxRead (addr))); 229 | addr = HOST_CR3; 230 | KdPrint (("HOST_CR3 0x%X: 0x%llx\n", addr, VmxRead (addr))); 231 | addr = HOST_CR4; 232 | KdPrint (("HOST_CR4 0x%X: 0x%llx\n", addr, VmxRead (addr))); 233 | addr = HOST_FS_BASE; 234 | KdPrint (("HOST_FS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 235 | addr = HOST_GS_BASE; 236 | KdPrint (("HOST_GS_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 237 | addr = HOST_TR_BASE; 238 | KdPrint (("HOST_TR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 239 | addr = HOST_GDTR_BASE; 240 | KdPrint (("HOST_GDTR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 241 | addr = HOST_IDTR_BASE; 242 | KdPrint (("HOST_IDTR_BASE 0x%X: 0x%llx\n", addr, VmxRead (addr))); 243 | addr = HOST_IA32_SYSENTER_ESP; 244 | KdPrint (("HOST_IA32_SYSENTER_ESP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 245 | addr = HOST_IA32_SYSENTER_EIP; 246 | KdPrint (("HOST_IA32_SYSENTER_EIP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 247 | addr = HOST_RSP; 248 | KdPrint (("HOST_RSP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 249 | addr = HOST_RIP; 250 | KdPrint (("HOST_RIP 0x%X: 0x%llx\n", addr, VmxRead (addr))); 251 | } 252 | -------------------------------------------------------------------------------- /vmx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright holder: Invisible Things Lab 3 | */ 4 | 5 | #include "vmx.h" 6 | 7 | extern ULONG g_uSubvertedCPUs; 8 | 9 | /******************************************************************** 10 | 检测当前的处理器是否支持Vt 11 | ********************************************************************/ 12 | BOOLEAN VmxIsImplemented () 13 | { 14 | ULONG32 eax, ebx, ecx, edx; 15 | GetCpuIdInfo (0, &eax, &ebx, &ecx, &edx); 16 | if (eax < 1) 17 | { 18 | KdPrint (("VmxIsImplemented(): Extended CPUID functions not implemented\n")); 19 | return FALSE; 20 | } 21 | 22 | if (!(ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)) 23 | { 24 | KdPrint (("VmxIsImplemented(): Not an INTEL processor\n")); 25 | return FALSE; 26 | } 27 | 28 | GetCpuIdInfo (0x1, &eax, &ebx, &ecx, &edx); 29 | return (ecx & (1<<5)); 30 | } 31 | 32 | BOOLEAN 33 | DispatchCrAccess (PGUEST_REGS GuestRegs) 34 | { 35 | ULONG32 exit_qualification = (ULONG32) VmxRead (EXIT_QUALIFICATION); 36 | ULONG32 gp = (exit_qualification & CONTROL_REG_ACCESS_REG) >> 8; 37 | ULONG32 cr = exit_qualification & CONTROL_REG_ACCESS_NUM; 38 | 39 | switch (exit_qualification & CONTROL_REG_ACCESS_TYPE) 40 | { 41 | case TYPE_MOV_TO_CR: 42 | if (cr == 0) 43 | { 44 | __vmx_vmwrite (CR0_READ_SHADOW, (*(((PULONG64) GuestRegs) + gp))); 45 | return FALSE; 46 | } 47 | 48 | if (cr == 3) 49 | { 50 | __vmx_vmwrite (GUEST_CR3, *(((PULONG64) GuestRegs) + gp)); 51 | return TRUE; 52 | } 53 | 54 | if (cr == 4) 55 | { 56 | //Nbp need enabele VMXE. so guest try to clear cr4_vmxe, it would be mask. 57 | __vmx_vmwrite (CR4_READ_SHADOW, (*(((PULONG64) GuestRegs) + gp)) & ~X86_CR4_VMXE); 58 | __vmx_vmwrite (GUEST_CR4, (*(((PULONG64) GuestRegs) + gp)) | X86_CR4_VMXE); 59 | 60 | return FALSE; 61 | } 62 | break; 63 | 64 | case TYPE_MOV_FROM_CR: 65 | if (cr == 3) 66 | { 67 | __vmx_vmread(GUEST_CR3, (PULONG64) GuestRegs + gp); 68 | } 69 | break; 70 | case TYPE_CLTS: 71 | break; 72 | case TYPE_LMSW: 73 | break; 74 | } 75 | 76 | return TRUE; 77 | } 78 | 79 | VOID 80 | VmExitHandler ( 81 | PGUEST_REGS GuestRegs 82 | ) 83 | { 84 | ULONG64 ExitReason; 85 | ULONG_PTR GuestEIP; 86 | ULONG_PTR inst_len; 87 | 88 | if (!GuestRegs) 89 | return; 90 | 91 | __vmx_vmread(VM_EXIT_REASON, &ExitReason); 92 | __vmx_vmread(GUEST_RIP, &GuestEIP); 93 | __vmx_vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); 94 | 95 | if (ExitReason == EXIT_REASON_CPUID) // done! 96 | { 97 | ULONG32 fn, eax, ebx, ecx, edx; 98 | 99 | fn = (ULONG32) GuestRegs->rax; 100 | 101 | if (fn == BP_KNOCK_EAX) 102 | { 103 | KdPrint (("Magic knock received: %x\n", BP_KNOCK_EAX)); 104 | GuestRegs->rax = 0x68686868; 105 | } 106 | else 107 | { 108 | ecx = (ULONG32) GuestRegs->rcx; 109 | GetCpuIdInfo (fn, &eax, &ebx, &ecx, &edx); 110 | GuestRegs->rax = eax; 111 | GuestRegs->rbx = ebx; 112 | GuestRegs->rcx = ecx; 113 | GuestRegs->rdx = edx; 114 | } 115 | } 116 | else if (ExitReason == EXIT_REASON_MSR_READ) // done! 117 | { 118 | LARGE_INTEGER MsrValue; 119 | ULONG32 ecx = (ULONG32) GuestRegs->rcx; 120 | 121 | switch (ecx) 122 | { 123 | case MSR_LSTAR: 124 | KdPrint(("readmsr MSR_LSTAR\n")); 125 | MsrValue.QuadPart = __readmsr (MSR_LSTAR); 126 | break; 127 | case MSR_GS_BASE: 128 | MsrValue.QuadPart = VmxRead (GUEST_GS_BASE); 129 | break; 130 | case MSR_FS_BASE: 131 | MsrValue.QuadPart = VmxRead (GUEST_FS_BASE); 132 | break; 133 | default: 134 | MsrValue.QuadPart = __readmsr (ecx); 135 | } 136 | 137 | GuestRegs->rax = MsrValue.LowPart; 138 | GuestRegs->rdx = MsrValue.HighPart; 139 | } 140 | else if (ExitReason == EXIT_REASON_MSR_WRITE) // done! 141 | { 142 | LARGE_INTEGER MsrValue; 143 | ULONG32 ecx = (ULONG32) GuestRegs->rcx; 144 | 145 | MsrValue.LowPart = (ULONG32) GuestRegs->rax; 146 | MsrValue.HighPart = (ULONG32) GuestRegs->rdx; 147 | 148 | switch (ecx) 149 | { 150 | case MSR_LSTAR: 151 | KdPrint(("writemsr MSR_LSTAR\n")); 152 | __vmx_vmwrite (MSR_LSTAR, MsrValue.QuadPart); 153 | break; 154 | case MSR_GS_BASE: 155 | __vmx_vmwrite (GUEST_GS_BASE, MsrValue.QuadPart); 156 | break; 157 | case MSR_FS_BASE: 158 | __vmx_vmwrite (GUEST_FS_BASE, MsrValue.QuadPart); 159 | break; 160 | default: 161 | __writemsr (ecx, MsrValue.QuadPart); 162 | } 163 | } 164 | else if (ExitReason == EXIT_REASON_INVD) // done! 165 | { 166 | 167 | } 168 | else if (ExitReason == EXIT_REASON_VMCALL) // done! 169 | { 170 | ULONG32 HypercallNumber = (ULONG32) (GuestRegs->rcx & 0xffff); 171 | 172 | switch (HypercallNumber) 173 | { 174 | case NBP_HYPERCALL_UNLOAD: 175 | 176 | GuestRegs->rcx = NBP_MAGIC; 177 | GuestRegs->rdx = 0; 178 | 179 | // disable virtualization, resume guest, don't setup time bomb 180 | VmxShutdown (GuestRegs); 181 | 182 | // never returns 183 | KdPrint (("HcDispatchHypercall(): ArchShutdown() returned\n")); 184 | break; 185 | 186 | default: 187 | KdPrint (("HcDispatchHypercall(): Unsupported hypercall 0x%04X\n", HypercallNumber)); 188 | break; 189 | } 190 | 191 | GuestRegs->rcx = NBP_MAGIC; 192 | GuestRegs->rdx = 0; 193 | } 194 | else if (ExitReason >= EXIT_REASON_VMCLEAR && ExitReason <= EXIT_REASON_VMXON) // done! 195 | { 196 | __vmx_vmwrite(GUEST_RFLAGS, VmxRead (GUEST_RFLAGS) & (~0x8d5) | 0x1 /* VMFailInvalid */ ); 197 | } 198 | else if (ExitReason == EXIT_REASON_CR_ACCESS) 199 | { 200 | if (DispatchCrAccess(GuestRegs)) 201 | { 202 | __vmx_vmwrite(GUEST_RIP, GuestEIP + inst_len); 203 | return; 204 | } 205 | else 206 | return; 207 | } 208 | else 209 | { 210 | KdPrint (("VmExitHandler(): failed for exitcode 0x%llX\n", ExitReason)); 211 | //__debugbreak(); 212 | } 213 | 214 | __vmx_vmwrite(GUEST_RIP, GuestEIP + inst_len); 215 | } 216 | 217 | static ULONG32 VmxAdjustControls ( 218 | ULONG32 Ctl, 219 | ULONG32 Msr 220 | ) 221 | { 222 | LARGE_INTEGER MsrValue; 223 | 224 | MsrValue.QuadPart = __readmsr (Msr); 225 | Ctl &= MsrValue.HighPart; /* bit == 0 in high word ==> must be zero */ 226 | Ctl |= MsrValue.LowPart; /* bit == 1 in low word ==> must be one */ 227 | return Ctl; 228 | } 229 | 230 | NTSTATUS VmxFillGuestSelectorData ( 231 | PVOID GdtBase, 232 | ULONG Segreg, 233 | USHORT Selector 234 | ) 235 | { 236 | SEGMENT_SELECTOR SegmentSelector = { 0 }; 237 | ULONG uAccessRights; 238 | 239 | CmInitializeSegmentSelector (&SegmentSelector, Selector, GdtBase); 240 | uAccessRights = ((PUCHAR) & SegmentSelector.attributes)[0] + (((PUCHAR) & SegmentSelector.attributes)[1] << 12); 241 | 242 | if (!Selector) 243 | uAccessRights |= 0x10000; 244 | 245 | __vmx_vmwrite (GUEST_ES_SELECTOR + Segreg * 2, Selector); 246 | __vmx_vmwrite (GUEST_ES_LIMIT + Segreg * 2, SegmentSelector.limit); 247 | __vmx_vmwrite (GUEST_ES_AR_BYTES + Segreg * 2, uAccessRights); 248 | 249 | if ((Segreg == LDTR) || (Segreg == TR)) 250 | // don't setup for FS/GS - their bases are stored in MSR values 251 | __vmx_vmwrite (GUEST_ES_BASE + Segreg * 2, SegmentSelector.base); 252 | 253 | return STATUS_SUCCESS; 254 | } 255 | 256 | NTSTATUS VmxSetupVMCS ( 257 | ULONG_PTR VMM_Stack, 258 | PVOID GuestRip, 259 | PVOID GuestRsp 260 | ) 261 | { 262 | SEGMENT_SELECTOR SegmentSelector; 263 | PVOID GdtBase = (PVOID) GetGdtBase (); 264 | 265 | ///////////////////////////////////////////////////////////////////////////// 266 | /*64BIT Guest-Statel Fields. */ 267 | __vmx_vmwrite (VMCS_LINK_POINTER, 0xffffffff); 268 | __vmx_vmwrite (VMCS_LINK_POINTER_HIGH, 0xffffffff); 269 | 270 | /*32BIT Control Fields. */ //disable Vmexit by Extern-interrupt,NMI and Virtual NMI 271 | __vmx_vmwrite (PIN_BASED_VM_EXEC_CONTROL, VmxAdjustControls (0, MSR_IA32_VMX_PINBASED_CTLS)); 272 | __vmx_vmwrite (CPU_BASED_VM_EXEC_CONTROL, VmxAdjustControls (0, MSR_IA32_VMX_PROCBASED_CTLS)); 273 | __vmx_vmwrite (EXCEPTION_BITMAP, 0); 274 | __vmx_vmwrite (VM_EXIT_CONTROLS, 275 | VmxAdjustControls (VM_EXIT_IA32E_MODE | VM_EXIT_ACK_INTR_ON_EXIT, MSR_IA32_VMX_EXIT_CTLS)); 276 | __vmx_vmwrite (VM_ENTRY_CONTROLS, VmxAdjustControls (VM_ENTRY_IA32E_MODE, MSR_IA32_VMX_ENTRY_CTLS)); 277 | 278 | __vmx_vmwrite (VM_EXIT_MSR_STORE_COUNT, 0); 279 | __vmx_vmwrite (VM_EXIT_MSR_LOAD_COUNT, 0); 280 | __vmx_vmwrite (VM_ENTRY_MSR_LOAD_COUNT, 0); 281 | __vmx_vmwrite (VM_ENTRY_INTR_INFO_FIELD,0); 282 | __vmx_vmwrite (GUEST_ACTIVITY_STATE, 0); // 处于正常执行指令状态 283 | 284 | //////////////////////////////////////////////////////////////////////////////////////////////// 285 | 286 | // SetCRx() 287 | __vmx_vmwrite (CR0_GUEST_HOST_MASK, X86_CR0_PG); // disable vmexit 0f mov to cr0 expect for X86_CR0_PG 288 | __vmx_vmwrite (CR4_GUEST_HOST_MASK, X86_CR4_VMXE); // disable vmexit 0f mov to cr4 expect for X86_CR4_VMXE 289 | //__vmx_vmwrite (CR0_READ_SHADOW, __readcr0()); 290 | __vmx_vmwrite (CR4_READ_SHADOW, __readcr4() & ~X86_CR4_VMXE); // Cr4寄存器SHADOW里去掉X86_CR4_VMXE 291 | 292 | // 293 | __vmx_vmwrite (GUEST_CR0, __readcr0 ()); 294 | __vmx_vmwrite (GUEST_CR3, __readcr3 ()); 295 | __vmx_vmwrite (GUEST_CR4, __readcr4 ()); 296 | __vmx_vmwrite (GUEST_DR7, 0x400); 297 | // 298 | __vmx_vmwrite (HOST_CR0, __readcr0 ()); 299 | __vmx_vmwrite (HOST_CR3, __readcr3 ()); 300 | __vmx_vmwrite (HOST_CR4, __readcr4 ()); 301 | 302 | // SetDT() 303 | __vmx_vmwrite (GUEST_GDTR_LIMIT, GetGdtLimit ()); 304 | __vmx_vmwrite (GUEST_IDTR_LIMIT, GetIdtLimit ()); 305 | __vmx_vmwrite (GUEST_GDTR_BASE, (ULONG64) GdtBase); 306 | __vmx_vmwrite (GUEST_IDTR_BASE, GetIdtBase ()); 307 | // 308 | __vmx_vmwrite (HOST_GDTR_BASE, (ULONG64) GdtBase); 309 | __vmx_vmwrite (HOST_IDTR_BASE, (ULONG64) GetIdtBase ()); 310 | 311 | // SetSegSelectors() 312 | VmxFillGuestSelectorData (GdtBase, ES, RegGetEs ()); 313 | VmxFillGuestSelectorData (GdtBase, CS, RegGetCs ()); 314 | VmxFillGuestSelectorData (GdtBase, SS, RegGetSs ()); 315 | VmxFillGuestSelectorData (GdtBase, DS, RegGetDs ()); 316 | VmxFillGuestSelectorData (GdtBase, FS, RegGetFs ()); 317 | VmxFillGuestSelectorData (GdtBase, GS, RegGetGs ()); 318 | VmxFillGuestSelectorData (GdtBase, LDTR, GetLdtr ()); 319 | VmxFillGuestSelectorData (GdtBase, TR, GetTrSelector ()); 320 | // 321 | __vmx_vmwrite (GUEST_ES_BASE, 0); 322 | __vmx_vmwrite (GUEST_CS_BASE, 0); 323 | __vmx_vmwrite (GUEST_SS_BASE, 0); 324 | __vmx_vmwrite (GUEST_DS_BASE, 0); 325 | __vmx_vmwrite (GUEST_FS_BASE, __readmsr (MSR_FS_BASE)); 326 | __vmx_vmwrite (GUEST_GS_BASE, __readmsr (MSR_GS_BASE)); 327 | // 328 | __vmx_vmwrite (HOST_CS_SELECTOR, BP_GDT64_CODE); 329 | __vmx_vmwrite (HOST_DS_SELECTOR, BP_GDT64_DATA); 330 | __vmx_vmwrite (HOST_ES_SELECTOR, BP_GDT64_DATA); 331 | __vmx_vmwrite (HOST_SS_SELECTOR, BP_GDT64_DATA); 332 | __vmx_vmwrite (HOST_FS_SELECTOR, RegGetFs () & 0xf8); 333 | __vmx_vmwrite (HOST_GS_SELECTOR, RegGetGs () & 0xf8); 334 | __vmx_vmwrite (HOST_TR_SELECTOR, GetTrSelector () & 0xf8); 335 | // 336 | __vmx_vmwrite (HOST_FS_BASE, __readmsr (MSR_FS_BASE)); 337 | __vmx_vmwrite (HOST_GS_BASE, __readmsr (MSR_GS_BASE)); 338 | CmInitializeSegmentSelector (&SegmentSelector, GetTrSelector (), GdtBase); 339 | __vmx_vmwrite (HOST_TR_BASE, SegmentSelector.base); 340 | 341 | ///////////////////////////////////////////////////////////////////////////// 342 | __vmx_vmwrite (GUEST_RSP, (ULONG64) GuestRsp); //setup guest sp 343 | __vmx_vmwrite (GUEST_RIP, (ULONG64) GuestRip); //setup guest ip : common-asm CmResumeGuest 344 | __vmx_vmwrite (GUEST_RFLAGS, RegGetRflags ()); 345 | 346 | // HOST_RSP与HOST_RIP决定进入VMM的地址 347 | __vmx_vmwrite (HOST_RSP, VMM_Stack); 348 | __vmx_vmwrite (HOST_RIP, (ULONG64) VmxVmexitHandler); 349 | 350 | return STATUS_SUCCESS; 351 | } 352 | 353 | VOID VmxGenerateTrampolineToGuest ( 354 | PGUEST_REGS GuestRegs, 355 | PUCHAR Trampoline 356 | ) 357 | { 358 | ULONG uTrampolineSize = 0; 359 | ULONG64 NewRsp; 360 | 361 | // assume Trampoline buffer is big enough 362 | __vmx_vmwrite (GUEST_RFLAGS, VmxRead (GUEST_RFLAGS) & ~0x100); // disable TF 363 | 364 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RCX, GuestRegs->rcx); 365 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RDX, GuestRegs->rdx); 366 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RBX, GuestRegs->rbx); 367 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RBP, GuestRegs->rbp); 368 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RSI, GuestRegs->rsi); 369 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RDI, GuestRegs->rdi); 370 | 371 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R8, GuestRegs->r8); 372 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R9, GuestRegs->r9); 373 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R10, GuestRegs->r10); 374 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R11, GuestRegs->r11); 375 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R12, GuestRegs->r12); 376 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R13, GuestRegs->r13); 377 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R14, GuestRegs->r14); 378 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_R15, GuestRegs->r15); 379 | 380 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR0, VmxRead (GUEST_CR0)); 381 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR3, VmxRead (GUEST_CR3)); 382 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_CR4, VmxRead (GUEST_CR4)); 383 | 384 | NewRsp = VmxRead (GUEST_RSP); 385 | 386 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RSP, NewRsp); 387 | 388 | // construct stack frame for IRETQ: 389 | // [TOS] rip 390 | // [TOS+0x08] cs 391 | // [TOS+0x10] rflags 392 | // [TOS+0x18] rsp 393 | // [TOS+0x20] ss 394 | 395 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, VmxRead (GUEST_SS_SELECTOR)); 396 | CmGeneratePushReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX); 397 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, NewRsp); 398 | CmGeneratePushReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX); 399 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, VmxRead (GUEST_RFLAGS)); 400 | CmGeneratePushReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX); 401 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, VmxRead (GUEST_CS_SELECTOR)); 402 | CmGeneratePushReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX); 403 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, VmxRead (GUEST_RIP) + VmxRead (VM_EXIT_INSTRUCTION_LEN)); 404 | CmGeneratePushReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX); 405 | CmGenerateMovReg (&Trampoline[uTrampolineSize], &uTrampolineSize, REG_RAX, GuestRegs->rax); 406 | 407 | CmGenerateIretq (&Trampoline[uTrampolineSize], &uTrampolineSize); 408 | } 409 | 410 | NTSTATUS VmxShutdown ( 411 | PGUEST_REGS GuestRegs 412 | ) 413 | { 414 | UCHAR Trampoline[0x600]; 415 | 416 | InterlockedDecrement (&g_uSubvertedCPUs); 417 | 418 | // The code should be updated to build an approproate trampoline to exit to any guest mode. 419 | VmxGenerateTrampolineToGuest (GuestRegs, Trampoline); 420 | 421 | __vmx_off (); 422 | clear_in_cr4 (X86_CR4_VMXE); 423 | 424 | ((VOID (*)()) &Trampoline) (); 425 | 426 | // never returns 427 | return STATUS_SUCCESS; 428 | } 429 | --------------------------------------------------------------------------------