diff --git a/bluepill.vcxproj b/bluepill.vcxproj index 9555dbd..e62f178 100644 --- a/bluepill.vcxproj +++ b/bluepill.vcxproj @@ -56,6 +56,8 @@ + + @@ -63,6 +65,7 @@ + diff --git a/bluepill.vcxproj.filters b/bluepill.vcxproj.filters index 816cf7c..85c041b 100644 --- a/bluepill.vcxproj.filters +++ b/bluepill.vcxproj.filters @@ -23,6 +23,12 @@ Source Files + + Source Files + + + Source Files + @@ -43,6 +49,9 @@ Header Files + + Header Files + diff --git a/entry.cpp b/entry.cpp index 44698fd..564ad15 100644 --- a/entry.cpp +++ b/entry.cpp @@ -53,7 +53,7 @@ auto driver_entry( KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL); // vmxlaunch for all cores... - // KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL); + KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL); driver_object->DriverUnload = &driver_unload; return STATUS_SUCCESS; diff --git a/exit_handler.cpp b/exit_handler.cpp index a3d9ebc..40ac66d 100644 --- a/exit_handler.cpp +++ b/exit_handler.cpp @@ -19,6 +19,6 @@ auto exit_handler(hv::pguest_registers regs) -> void case VMX_EXIT_REASON_EXECUTE_VMCLEAR: case VMX_EXIT_REASON_EXECUTE_RDTSC: default: - __vmx_off(); + break; } } \ No newline at end of file diff --git a/hv_types.hpp b/hv_types.hpp index 21e7e09..3fb6156 100644 --- a/hv_types.hpp +++ b/hv_types.hpp @@ -14,6 +14,11 @@ using s16 = short; using s32 = int; using s64 = long long; +// didnt find it in intrin.h... ? +extern "C" void _sgdt(void*); +#pragma intrinsic(_sgdt); + + #define DBG_PRINT(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[hv]" __VA_ARGS__) #define HOST_STACK_PAGES 6 @@ -378,4 +383,11 @@ namespace hv u32 vcpu_num; pvcpu_ctx* vcpus; } vmx_ctx, *pvmx_ctx; + + typedef struct _segment_info_ctx + { + vmx_segment_access_rights rights; + u64 limit; + u64 base_addr; + } segment_info_ctx, *psegment_info_ctx; } \ No newline at end of file diff --git a/ia32.hpp b/ia32.hpp index 39d6427..80c01f6 100644 --- a/ia32.hpp +++ b/ia32.hpp @@ -9936,6 +9936,7 @@ typedef union #define IA32_VMX_BASIC 0x00000480 typedef union { + uint64_t flags; struct { /** @@ -10054,8 +10055,6 @@ typedef union #define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01) uint64_t reserved2 : 8; }; - - uint64_t flags; } ia32_vmx_basic_register; @@ -10069,6 +10068,7 @@ typedef union #define IA32_VMX_PINBASED_CTLS 0x00000481 typedef union { + uint64_t flags; struct { /** @@ -10144,8 +10144,6 @@ typedef union #define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01) uint64_t reserved3 : 56; }; - - uint64_t flags; } ia32_vmx_pinbased_ctls_register; @@ -15458,7 +15456,7 @@ typedef struct * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. */ uint32_t base_address_middle : 8; -#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 +#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 16 #define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF #define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF #define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) @@ -15611,6 +15609,7 @@ typedef struct * Base address field (32:63); see description of $BASE_LOW for more details. */ uint32_t base_address_upper; +#define SEGMENT__BASE_ADDRESS_SHIFT 32 /** * Base address field (32:63); see description of $BASE_LOW for more details. @@ -15844,6 +15843,8 @@ typedef struct */ typedef union { + uint16_t flags; + struct { /** @@ -15879,8 +15880,6 @@ typedef union #define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF #define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF) }; - - uint16_t flags; } segment_selector; /** diff --git a/segment.cpp b/segment.cpp new file mode 100644 index 0000000..b991148 --- /dev/null +++ b/segment.cpp @@ -0,0 +1,38 @@ +#include "segment_intrin.h" + +namespace segment +{ + auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights + { + vmx_segment_access_rights result; + result.granularity = segment_descriptor->granularity; + result.type = segment_descriptor->type; + result.descriptor_type = segment_descriptor->descriptor_type; + result.present = segment_descriptor->present; + result.long_mode = segment_descriptor->long_mode; + result.available_bit = segment_descriptor->system; + result.default_big = segment_descriptor->default_big; + return result; + } + + auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx + { + hv::segment_info_ctx segment_info; + const auto segment_descriptor = + reinterpret_cast( + gdt_value.base_address + (segment_selector.index << SEGMENT_SELECTOR_INDEX_BIT)); + + 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) | + (segment_descriptor->base_address_low)); + + segment_info.base_addr &= 0xFFFFFFFF; + if (!segment_descriptor->descriptor_type) + segment_info.base_addr |= ((u64)segment_descriptor->base_address_upper << SEGMENT__BASE_ADDRESS_SHIFT); + + return segment_info; + } +} \ No newline at end of file diff --git a/segment_intrin.asm b/segment_intrin.asm index 9719f2b..8742a4c 100644 --- a/segment_intrin.asm +++ b/segment_intrin.asm @@ -28,4 +28,14 @@ readcs proc mov rax, cs ret readcs endp + +readtr proc + str ax + ret +readtr endp + +readldt proc + sldt ax + ret +readldt endp end \ No newline at end of file diff --git a/segment_intrin.h b/segment_intrin.h index 3e30b52..49c07ca 100644 --- a/segment_intrin.h +++ b/segment_intrin.h @@ -1,9 +1,17 @@ #pragma once #include "hv_types.hpp" -extern "C" u64 readfs(void); -extern "C" u64 readgs(void); -extern "C" u64 reades(void); -extern "C" u64 readds(void); -extern "C" u64 readss(void); -extern "C" u64 readcs(void); \ No newline at end of file +extern "C" u16 readfs(void); +extern "C" u16 readgs(void); +extern "C" u16 reades(void); +extern "C" u16 readds(void); +extern "C" u16 readss(void); +extern "C" u16 readcs(void); +extern "C" u16 readtr(void); +extern "C" u16 readldt(void); + +namespace segment +{ + auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx; + auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights; +} \ No newline at end of file diff --git a/vmcs.cpp b/vmcs.cpp new file mode 100644 index 0000000..8e261d7 --- /dev/null +++ b/vmcs.cpp @@ -0,0 +1,216 @@ +#include "vmcs.hpp" + +namespace vmcs +{ + auto setup_host(void* host_rip, u64 host_rsp) -> void + { + segment_descriptor_register_64 gdt_value; + segment_descriptor_register_64 idt_value; + + __sidt(&idt_value); + _sgdt(&gdt_value); + + __vmx_vmwrite(VMCS_HOST_CR0, __readcr0()); + __vmx_vmwrite(VMCS_HOST_CR3, __readcr3()); + __vmx_vmwrite(VMCS_HOST_CR4, __readcr4()); + + __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)); + __vmx_vmwrite(VMCS_HOST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); + + __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()); + + __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); + __vmx_vmwrite(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE)); + } + + auto setup_guest() -> void + { + segment_descriptor_register_64 gdt_value; + segment_descriptor_register_64 idt_value; + + __sidt(&idt_value); + _sgdt(&gdt_value); + + __vmx_vmwrite(VMCS_GUEST_CR0, __readcr0()); + __vmx_vmwrite(VMCS_GUEST_CR3, __readcr3()); + __vmx_vmwrite(VMCS_GUEST_CR4, __readcr4()); + + __vmx_vmwrite(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL); + __vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL)); + + __vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL)); + __vmx_vmwrite(VMCS_GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); + __vmx_vmwrite(VMCS_GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); + __vmx_vmwrite(VMCS_GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); + + __vmx_vmwrite(VMCS_GUEST_GDTR_BASE, gdt_value.base_address); + __vmx_vmwrite(VMCS_GUEST_GDTR_LIMIT, gdt_value.limit); + + __vmx_vmwrite(VMCS_GUEST_IDTR_BASE, idt_value.base_address); + __vmx_vmwrite(VMCS_GUEST_IDTR_LIMIT, idt_value.limit); + + __vmx_vmwrite(VMCS_GUEST_RFLAGS, __readeflags()); + __vmx_vmwrite(VMCS_GUEST_DR7, __readdr(7)); + + const auto [es_rights, es_limit, es_base] = + segment::get_info(gdt_value, segment_selector{ reades() }); + + __vmx_vmwrite(VMCS_GUEST_ES_BASE, es_base); + __vmx_vmwrite(VMCS_GUEST_ES_LIMIT, es_limit); + __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades()); + __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, es_rights.flags); + + const auto [ds_rights, ds_limit, ds_base] = + segment::get_info(gdt_value, segment_selector{ readds() }); + + __vmx_vmwrite(VMCS_GUEST_DS_BASE, ds_base); + __vmx_vmwrite(VMCS_GUEST_DS_LIMIT, ds_limit); + __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds()); + __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, ds_rights.flags); + + const auto [fs_rights, fs_limit, fs_base] = + segment::get_info(gdt_value, segment_selector{ readfs() }); + + __vmx_vmwrite(VMCS_GUEST_FS_BASE, fs_base); + __vmx_vmwrite(VMCS_GUEST_FS_LIMIT, fs_limit); + __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, readfs()); + __vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, fs_rights.flags); + + const auto [gs_rights, gs_limit, gs_base] = + segment::get_info(gdt_value, segment_selector{ readgs() }); + + __vmx_vmwrite(VMCS_GUEST_GS_BASE, gs_base); + __vmx_vmwrite(VMCS_GUEST_GS_LIMIT, gs_limit); + __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, readgs()); + __vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, gs_rights.flags); + + const auto [ss_rights, ss_limit, ss_base] = + segment::get_info(gdt_value, segment_selector{ readss() }); + + __vmx_vmwrite(VMCS_GUEST_SS_BASE, ss_base); + __vmx_vmwrite(VMCS_GUEST_SS_LIMIT, ss_limit); + __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, readss()); + __vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, ss_rights.flags); + + const auto [cs_rights, cs_limit, cs_base] = + segment::get_info(gdt_value, segment_selector{ readcs() }); + + __vmx_vmwrite(VMCS_GUEST_CS_BASE, cs_base); + __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, cs_limit); + __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs()); + __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, cs_rights.flags); + + const auto [tr_rights, tr_limit, tr_base] = + segment::get_info(gdt_value, segment_selector{ readtr() }); + + __vmx_vmwrite(VMCS_GUEST_TR_BASE, tr_base); + __vmx_vmwrite(VMCS_GUEST_TR_LIMIT, tr_limit); + __vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, readtr()); + __vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, tr_rights.flags); + + const auto [ldt_rights, ldt_limit, ldt_base] = + segment::get_info(gdt_value, segment_selector{ readldt() }); + + __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, ldt_base); + __vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, ldt_limit); + __vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, readldt()); + __vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, ldt_rights.flags); + + __vmx_vmwrite(VMCS_GUEST_GS_BASE, __readmsr(IA32_GS_BASE)); + __vmx_vmwrite(VMCS_GUEST_FS_BASE, __readmsr(IA32_FS_BASE)); + } + + auto setup_controls() -> void + { + ia32_vmx_true_ctls_register msr_fix_value; + ia32_vmx_pinbased_ctls_register pinbased_ctls; + ia32_vmx_procbased_ctls_register procbased_ctls; + ia32_vmx_procbased_ctls2_register procbased_ctls2; + ia32_vmx_entry_ctls_register entry_ctls; + ia32_vmx_exit_ctls_register exit_ctls; + ia32_vmx_basic_register vmx_basic; + + vmx_basic.flags = __readmsr(IA32_VMX_BASIC); + pinbased_ctls.flags = NULL; + procbased_ctls.flags = NULL; + procbased_ctls2.flags = NULL; + entry_ctls.flags = NULL; + exit_ctls.flags = NULL; + + if (vmx_basic.vmx_controls) + { + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS); + pinbased_ctls.flags &= msr_fix_value.allowed_1_settings; + pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; + __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); + + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS); + 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); + + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_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; + __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); + + msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_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; + __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); + } + else + { + msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS); + pinbased_ctls.flags &= msr_fix_value.allowed_1_settings; + pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; + __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); + + msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS); + 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); + + 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; + __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); + + 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; + __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); + } + + msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2); + 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); + } +} \ No newline at end of file diff --git a/vmcs.hpp b/vmcs.hpp new file mode 100644 index 0000000..b54014c --- /dev/null +++ b/vmcs.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "hv_types.hpp" +#include "segment_intrin.h" +#include "vmxexit_handler.h" + +namespace vmcs +{ + auto setup_host(void* host_rip, u64 host_rsp) -> void; + auto setup_guest() -> void; + auto setup_controls() -> void; +} \ No newline at end of file diff --git a/vmxexit_handler.asm b/vmxexit_handler.asm index 1bd1a7f..d5602d7 100644 --- a/vmxexit_handler.asm +++ b/vmxexit_handler.asm @@ -2,6 +2,7 @@ extern exit_handler : proc .code vmxexit_handler proc + int 3 ; see if vmexit get called... push rax push rbx push rcx @@ -38,9 +39,9 @@ vmxexit_handler proc movaps [rsp + 0F0h], xmm15 mov rcx, rsp - sub rsp, 28h ; shadow space or some shit MSVC does it so i do it... + sub rsp, 20h call exit_handler - add rsp, 28h + add rsp, 20h movaps xmm0, [rsp] movaps xmm1, [rsp + 010h] @@ -76,6 +77,6 @@ vmxexit_handler proc pop rcx pop rax - vmresume ; resume guest execution... + vmresume vmxexit_handler endp end \ No newline at end of file diff --git a/vmxlaunch.cpp b/vmxlaunch.cpp index 03399af..c1c11e9 100644 --- a/vmxlaunch.cpp +++ b/vmxlaunch.cpp @@ -2,104 +2,28 @@ auto vmxlaunch::init_vmcs() -> void { - __vmx_vmclear(&vmxon::g_vmx_ctx->vcpus[ - KeGetCurrentProcessorNumber()]->vmcs_phys); - - __vmx_vmptrld(&vmxon::g_vmx_ctx->vcpus[ - KeGetCurrentProcessorNumber()]->vmcs_phys); - - // setup host VMCS fields... - __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, readcs() & 0xF8); - __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, readds() & 0xF8); - __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, reades() & 0xF8); - __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, readgs() & 0xF8); - __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, readss() & 0xF8); - __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, readfs() & 0xF8); - - // TODO IDT, TR, GDT (base and limit for each segment register), and LDT... - - __vmx_vmwrite(VMCS_HOST_CR0, __readcr0()); - __vmx_vmwrite(VMCS_HOST_CR3, __readcr3()); - __vmx_vmwrite(VMCS_HOST_CR4, __readcr4()); - - __vmx_vmwrite(VMCS_HOST_RIP, - reinterpret_cast(&::vmxexit_handler)); - - __vmx_vmwrite(VMCS_HOST_RSP, + const auto vcpu = vmxon::g_vmx_ctx->vcpus[ - KeGetCurrentProcessorNumber()]->host_stack); - - // setup guest VMCS fields... - __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs()); - __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds()); - __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades()); - __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, readgs()); - __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, readss()); - __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, readfs()); - __vmx_vmwrite(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL); - - ia32_vmx_exit_ctls_register exit_ctls; - exit_ctls.save_ia32_efer = true; - exit_ctls.conceal_vmx_from_pt = false; - exit_ctls.host_address_space_size = true; - exit_ctls.load_ia32_efer = false; // TODO readup on this... - exit_ctls.load_ia32_pat = true; // TODO ask daax about this... - exit_ctls.save_debug_controls = true; - exit_ctls.load_ia32_perf_global_ctrl = true; - exit_ctls.save_vmx_preemption_timer_value = true; - __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); - - ia32_vmx_procbased_ctls2_register procbased_ctls; - procbased_ctls.apic_register_virtualization = false; - procbased_ctls.conceal_vmx_from_pt = true; - procbased_ctls.descriptor_table_exiting = false; - procbased_ctls.enable_encls_exiting = false; - procbased_ctls.enable_ept = false; - procbased_ctls.enable_invpcid = false; - procbased_ctls.enable_pml = false; - procbased_ctls.enable_rdtscp = false; // might need to enable this... - procbased_ctls.enable_vm_functions = false; - procbased_ctls.enable_vpid = true; // TODO read up on this... - procbased_ctls.enable_xsaves = false; // TODO not sure if i need this enabled... - procbased_ctls.ept_violation = false; - procbased_ctls.mode_based_execute_control_for_ept = false; - procbased_ctls.pause_loop_exiting = false; - procbased_ctls.rdrand_exiting = false; - procbased_ctls.rdseed_exiting = false; - procbased_ctls.unrestricted_guest = false; // TODO read up on this... - procbased_ctls.use_tsc_scaling = true; // TODO read up on this... - procbased_ctls.virtualize_apic_accesses = false; - procbased_ctls.virtualize_x2apic_mode = false; - procbased_ctls.virtual_interrupt_delivery = false; - procbased_ctls.vmcs_shadowing = false; - procbased_ctls.wbinvd_exiting = false; //TODO not sure if i need this to be true... - __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); + KeGetCurrentProcessorNumber()]; - ia32_vmx_pinbased_ctls_register pinbased_ctls; - pinbased_ctls.activate_vmx_preemption_timer = false; - pinbased_ctls.external_interrupt_exiting = false; - pinbased_ctls.nmi_exiting = false; - pinbased_ctls.process_posted_interrupts = false; - pinbased_ctls.virtual_nmi = false; - __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); + __vmx_vmclear(&vcpu->vmcs_phys); + __vmx_vmptrld(&vcpu->vmcs_phys); - ia32_vmx_entry_ctls_register entry_ctls; - entry_ctls.conceal_vmx_from_pt = true; - entry_ctls.deactivate_dual_monitor_treatment = false; - entry_ctls.entry_to_smm = false; // TODO ask daax about this... - entry_ctls.ia32e_mode_guest = true; - entry_ctls.load_cet_state = true; // TODO ask daax... - entry_ctls.load_debug_controls = true; // TODO ask daax about this... - entry_ctls.load_ia32_bndcfgs = false; // TODO ask daax about this... - entry_ctls.load_ia32_efer = true; // TODO ask daax about this... - entry_ctls.load_ia32_pat = true; - entry_ctls.load_ia32_perf_global_ctrl = true; // TODO ask daax... - entry_ctls.load_ia32_rtit_ctl = true; // TODO ask daax... - __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); + vmcs::setup_host(&vmxexit_handler, vcpu->host_stack); + vmcs::setup_guest(); + vmcs::setup_controls(); } auto vmxlaunch::launch() -> void { + const auto vmlaunch_result = __vmx_vmlaunch(); DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber()); - DBG_PRINT(" - vmxlaunch result (0 == success): %d\n", __vmx_vmlaunch()); + DBG_PRINT(" - vmxlaunch result (0 == success): %d\n", vmlaunch_result); + + if (vmlaunch_result) + { + u64 vmxerror; + __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &vmxerror); + DBG_PRINT("vmxerror: %d\n", vmxerror); + } } \ No newline at end of file diff --git a/vmxlaunch.hpp b/vmxlaunch.hpp index 1ad673e..6095d35 100644 --- a/vmxlaunch.hpp +++ b/vmxlaunch.hpp @@ -2,6 +2,7 @@ #include "segment_intrin.h" #include "vmxexit_handler.h" #include "vmxon.hpp" +#include "vmcs.hpp" namespace vmxlaunch { diff --git a/vmxon.cpp b/vmxon.cpp index d10f06a..cd7b364 100644 --- a/vmxon.cpp +++ b/vmxon.cpp @@ -95,11 +95,14 @@ namespace vmxon hv::cr0_t cr0 = { 0 }; hv::cr4_t cr4 = { 0 }; + // 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; __writemsr(IA32_FEATURE_CONTROL, feature_msr.control); + // not sure if did this in the wrong order, i think maybe cr4.vmx_enable bit needs + // to be flipped before i fixed cr0 and cr4 registers? TODO: read up on dat sheet... cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED0); cr0.flags = __readcr0(); cr0.flags |= cr_fixed.split.low; @@ -118,17 +121,10 @@ namespace vmxon cr4.vmx_enable = true; __writecr4(cr4.flags); - __try - { - DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber()); - + DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber()); + DBG_PRINT(" - vmxon result (0 == success): %d\n", __vmx_on((unsigned long long*) &vmxon::g_vmx_ctx->vcpus[ - KeGetCurrentProcessorNumber()]->vmxon_phys); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - DBG_PRINT("vmxon failed for processor: %d\n", KeGetCurrentProcessorNumber()); - } + KeGetCurrentProcessorNumber()]->vmxon_phys)); } } \ No newline at end of file