From c587c20e3fb9a982e5d6a5be28b2f3d9c3e77c04 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 3 Feb 2021 00:46:27 -0800 Subject: [PATCH] vmxlaunch is working... still some issues with host stack i think, need to handle vmexits and shit now... --- bluepill.sln | 4 + bluepill.vcxproj | 29 ++++++ bluepill.vcxproj.user | 3 + hv_types.hpp | 36 ++++--- segment.cpp | 26 ++++- vmcs.cpp | 236 ++++++++++++++++++++++++++++++++++++++---- vmxexit_handler.asm | 2 - vmxon.cpp | 18 +++- 8 files changed, 307 insertions(+), 47 deletions(-) diff --git a/bluepill.sln b/bluepill.sln index 08d6100..8823095 100644 --- a/bluepill.sln +++ b/bluepill.sln @@ -7,9 +7,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bluepill", "bluepill.vcxpro EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Debug|x64.ActiveCfg = Debug|x64 + {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Debug|x64.Build.0 = Debug|x64 + {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Debug|x64.Deploy.0 = Debug|x64 {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.ActiveCfg = Release|x64 {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.Build.0 = Release|x64 {881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.Deploy.0 = Release|x64 diff --git a/bluepill.vcxproj b/bluepill.vcxproj index e62f178..94f6559 100644 --- a/bluepill.vcxproj +++ b/bluepill.vcxproj @@ -1,6 +1,10 @@  + + Debug + x64 + Release x64 @@ -28,6 +32,16 @@ false false + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + false + false + @@ -40,6 +54,10 @@ DbgengKernelDebugger false + + DbgengKernelDebugger + false + false @@ -50,6 +68,17 @@ false + + + false + driver_entry + + + stdcpp17 + false + DBG_PRINT_BOOL;%(PreprocessorDefinitions) + + diff --git a/bluepill.vcxproj.user b/bluepill.vcxproj.user index b2a2bcc..d906e66 100644 --- a/bluepill.vcxproj.user +++ b/bluepill.vcxproj.user @@ -3,4 +3,7 @@ Off + + Off + \ No newline at end of file diff --git a/hv_types.hpp b/hv_types.hpp index 3fb6156..d5e6524 100644 --- a/hv_types.hpp +++ b/hv_types.hpp @@ -18,29 +18,18 @@ using s64 = long long; extern "C" void _sgdt(void*); #pragma intrinsic(_sgdt); +#ifdef DBG_PRINT_BOOL +#define DBG_PRINT(format, ...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[hv [core number = %d]]" format, KeGetCurrentProcessorNumber(), __VA_ARGS__) +#else +#define DBG_PRINT(format, ...) +#endif -#define DBG_PRINT(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[hv]" __VA_ARGS__) #define HOST_STACK_PAGES 6 namespace hv { typedef struct _guest_registers { - u64 r15; - u64 r14; - u64 r13; - u64 r12; - u64 r11; - u64 r10; - u64 r9; - u64 r8; - u64 rbp; - u64 rdi; - u64 rsi; - u64 rdx; - u64 rcx; - u64 rax; - u128 xmm0; u128 xmm1; u128 xmm2; @@ -57,6 +46,21 @@ namespace hv u128 xmm13; u128 xmm14; u128 xmm15; + + u64 r15; + u64 r14; + u64 r13; + u64 r12; + u64 r11; + u64 r10; + u64 r9; + u64 r8; + u64 rbp; + u64 rdi; + u64 rsi; + u64 rdx; + u64 rcx; + u64 rax; } guest_registers, * pguest_registers; union ia32_efer_t diff --git a/segment.cpp b/segment.cpp index b991148..8e7c0b4 100644 --- a/segment.cpp +++ b/segment.cpp @@ -18,20 +18,38 @@ namespace segment auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx { hv::segment_info_ctx segment_info; + + // GDT->BaseAddress + (segment index << 3) + // gives us a pointer to the segment descriptor... const auto segment_descriptor = reinterpret_cast( gdt_value.base_address + (segment_selector.index << SEGMENT_SELECTOR_INDEX_BIT)); + // access rights are spread out over the segment + // descriptor so those need to picked out and assigned + // to the vmx segment access rights variable... segment_info.limit = __segmentlimit(segment_selector.flags); segment_info.rights = get_access_rights(segment_descriptor); - segment_info.base_addr = (u32)((segment_descriptor->base_address_high << SEGMENT__BASE_ADDRESS_HIGH_BIT) | - (segment_descriptor->base_address_middle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) | + // base address of a segment is spread over the segment descriptor in 3 places. 2 parts of the + // address are 8 bits each (1 byte each) and the lowest part of the address is 2 bytes (4 bytes in total)... + // by shifting the values to the correct bit offset and adding them all together we get the address... + segment_info.base_addr = (u32)((segment_descriptor->base_address_high << SEGMENT__BASE_ADDRESS_HIGH_BIT) + + (segment_descriptor->base_address_middle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) + (segment_descriptor->base_address_low)); - segment_info.base_addr &= 0xFFFFFFFF; + // Example: + // - high bits: 0b1111 0000 0000 0000 + // - middle bits: 0b0000 1111 0000 0000 + // - low bits: 0b0000 0000 1011 1000 + // --------------------- + + // 0b1111 1111 1011 1000 <==== full address... + // if you add all of these together you will get the full address... + + // if the base address is 64bits then go ahead + // and add the top 32bits onto the address.. if (!segment_descriptor->descriptor_type) - segment_info.base_addr |= ((u64)segment_descriptor->base_address_upper << SEGMENT__BASE_ADDRESS_SHIFT); + segment_info.base_addr += ((u64)segment_descriptor->base_address_upper << SEGMENT__BASE_ADDRESS_SHIFT); return segment_info; } diff --git a/vmcs.cpp b/vmcs.cpp index 8e261d7..9774b7b 100644 --- a/vmcs.cpp +++ b/vmcs.cpp @@ -10,12 +10,14 @@ namespace vmcs __sidt(&idt_value); _sgdt(&gdt_value); + // use guest values for now... later on CR3 will be custom... __vmx_vmwrite(VMCS_HOST_CR0, __readcr0()); __vmx_vmwrite(VMCS_HOST_CR3, __readcr3()); __vmx_vmwrite(VMCS_HOST_CR4, __readcr4()); + // stack growns down... + __vmx_vmwrite(VMCS_HOST_RSP, host_rsp + (PAGE_SIZE * HOST_STACK_PAGES) - 8); __vmx_vmwrite(VMCS_HOST_RIP, reinterpret_cast(host_rip)); - __vmx_vmwrite(VMCS_HOST_RSP, host_rsp); __vmx_vmwrite(VMCS_HOST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); __vmx_vmwrite(VMCS_HOST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); @@ -24,13 +26,43 @@ namespace vmcs __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address); __vmx_vmwrite(VMCS_HOST_IDTR_BASE, idt_value.base_address); - __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, reades()); - __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, readcs()); - __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, readds()); - __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, readfs()); - __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, readgs()); - __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, readss()); - __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, readtr()); + // manual says that the priv level must be 0 and + // that the table flag also needs to be 0 so it uses the GDT... + segment_selector es{ reades() }; + es.request_privilege_level = NULL; + es.table = NULL; + + segment_selector cs{ readcs() }; + cs.request_privilege_level = NULL; + cs.table = NULL; + + segment_selector ds{ readds() }; + ds.request_privilege_level = NULL; + ds.table = NULL; + + segment_selector fs{ readfs() }; + fs.request_privilege_level = NULL; + fs.table = NULL; + + segment_selector gs{ readgs() }; + gs.request_privilege_level = NULL; + gs.table = NULL; + + segment_selector ss{ readss() }; + ss.request_privilege_level = NULL; + ss.table = NULL; + + segment_selector tr{ readtr() }; + tr.request_privilege_level = NULL; + tr.table = NULL; + + __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, es.flags); + __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, cs.flags); + __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, ds.flags); + __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, fs.flags); + __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, gs.flags); + __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, ss.flags); + __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, tr.flags); __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); __vmx_vmwrite(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE)); @@ -157,25 +189,91 @@ namespace vmcs pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); + DBG_PRINT("============================== pinbased vm-exit controls ==============================\n"); + DBG_PRINT(" - pinbased_ctls.activate_vmx_preemption_timer: %d\n", pinbased_ctls.activate_vmx_preemption_timer); + DBG_PRINT(" - pinbased_ctls.external_interrupt_exiting: %d\n", pinbased_ctls.external_interrupt_exiting); + DBG_PRINT(" - pinbased_ctls.nmi_exiting: %d\n", pinbased_ctls.nmi_exiting); + DBG_PRINT(" - pinbased_ctls.process_posted_interrupts: %d\n", pinbased_ctls.process_posted_interrupts); + DBG_PRINT(" - pinbased_ctls.virtual_nmi: %d\n", pinbased_ctls.virtual_nmi); + DBG_PRINT(" - pinbased_ctls.flags: 0x%x\n", pinbased_ctls.flags); + DBG_PRINT(" - IA32_VMX_TRUE_PINBASED_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_TRUE_PINBASED_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS); + procbased_ctls.activate_secondary_controls = true; procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings; - procbased_ctls.activate_secondary_controls = true; __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); + DBG_PRINT("============================== processor based vm-exit controls ==============================\n"); + DBG_PRINT(" - procbased_ctls.activate_secondary_controls: %d\n", procbased_ctls.activate_secondary_controls); + DBG_PRINT(" - procbased_ctls.cr3_load_exiting: %d\n", procbased_ctls.cr3_load_exiting); + DBG_PRINT(" - procbased_ctls.cr3_store_exiting: %d\n", procbased_ctls.cr3_store_exiting); + DBG_PRINT(" - procbased_ctls.cr8_load_exiting: %d\n", procbased_ctls.cr8_load_exiting); + DBG_PRINT(" - procbased_ctls.cr8_store_exiting: %d\n", procbased_ctls.cr8_store_exiting); + DBG_PRINT(" - procbased_ctls.hlt_exiting: %d\n", procbased_ctls.hlt_exiting); + DBG_PRINT(" - procbased_ctls.interrupt_window_exiting: %d\n", procbased_ctls.interrupt_window_exiting); + DBG_PRINT(" - procbased_ctls.invlpg_exiting: %d\n", procbased_ctls.invlpg_exiting); + DBG_PRINT(" - procbased_ctls.monitor_exiting: %d\n", procbased_ctls.monitor_exiting); + DBG_PRINT(" - procbased_ctls.monitor_trap_flag: %d\n", procbased_ctls.monitor_trap_flag); + DBG_PRINT(" - procbased_ctls.mov_dr_exiting: %d\n", procbased_ctls.mov_dr_exiting); + DBG_PRINT(" - procbased_ctls.mwait_exiting: %d\n", procbased_ctls.mwait_exiting); + DBG_PRINT(" - procbased_ctls.nmi_window_exiting: %d\n", procbased_ctls.nmi_window_exiting); + DBG_PRINT(" - procbased_ctls.pause_exiting: %d\n", procbased_ctls.pause_exiting); + DBG_PRINT(" - procbased_ctls.rdpmc_exiting: %d\n", procbased_ctls.rdpmc_exiting); + DBG_PRINT(" - procbased_ctls.rdtsc_exiting: %d\n", procbased_ctls.rdtsc_exiting); + DBG_PRINT(" - procbased_ctls.unconditional_io_exiting: %d\n", procbased_ctls.unconditional_io_exiting); + DBG_PRINT(" - procbased_ctls.use_io_bitmaps: %d\n", procbased_ctls.use_io_bitmaps); + DBG_PRINT(" - procbased_ctls.use_msr_bitmaps: %d\n", procbased_ctls.use_msr_bitmaps); + DBG_PRINT(" - procbased_ctls.use_tpr_shadow: %d\n", procbased_ctls.use_tpr_shadow); + DBG_PRINT(" - procbased_ctls.use_tsc_offsetting: %d\n", procbased_ctls.use_tsc_offsetting); + DBG_PRINT(" - procbased_ctls.flags: 0x%x\n", procbased_ctls.flags); + DBG_PRINT(" - IA32_VMX_TRUE_PROCBASED_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_TRUE_PROCBASED_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS); + entry_ctls.ia32e_mode_guest = true; entry_ctls.flags &= msr_fix_value.allowed_1_settings; entry_ctls.flags |= msr_fix_value.allowed_0_settings; - entry_ctls.ia32e_mode_guest = true; - entry_ctls.conceal_vmx_from_pt = true; __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); + DBG_PRINT("============================== vm-entry controls ==============================\n"); + DBG_PRINT(" - entry_ctls.conceal_vmx_from_pt: %d\n", entry_ctls.conceal_vmx_from_pt); + DBG_PRINT(" - entry_ctls.deactivate_dual_monitor_treatment: %d\n", entry_ctls.deactivate_dual_monitor_treatment); + DBG_PRINT(" - entry_ctls.entry_to_smm: %d\n", entry_ctls.entry_to_smm); + DBG_PRINT(" - entry_ctls.ia32e_mode_guest: %d\n", entry_ctls.ia32e_mode_guest); + DBG_PRINT(" - entry_ctls.load_cet_state: %d\n", entry_ctls.load_cet_state); + DBG_PRINT(" - entry_ctls.load_debug_controls: %d\n", entry_ctls.load_debug_controls); + DBG_PRINT(" - entry_ctls.load_ia32_bndcfgs: %d\n", entry_ctls.load_ia32_bndcfgs); + DBG_PRINT(" - entry_ctls.load_ia32_efer: %d\n", entry_ctls.load_ia32_efer); + DBG_PRINT(" - entry_ctls.load_ia32_pat: %d\n", entry_ctls.load_ia32_pat); + DBG_PRINT(" - entry_ctls.load_ia32_perf_global_ctrl: %d\n", entry_ctls.load_ia32_perf_global_ctrl); + DBG_PRINT(" - entry_ctls.load_ia32_rtit_ctl: %d\n", entry_ctls.load_ia32_rtit_ctl); + DBG_PRINT(" - entry_ctls.flags: 0x%x\n", entry_ctls.flags); + DBG_PRINT(" - IA32_VMX_TRUE_ENTRY_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_TRUE_ENTRY_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_EXIT_CTLS); + exit_ctls.host_address_space_size = true; exit_ctls.flags &= msr_fix_value.allowed_1_settings; exit_ctls.flags |= msr_fix_value.allowed_0_settings; - exit_ctls.host_address_space_size = true; - exit_ctls.conceal_vmx_from_pt = true; __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); + + DBG_PRINT("============================== vm-exit controls ==============================\n"); + DBG_PRINT(" - exit_ctls.acknowledge_interrupt_on_exit: %d\n", exit_ctls.acknowledge_interrupt_on_exit); + DBG_PRINT(" - exit_ctls.clear_ia32_bndcfgs: %d\n", exit_ctls.clear_ia32_bndcfgs); + DBG_PRINT(" - exit_ctls.conceal_vmx_from_pt: %d\n", exit_ctls.conceal_vmx_from_pt); + DBG_PRINT(" - exit_ctls.host_address_space_size: %d\n", exit_ctls.host_address_space_size); + DBG_PRINT(" - exit_ctls.load_ia32_efer: %d\n", exit_ctls.load_ia32_efer); + DBG_PRINT(" - exit_ctls.load_ia32_pat: %d\n", exit_ctls.load_ia32_pat); + DBG_PRINT(" - exit_ctls.load_ia32_perf_global_ctrl: %d\n", exit_ctls.load_ia32_perf_global_ctrl); + DBG_PRINT(" - exit_ctls.save_debug_controls: %d\n", exit_ctls.save_debug_controls); + DBG_PRINT(" - exit_ctls.save_ia32_efer: %d\n", exit_ctls.save_ia32_efer); + DBG_PRINT(" - exit_ctls.save_ia32_pat: %d\n", exit_ctls.save_ia32_pat); + DBG_PRINT(" - exit_ctls.save_vmx_preemption_timer_value: %d\n", exit_ctls.save_vmx_preemption_timer_value); + DBG_PRINT(" - exit_ctls.flags: 0x%x\n", exit_ctls.flags); + DBG_PRINT(" - IA32_VMX_TRUE_EXIT_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_TRUE_EXIT_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); } else { @@ -184,33 +282,129 @@ namespace vmcs pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); + DBG_PRINT("============================== pinbased vm-exit controls ==============================\n"); + DBG_PRINT(" - pinbased_ctls.activate_vmx_preemption_timer: %d\n", pinbased_ctls.activate_vmx_preemption_timer); + DBG_PRINT(" - pinbased_ctls.external_interrupt_exiting: %d\n", pinbased_ctls.external_interrupt_exiting); + DBG_PRINT(" - pinbased_ctls.nmi_exiting: %d\n", pinbased_ctls.nmi_exiting); + DBG_PRINT(" - pinbased_ctls.process_posted_interrupts: %d\n", pinbased_ctls.process_posted_interrupts); + DBG_PRINT(" - pinbased_ctls.virtual_nmi: %d\n", pinbased_ctls.virtual_nmi); + DBG_PRINT(" - pinbased_ctls.flags: 0x%x\n", pinbased_ctls.flags); + DBG_PRINT(" - IA32_VMX_PINBASED_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_PINBASED_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS); + procbased_ctls.activate_secondary_controls = true; procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings; - procbased_ctls.activate_secondary_controls = true; __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); + DBG_PRINT("============================== processor based vm-exit controls ==============================\n"); + DBG_PRINT(" - procbased_ctls.activate_secondary_controls: %d\n", procbased_ctls.activate_secondary_controls); + DBG_PRINT(" - procbased_ctls.cr3_load_exiting: %d\n", procbased_ctls.cr3_load_exiting); + DBG_PRINT(" - procbased_ctls.cr3_store_exiting: %d\n", procbased_ctls.cr3_store_exiting); + DBG_PRINT(" - procbased_ctls.cr8_load_exiting: %d\n", procbased_ctls.cr8_load_exiting); + DBG_PRINT(" - procbased_ctls.cr8_store_exiting: %d\n", procbased_ctls.cr8_store_exiting); + DBG_PRINT(" - procbased_ctls.hlt_exiting: %d\n", procbased_ctls.hlt_exiting); + DBG_PRINT(" - procbased_ctls.interrupt_window_exiting: %d\n", procbased_ctls.interrupt_window_exiting); + DBG_PRINT(" - procbased_ctls.invlpg_exiting: %d\n", procbased_ctls.invlpg_exiting); + DBG_PRINT(" - procbased_ctls.monitor_exiting: %d\n", procbased_ctls.monitor_exiting); + DBG_PRINT(" - procbased_ctls.monitor_trap_flag: %d\n", procbased_ctls.monitor_trap_flag); + DBG_PRINT(" - procbased_ctls.mov_dr_exiting: %d\n", procbased_ctls.mov_dr_exiting); + DBG_PRINT(" - procbased_ctls.mwait_exiting: %d\n", procbased_ctls.mwait_exiting); + DBG_PRINT(" - procbased_ctls.nmi_window_exiting: %d\n", procbased_ctls.nmi_window_exiting); + DBG_PRINT(" - procbased_ctls.pause_exiting: %d\n", procbased_ctls.pause_exiting); + DBG_PRINT(" - procbased_ctls.rdpmc_exiting: %d\n", procbased_ctls.rdpmc_exiting); + DBG_PRINT(" - procbased_ctls.rdtsc_exiting: %d\n", procbased_ctls.rdtsc_exiting); + DBG_PRINT(" - procbased_ctls.unconditional_io_exiting: %d\n", procbased_ctls.unconditional_io_exiting); + DBG_PRINT(" - procbased_ctls.use_io_bitmaps: %d\n", procbased_ctls.use_io_bitmaps); + DBG_PRINT(" - procbased_ctls.use_msr_bitmaps: %d\n", procbased_ctls.use_msr_bitmaps); + DBG_PRINT(" - procbased_ctls.use_tpr_shadow: %d\n", procbased_ctls.use_tpr_shadow); + DBG_PRINT(" - procbased_ctls.use_tsc_offsetting: %d\n", procbased_ctls.use_tsc_offsetting); + DBG_PRINT(" - procbased_ctls.flags: 0x%x\n", procbased_ctls.flags); + DBG_PRINT(" - IA32_VMX_PROCBASED_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_PROCBASED_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS); - entry_ctls.flags &= msr_fix_value.allowed_1_settings; - entry_ctls.flags |= msr_fix_value.allowed_0_settings; entry_ctls.ia32e_mode_guest = true; entry_ctls.conceal_vmx_from_pt = true; + entry_ctls.flags &= msr_fix_value.allowed_1_settings; + entry_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); + DBG_PRINT("============================== vm-entry controls ==============================\n"); + DBG_PRINT(" - entry_ctls.conceal_vmx_from_pt: %d\n", entry_ctls.conceal_vmx_from_pt); + DBG_PRINT(" - entry_ctls.deactivate_dual_monitor_treatment: %d\n", entry_ctls.deactivate_dual_monitor_treatment); + DBG_PRINT(" - entry_ctls.entry_to_smm: %d\n", entry_ctls.entry_to_smm); + DBG_PRINT(" - entry_ctls.ia32e_mode_guest: %d\n", entry_ctls.ia32e_mode_guest); + DBG_PRINT(" - entry_ctls.load_cet_state: %d\n", entry_ctls.load_cet_state); + DBG_PRINT(" - entry_ctls.load_debug_controls: %d\n", entry_ctls.load_debug_controls); + DBG_PRINT(" - entry_ctls.load_ia32_bndcfgs: %d\n", entry_ctls.load_ia32_bndcfgs); + DBG_PRINT(" - entry_ctls.load_ia32_efer: %d\n", entry_ctls.load_ia32_efer); + DBG_PRINT(" - entry_ctls.load_ia32_pat: %d\n", entry_ctls.load_ia32_pat); + DBG_PRINT(" - entry_ctls.load_ia32_perf_global_ctrl: %d\n", entry_ctls.load_ia32_perf_global_ctrl); + DBG_PRINT(" - entry_ctls.load_ia32_rtit_ctl: %d\n", entry_ctls.load_ia32_rtit_ctl); + DBG_PRINT(" - entry_ctls.flags: 0x%x\n", entry_ctls.flags); + DBG_PRINT(" - IA32_VMX_ENTRY_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_ENTRY_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); + msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS); - exit_ctls.flags &= msr_fix_value.allowed_1_settings; - exit_ctls.flags |= msr_fix_value.allowed_0_settings; exit_ctls.host_address_space_size = true; exit_ctls.conceal_vmx_from_pt = true; + exit_ctls.flags &= msr_fix_value.allowed_1_settings; + exit_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); + + DBG_PRINT("============================== vm-exit controls ==============================\n"); + DBG_PRINT(" - exit_ctls.acknowledge_interrupt_on_exit: %d\n", exit_ctls.acknowledge_interrupt_on_exit); + DBG_PRINT(" - exit_ctls.clear_ia32_bndcfgs: %d\n", exit_ctls.clear_ia32_bndcfgs); + DBG_PRINT(" - exit_ctls.conceal_vmx_from_pt: %d\n", exit_ctls.conceal_vmx_from_pt); + DBG_PRINT(" - exit_ctls.host_address_space_size: %d\n", exit_ctls.host_address_space_size); + DBG_PRINT(" - exit_ctls.load_ia32_efer: %d\n", exit_ctls.load_ia32_efer); + DBG_PRINT(" - exit_ctls.load_ia32_pat: %d\n", exit_ctls.load_ia32_pat); + DBG_PRINT(" - exit_ctls.load_ia32_perf_global_ctrl: %d\n", exit_ctls.load_ia32_perf_global_ctrl); + DBG_PRINT(" - exit_ctls.save_debug_controls: %d\n", exit_ctls.save_debug_controls); + DBG_PRINT(" - exit_ctls.save_ia32_efer: %d\n", exit_ctls.save_ia32_efer); + DBG_PRINT(" - exit_ctls.save_ia32_pat: %d\n", exit_ctls.save_ia32_pat); + DBG_PRINT(" - exit_ctls.save_vmx_preemption_timer_value: %d\n", exit_ctls.save_vmx_preemption_timer_value); + DBG_PRINT(" - exit_ctls.flags: 0x%x\n", exit_ctls.flags); + DBG_PRINT(" - IA32_VMX_EXIT_CTLS high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_EXIT_CTLS low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); } msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2); + procbased_ctls2.enable_rdtscp = true; + procbased_ctls2.enable_xsaves = true; // although my xeons dont support xsave... other cpus do! + procbased_ctls2.conceal_vmx_from_pt = true; // although my xeons dont support processor tracing... other cpus do! procbased_ctls2.flags &= msr_fix_value.allowed_1_settings; procbased_ctls2.flags |= msr_fix_value.allowed_0_settings; - procbased_ctls2.enable_rdtscp = true; - procbased_ctls2.enable_xsaves = true; - procbased_ctls2.conceal_vmx_from_pt = true; __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags); + + DBG_PRINT("============================== secondary processor based vm-exec controls ==============================\n"); + DBG_PRINT(" - procbased_ctls2.apic_register_virtualization: %d\n", procbased_ctls2.apic_register_virtualization); + DBG_PRINT(" - procbased_ctls2.conceal_vmx_from_pt: %d\n", procbased_ctls2.conceal_vmx_from_pt); + DBG_PRINT(" - procbased_ctls2.descriptor_table_exiting: %d\n", procbased_ctls2.descriptor_table_exiting); + DBG_PRINT(" - procbased_ctls2.enable_encls_exiting: %d\n", procbased_ctls2.enable_encls_exiting); + DBG_PRINT(" - procbased_ctls2.enable_ept: %d\n", procbased_ctls2.enable_ept); + DBG_PRINT(" - procbased_ctls2.enable_invpcid: %d\n", procbased_ctls2.enable_invpcid); + DBG_PRINT(" - procbased_ctls2.enable_pml: %d\n", procbased_ctls2.enable_pml); + DBG_PRINT(" - procbased_ctls2.enable_rdtscp: %d\n", procbased_ctls2.enable_rdtscp); + DBG_PRINT(" - procbased_ctls2.enable_vm_functions: %d\n", procbased_ctls2.enable_vm_functions); + DBG_PRINT(" - procbased_ctls2.enable_vpid: %d\n", procbased_ctls2.enable_vpid); + DBG_PRINT(" - procbased_ctls2.enable_xsaves: %d\n", procbased_ctls2.enable_xsaves); + DBG_PRINT(" - procbased_ctls2.ept_violation: %d\n", procbased_ctls2.ept_violation); + DBG_PRINT(" - procbased_ctls2.mode_based_execute_control_for_ept: %d\n", procbased_ctls2.mode_based_execute_control_for_ept); + DBG_PRINT(" - procbased_ctls2.pause_loop_exiting: %d\n", procbased_ctls2.pause_loop_exiting); + DBG_PRINT(" - procbased_ctls2.rdrand_exiting: %d\n", procbased_ctls2.rdrand_exiting); + DBG_PRINT(" - procbased_ctls2.rdseed_exiting: %d\n", procbased_ctls2.rdseed_exiting); + DBG_PRINT(" - procbased_ctls2.unrestricted_guest: %d\n", procbased_ctls2.unrestricted_guest); + DBG_PRINT(" - procbased_ctls2.use_tsc_scaling: %d\n", procbased_ctls2.use_tsc_scaling); + DBG_PRINT(" - procbased_ctls2.virtualize_apic_accesses: %d\n", procbased_ctls2.virtualize_apic_accesses); + DBG_PRINT(" - procbased_ctls2.virtualize_x2apic_mode: %d\n", procbased_ctls2.virtualize_x2apic_mode); + DBG_PRINT(" - procbased_ctls2.virtual_interrupt_delivery: %d\n", procbased_ctls2.virtual_interrupt_delivery); + DBG_PRINT(" - procbased_ctls2.vmcs_shadowing: %d\n", procbased_ctls2.vmcs_shadowing); + DBG_PRINT(" - procbased_ctls2.wbinvd_exiting: %d\n", procbased_ctls2.wbinvd_exiting); + DBG_PRINT(" - procbased_ctls2.flags: 0x%x\n", procbased_ctls2.flags); + DBG_PRINT(" - IA32_VMX_PROCBASED_CTLS2 high bits mask: 0x%x\n", msr_fix_value.allowed_1_settings); + DBG_PRINT(" - IA32_VMX_PROCBASED_CTLS2 low bits mask: 0x%x\n", msr_fix_value.allowed_0_settings); } } \ No newline at end of file diff --git a/vmxexit_handler.asm b/vmxexit_handler.asm index d5602d7..ee4158d 100644 --- a/vmxexit_handler.asm +++ b/vmxexit_handler.asm @@ -10,7 +10,6 @@ vmxexit_handler proc push rsi push rdi push rbp - push rbp ; gotta keep the stack aligned... push r8 push r9 push r10 @@ -69,7 +68,6 @@ vmxexit_handler proc pop r10 pop r9 pop r8 - pop rbp ; gotta keep the stack aligned... pop rbp pop rdi pop rsi diff --git a/vmxon.cpp b/vmxon.cpp index cd7b364..6a25880 100644 --- a/vmxon.cpp +++ b/vmxon.cpp @@ -72,11 +72,17 @@ namespace vmxon reinterpret_cast( ExAllocatePool(NonPagedPool, sizeof hv::vcpu_ctx)); + // allocate host stack... vmx_ctx->vcpus[idx]->host_stack = reinterpret_cast( ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES)); + // zero host stack... + RtlZeroMemory(reinterpret_cast( + vmx_ctx->vcpus[idx]->host_stack), PAGE_SIZE * HOST_STACK_PAGES); + + // setup VMCS and VMXON region... create_vmxon_region(vmx_ctx->vcpus[idx]); create_vmcs(vmx_ctx->vcpus[idx]); @@ -85,6 +91,7 @@ namespace vmxon DBG_PRINT(" - vmxon region (physical): 0x%p\n", vmx_ctx->vcpus[idx]->vmxon_phys); DBG_PRINT(" - vmcs (virtual): 0x%p\n", vmx_ctx->vcpus[idx]->vmcs); DBG_PRINT(" - vmcs (physical): 0x%p\n", vmx_ctx->vcpus[idx]->vmcs_phys); + DBG_PRINT(" - host stack: 0x%p\n", vmx_ctx->vcpus[idx]->host_stack); } } @@ -95,7 +102,7 @@ namespace vmxon hv::cr0_t cr0 = { 0 }; hv::cr4_t cr4 = { 0 }; - // should check to see if this is locked or not... + // TODO: should check to see if this is locked or not... feature_msr.control = __readmsr(IA32_FEATURE_CONTROL); feature_msr.bits.vmxon_outside_smx = true; feature_msr.bits.lock = true; @@ -117,14 +124,17 @@ namespace vmxon cr4.flags &= cr_fixed.split.low; __writecr4(cr4.flags); + // enable vmx instructions on this core... cr4.flags = __readcr4(); cr4.vmx_enable = true; __writecr4(cr4.flags); - DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber()); - DBG_PRINT(" - vmxon result (0 == success): %d\n", + const auto vmxon_result = __vmx_on((unsigned long long*) &vmxon::g_vmx_ctx->vcpus[ - KeGetCurrentProcessorNumber()]->vmxon_phys)); + KeGetCurrentProcessorNumber()]->vmxon_phys); + + DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber()); + DBG_PRINT(" - vmxon result (0 == success): %d\n", vmxon_result); } } \ No newline at end of file