diff --git a/binaries/bluepill.sys b/binaries/bluepill.sys deleted file mode 100644 index c9fc14a..0000000 Binary files a/binaries/bluepill.sys and /dev/null differ diff --git a/binaries/demo.exe b/binaries/demo.exe deleted file mode 100644 index effba91..0000000 Binary files a/binaries/demo.exe and /dev/null differ diff --git a/exit_handler.cpp b/exit_handler.cpp index 10028da..07b89fe 100644 --- a/exit_handler.cpp +++ b/exit_handler.cpp @@ -22,6 +22,13 @@ auto set_command(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_co *reinterpret_cast(virt_map) = vmcall_command; } +auto vmresume_failure() -> void +{ + size_t value; + __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &value); + __debugbreak(); +} + auto exit_handler(hv::pguest_registers regs) -> void { u64 exit_reason; @@ -50,31 +57,19 @@ auto exit_handler(hv::pguest_registers regs) -> void __vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL); ia32_vmx_procbased_ctls_register procbased_ctls; - ia32_vmx_pinbased_ctls_register pinbased_ctls; - __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); - __vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags); procbased_ctls.nmi_window_exiting = false; - pinbased_ctls.virtual_nmi = false; - __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); - __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); return; // dont advance rip... } case VMX_EXIT_REASON_EXCEPTION_OR_NMI: { ia32_vmx_procbased_ctls_register procbased_ctls; - ia32_vmx_pinbased_ctls_register pinbased_ctls; - __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); - __vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags); procbased_ctls.nmi_window_exiting = true; - pinbased_ctls.virtual_nmi = true; - __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); - __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); return; // dont advance rip... } case VMX_EXIT_REASON_EXECUTE_XSETBV: diff --git a/ia32.hpp b/ia32.hpp index 10ca493..f576d1d 100644 --- a/ia32.hpp +++ b/ia32.hpp @@ -10444,6 +10444,7 @@ typedef union #define IA32_VMX_EXIT_CTLS 0x00000483 typedef union { + uint64_t flags; struct { uint64_t reserved1 : 2; @@ -10581,8 +10582,6 @@ typedef union #define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01) uint64_t reserved6 : 39; }; - - uint64_t flags; } ia32_vmx_exit_ctls_register; diff --git a/idt.cpp b/idt.cpp index d818b95..b65b354 100644 --- a/idt.cpp +++ b/idt.cpp @@ -96,16 +96,10 @@ auto seh_handler(hv::pidt_regs_t regs) -> void auto nmi_handler(hv::pidt_regs_t regs) -> void { ia32_vmx_procbased_ctls_register procbased_ctls; - ia32_vmx_pinbased_ctls_register pinbased_ctls; - __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); - __vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags); procbased_ctls.nmi_window_exiting = true; - pinbased_ctls.virtual_nmi = true; - __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); - __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); } namespace idt diff --git a/idt.hpp b/idt.hpp index 0efdaaf..81d515c 100644 --- a/idt.hpp +++ b/idt.hpp @@ -16,9 +16,8 @@ extern "C" void seh_handler_ecode(hv::pidt_regs_ecode_t regs); namespace idt { - __declspec(allocate(".idt")) - inline hv::idt_entry_t table[256]; - enum ist_idx : u8 { nmi = 3, de = 4, pf = 5, gp = 6}; + __declspec(allocate(".idt")) inline hv::idt_entry_t table[256]; + enum ist_idx : u8 { nmi = 3, de = 4, pf = 5, gp = 6 }; inline void* image_base = nullptr; // used for SEH... auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t; diff --git a/mm.hpp b/mm.hpp index d06c309..8455daf 100644 --- a/mm.hpp +++ b/mm.hpp @@ -129,8 +129,7 @@ namespace mm inline const ppml4e vmxroot_pml4 = reinterpret_cast(0x7fbfdfeff000); // make sure this is 4kb aligned or you are going to be meeting allah... - __declspec(allocate(".pml4")) - inline pml4e pml4[512]; + __declspec(allocate(".pml4")) inline pml4e pml4[512]; // translate vmxroot address's... auto translate(virt_addr_t virt_addr) -> u64; diff --git a/vmcs.cpp b/vmcs.cpp index 60569ac..139f385 100644 --- a/vmcs.cpp +++ b/vmcs.cpp @@ -144,44 +144,45 @@ namespace vmcs 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; + 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{ __readmsr(IA32_VMX_BASIC) }; + + pinbased_ctls.nmi_exiting = true; + pinbased_ctls.virtual_nmi = true; + + procbased_ctls.activate_secondary_controls = true; + exit_ctls.host_address_space_size = true; + + entry_ctls.ia32e_mode_guest = true; + entry_ctls.conceal_vmx_from_pt = true; + + procbased_ctls2.enable_rdtscp = true; + procbased_ctls2.enable_xsaves = true; + procbased_ctls2.conceal_vmx_from_pt = true; if (vmx_basic.vmx_controls) { msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS); - pinbased_ctls.nmi_exiting = true; 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.activate_secondary_controls = true; procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS); - 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); 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; __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); @@ -189,36 +190,27 @@ namespace vmcs else { msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS); - pinbased_ctls.nmi_exiting = true; 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.activate_secondary_controls = true; procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS); - 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); msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS); - 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); } msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2); - procbased_ctls2.enable_rdtscp = true; - procbased_ctls2.enable_xsaves = true; - procbased_ctls2.conceal_vmx_from_pt = true; procbased_ctls2.flags &= msr_fix_value.allowed_1_settings; procbased_ctls2.flags |= msr_fix_value.allowed_0_settings; __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags); diff --git a/vmxexit_handler.asm b/vmxexit_handler.asm index 6fb97ec..1ab295e 100644 --- a/vmxexit_handler.asm +++ b/vmxexit_handler.asm @@ -1,4 +1,5 @@ extern exit_handler : proc +extern vmresume_failure : proc .code vmxlaunch_processor proc @@ -99,5 +100,7 @@ vmxexit_handler proc pop rax vmresume + call vmresume_failure + hlt vmxexit_handler endp end \ No newline at end of file diff --git a/vmxexit_handler.h b/vmxexit_handler.h index 7dc8978..b404baa 100644 --- a/vmxexit_handler.h +++ b/vmxexit_handler.h @@ -60,6 +60,7 @@ typedef struct _vmcall_command_t } vmcall_command_t, * pvmcall_command_t; extern "C" auto vmxexit_handler() -> void; +extern "C" auto vmresume_failure() -> void; extern "C" auto exit_handler(hv::pguest_registers regs) -> void; auto get_command(u64 dirbase, u64 command_ptr) -> vmcall_command_t; diff --git a/vmxlaunch.cpp b/vmxlaunch.cpp index 52f22f3..fc2973d 100644 --- a/vmxlaunch.cpp +++ b/vmxlaunch.cpp @@ -33,10 +33,15 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void reinterpret_cast(ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES); - vcpu->gdt[segment_selector{ readtr() }.idx].base_address_upper = tss.upper; - vcpu->gdt[segment_selector{ readtr() }.idx].base_address_high = tss.high; - vcpu->gdt[segment_selector{ readtr() }.idx].base_address_middle = tss.middle; - vcpu->gdt[segment_selector{ readtr() }.idx].base_address_low = tss.low; + vcpu->tss.interrupt_stack_table[idt::ist_idx::nmi] = + reinterpret_cast(ExAllocatePool(NonPagedPool, + PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES); + + const auto tr_idx = segment_selector{ readtr() }.idx; + vcpu->gdt[tr_idx].base_address_upper = tss.upper; + vcpu->gdt[tr_idx].base_address_high = tss.high; + vcpu->gdt[tr_idx].base_address_middle = tss.middle; + vcpu->gdt[tr_idx].base_address_low = tss.low; vmcs::setup_host(&vmxexit_handler, vcpu->host_stack, cr3_value, (u64)vcpu->gdt); @@ -48,9 +53,6 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void auto vmxlaunch::launch() -> void { const auto vmlaunch_result = vmxlaunch_processor(); - DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber()); - DBG_PRINT(" - vmxlaunch result: 0x%x\n", vmlaunch_result); - if (vmlaunch_result != VMX_LAUNCH_SUCCESS) { u64 vmxerror;