diff --git a/bluepill.vcxproj b/bluepill.vcxproj index cde56dc..c42e5c3 100644 --- a/bluepill.vcxproj +++ b/bluepill.vcxproj @@ -61,7 +61,7 @@ false - driver_entry + drv_entry stdcpp17 @@ -71,7 +71,7 @@ false - driver_entry + drv_entry stdcpp17 diff --git a/bluepill.vcxproj.filters b/bluepill.vcxproj.filters index ca468fc..a1d371b 100644 --- a/bluepill.vcxproj.filters +++ b/bluepill.vcxproj.filters @@ -29,15 +29,15 @@ Source Files - - Source Files - Source Files Source Files + + Source Files + @@ -70,10 +70,10 @@ Header Files - + Header Files - + Header Files diff --git a/demo/main.cpp b/demo/main.cpp index 44eb2c7..3a8f75d 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "hypercall.h" int main() diff --git a/drv_entry.cpp b/drv_entry.cpp index 5416da2..b5e1039 100644 --- a/drv_entry.cpp +++ b/drv_entry.cpp @@ -1,18 +1,7 @@ #include "vmxlaunch.hpp" #include "idt.hpp" -auto driver_unload( - PDRIVER_OBJECT driver_object -) -> void -{ - // no unloading this hv... restart... - __debugbreak(); -} - -auto driver_entry( - PDRIVER_OBJECT driver_object, - PUNICODE_STRING registry_path -) -> NTSTATUS +auto drv_entry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path) -> NTSTATUS { vmxon::g_vmx_ctx = reinterpret_cast( @@ -58,9 +47,8 @@ auto driver_entry( memcpy(idt::table, (void*)idt_value.base_address, idt_value.limit); // change gp, pf, and de to vmxroot handlers... - idt::table[general_protection] = create_entry(hv::idt_addr_t{ __gp_handler }, idt::ist_idx::gp); - idt::table[page_fault] = create_entry(hv::idt_addr_t{ __pf_handler }, idt::ist_idx::pf); - idt::table[divide_error] = create_entry(hv::idt_addr_t{ __de_handler }, idt::ist_idx::de); + idt::table[general_protection] = idt::create_entry(hv::idt_addr_t{ __gp_handler }, idt::ist_idx::gp); + idt::table[page_fault] = idt::create_entry(hv::idt_addr_t{ __pf_handler }, idt::ist_idx::pf); // used for SEH in vmxroot fault handler... idt::image_base = driver_object->DriverStart; @@ -73,7 +61,5 @@ auto driver_entry( // vmxlaunch for all cores... KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL); - - driver_object->DriverUnload = &driver_unload; return STATUS_SUCCESS; } \ No newline at end of file diff --git a/exit_handler.cpp b/exit_handler.cpp index 803e8bc..5bcd115 100644 --- a/exit_handler.cpp +++ b/exit_handler.cpp @@ -11,8 +11,15 @@ auto exit_handler(hv::pguest_registers regs) -> void { if (regs->rcx == 0xC0FFEE) { - regs->rax = 0xC0FFEE; - *(u8*)0x0 = 0xDE; + __try + { + *(u8*)0x0 = 0xDE; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + regs->rax = 0xC0FFEE; + break; + } } else { @@ -31,8 +38,6 @@ auto exit_handler(hv::pguest_registers regs) -> void value.high = regs->rdx; value.low = regs->rax; - // can also validate the input instead of using - // reimplimented SEH... __try { /* @@ -62,8 +67,6 @@ auto exit_handler(hv::pguest_registers regs) -> void } case VMX_EXIT_REASON_EXECUTE_RDMSR: { - // can also validate the input instead of using - // reimplimented SEH... __try { /* @@ -95,8 +98,6 @@ auto exit_handler(hv::pguest_registers regs) -> void value.low = regs->rax; value.high = regs->rdx; - // can also validate the input instead of using - // reimplimented SEH... __try { __writemsr(regs->rcx, value.value); diff --git a/gdt.hpp b/gdt.hpp index e1a5f0a..5c79080 100644 --- a/gdt.hpp +++ b/gdt.hpp @@ -1,12 +1,8 @@ #pragma once #include "hv_types.hpp" -#pragma section(".gdt", read, write) namespace gdt { - // index used for GDT per-core in vmxroot... - enum idx : u8 { es, ds, cs, gs, fs, ss, tr, ldt }; - auto get_info(const segment_descriptor_register_64& gdt_value, segment_selector segment) -> 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/hv_types.hpp b/hv_types.hpp index 756b891..63cf676 100644 --- a/hv_types.hpp +++ b/hv_types.hpp @@ -2,6 +2,7 @@ #include #include #include "ia32.hpp" +#include using u8 = unsigned char; using u16 = unsigned short; @@ -29,6 +30,188 @@ extern "C" void _sgdt(void*); #define HOST_STACK_PAGES 6 #define HOST_STACK_SIZE PAGE_SIZE * HOST_STACK_PAGES +// Export Directory +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +// Import Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +// Resource Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +// Exception Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +// Security Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 +// Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +// Debug Directory +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +// Description String +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +// Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +// TLS Directory +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +// Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 + +#define UNW_FLAG_NHANDLER 0 +#define UNW_FLAG_EHANDLER 1 +#define UNW_FLAG_UHANDLER 2 +#define UNW_FLAG_CHAININFO 4 + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + USHORT e_magic; // Magic number + USHORT e_cblp; // Bytes on last page of file + USHORT e_cp; // Pages in file + USHORT e_crlc; // Relocations + USHORT e_cparhdr; // Size of header in paragraphs + USHORT e_minalloc; // Minimum extra paragraphs needed + USHORT e_maxalloc; // Maximum extra paragraphs needed + USHORT e_ss; // Initial (relative) SS value + USHORT e_sp; // Initial SP value + USHORT e_csum; // Checksum + USHORT e_ip; // Initial IP value + USHORT e_cs; // Initial (relative) CS value + USHORT e_lfarlc; // File address of relocation table + USHORT e_ovno; // Overlay number + USHORT e_res[4]; // Reserved words + USHORT e_oemid; // OEM identifier (for e_oeminfo) + USHORT e_oeminfo; // OEM information; e_oemid specific + USHORT e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_FILE_HEADER { + short Machine; + short NumberOfSections; + unsigned TimeDateStamp; + unsigned PointerToSymbolTable; + unsigned NumberOfSymbols; + short SizeOfOptionalHeader; + short Characteristics; +} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + unsigned VirtualAddress; + unsigned Size; +} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + short Magic; + unsigned char MajorLinkerVersion; + unsigned char MinorLinkerVersion; + unsigned SizeOfCode; + unsigned SizeOfInitializedData; + unsigned SizeOfUninitializedData; + unsigned AddressOfEntryPoint; + unsigned BaseOfCode; + ULONGLONG ImageBase; + unsigned SectionAlignment; + unsigned FileAlignment; + short MajorOperatingSystemVersion; + short MinorOperatingSystemVersion; + short MajorImageVersion; + short MinorImageVersion; + short MajorSubsystemVersion; + short MinorSubsystemVersion; + unsigned Win32VersionValue; + unsigned SizeOfImage; + unsigned SizeOfHeaders; + unsigned CheckSum; + short Subsystem; + short DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + unsigned LoaderFlags; + unsigned NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[16]; +} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64; + +typedef struct _IMAGE_NT_HEADERS64 { + unsigned Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64; + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + union { + unsigned long Characteristics; // 0 for terminating null import descriptor + unsigned long OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + } DUMMYUNIONNAME; + unsigned long TimeDateStamp; // 0 if not bound, + // -1 if bound, and real date\time stamp + // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) + // O.W. date/time stamp of DLL bound to (Old BIND) + + unsigned long ForwarderChain; // -1 if no forwarders + unsigned long Name; + unsigned long FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) +} IMAGE_IMPORT_DESCRIPTOR; +typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED* PIMAGE_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_IMPORT_BY_NAME { + unsigned long Hint; + CHAR Name[1]; +} IMAGE_IMPORT_BY_NAME, * PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA64 { + union { + ULONGLONG ForwarderString; // PBYTE + ULONGLONG Function; // PDWORD + ULONGLONG Ordinal; + ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA64, * PIMAGE_THUNK_DATA64; +typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA; + +typedef struct _SCOPE_RECORD { + UINT32 BeginAddress; + UINT32 EndAddress; + UINT32 HandlerAddress; + UINT32 JumpTarget; +} SCOPE_RECORD; + +typedef struct _SCOPE_TABLE { + UINT32 Count; + SCOPE_RECORD ScopeRecords[1]; +} SCOPE_TABLE; + +typedef struct _RUNTIME_FUNCTION { + UINT32 BeginAddress; + UINT32 EndAddress; + UINT32 UnwindData; +} RUNTIME_FUNCTION; + +#pragma warning(push) +#pragma warning(disable : 4200) +#pragma warning(disable : 4201) +#pragma warning(disable : 4214) +typedef union _UNWIND_CODE { + UINT8 CodeOffset; + UINT8 UnwindOp : 4; + UINT8 OpInfo : 4; + UINT16 FrameOffset; +} UNWIND_CODE; + +typedef struct _UNWIND_INFO { + UINT8 Version : 3; + UINT8 Flags : 5; + UINT8 SizeOfProlog; + UINT8 CountOfCodes; + UINT8 FrameRegister : 4; + UINT8 FrameOffset : 4; + UNWIND_CODE UnwindCode[1]; + + union { + UINT32 ExceptionHandler; + UINT32 FunctionEntry; + }; + + UINT32 ExceptionData[]; +} UNWIND_INFO; +#pragma warning(pop) + namespace hv { typedef struct _guest_registers @@ -133,8 +316,7 @@ namespace hv u64 segment_selector : 16; u64 ist_index : 3; u64 reserved_0 : 5; - u64 gate_type : 4; - u64 storage_segment : 1; + u64 gate_type : 5; u64 dpl : 2; u64 present : 1; u64 offset_middle : 16; @@ -156,14 +338,12 @@ namespace hv typedef struct _tss64 { - u32 reserved_0; - u64 rsp_0; - u64 rsp_1; - u64 rsp_2; - void* interrupt_stack_table[8]; + u32 reserved; + u64 privilege_stacks[3]; u64 reserved_1; - u64 reserved_2; - u64 io_map_base; + u64 interrupt_stack_table[7]; + u16 reserved_2; + u16 iomap_base; } tss64, *ptss64; union segment_descriptor_addr_t @@ -492,13 +672,12 @@ namespace hv { pvmxon_region_ctx vmxon; pvmcs_ctx vmcs; - u64 vmcs_phys; u64 vmxon_phys; u64 host_stack; tss64 tss; - segment_descriptor_64 gdt[8]; + segment_descriptor_64* gdt; } vcpu_ctx, * pvcpu_ctx; typedef struct _vmx_ctx diff --git a/idt.cpp b/idt.cpp index 43f2f0f..9bb0538 100644 --- a/idt.cpp +++ b/idt.cpp @@ -2,44 +2,46 @@ auto seh_handler(hv::pidt_regs_t regs) -> void { - __debugbreak(); - - /*const auto rva = regs->rip - reinterpret_cast(idt::image_base); - - IMAGE_NT_HEADERS64* nt = (IMAGE_NT_HEADERS64*)(reinterpret_cast(idt::image_base) + - reinterpret_cast(idt::image_base).e_lfanew); - - IMAGE_DATA_DIRECTORY* exception = - &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; - - RUNTIME_FUNCTION* functions = - (RUNTIME_FUNCTION*)((UINT64)&__ImageBase + exception->VirtualAddress); - - for (UINT32 i = 0; i < exception->Size / sizeof(RUNTIME_FUNCTION); ++i) { - RUNTIME_FUNCTION* function = &functions[i]; - if (!(rva >= function->BeginAddress && rva < function->EndAddress)) { + const auto rva = regs->rip - reinterpret_cast(idt::image_base); + const auto nt_headers = reinterpret_cast( + reinterpret_cast(idt::image_base) + + reinterpret_cast(idt::image_base)->e_lfanew); + + const auto exception = + &nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + + const auto functions = + reinterpret_cast( + reinterpret_cast(idt::image_base) + exception->VirtualAddress); + + for (auto idx = 0; idx < exception->Size / sizeof(RUNTIME_FUNCTION); ++idx) + { + const auto function = &functions[idx]; + if (!(rva >= function->BeginAddress && rva < function->EndAddress)) continue; - } - UNWIND_INFO* unwindInfo = (UNWIND_INFO*)((UINT64)&__ImageBase + function->UnwindData); - if (!(unwindInfo->Flags & UNW_FLAG_EHANDLER)) { - continue; - } + const auto unwind_info = + reinterpret_cast( + reinterpret_cast(idt::image_base) + function->UnwindData); - SCOPE_TABLE* scopeTable = - (SCOPE_TABLE*)((UINT64)&unwindInfo->UnwindCode[(unwindInfo->CountOfCodes + 1) & ~1] + - sizeof(UINT32)); - - for (UINT32 e = 0; e < scopeTable->Count; ++e) { - SCOPE_RECORD* scopeRecord = &scopeTable->ScopeRecords[e]; + if (!(unwind_info->Flags & UNW_FLAG_EHANDLER)) + continue; - if (rva >= scopeRecord->BeginAddress && rva < scopeRecord->EndAddress) { - *rip = (UINT64)&__ImageBase + scopeRecord->JumpTarget; + const auto scope_table = + reinterpret_cast( + reinterpret_cast(&unwind_info->UnwindCode[ + (unwind_info->CountOfCodes + 1) & ~1]) + sizeof(u32)); + + for (auto entry = 0; entry < scope_table->Count; ++entry) + { + const auto scope_record = &scope_table->ScopeRecords[entry]; + if (rva >= scope_record->BeginAddress && rva < scope_record->EndAddress) + { + regs->rip = reinterpret_cast(idt::image_base) + scope_record->JumpTarget; return; } } } - */ } namespace idt @@ -47,11 +49,10 @@ namespace idt auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t { hv::idt_entry_t result{}; - result.segment_selector = readcs(); + result.segment_selector = readcs(); result.gate_type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE; result.present = true; - result.ist_index = NULL; - result.dpl = 0; + //result.ist_index = ist_index; result.offset_high = idt_handler.offset_high; result.offset_middle = idt_handler.offset_middle; diff --git a/idt.hpp b/idt.hpp index 7aec693..bfab4af 100644 --- a/idt.hpp +++ b/idt.hpp @@ -6,15 +6,14 @@ #pragma section(".idt", read, write) extern "C" void __gp_handler(void); extern "C" void __pf_handler(void); -extern "C" void __de_handler(void); extern "C" void seh_handler(hv::pidt_regs_t regs); namespace idt { __declspec(allocate(".idt")) inline hv::idt_entry_t table[256]; - inline void* image_base = nullptr; // used for SEH... - enum ist_idx : u8 { gp = 5, pf = 6, de = 7}; + enum ist_idx : u8 { 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; } \ No newline at end of file diff --git a/idt_handlers.asm b/idt_handlers.asm index ff0c7b9..d9e86d6 100644 --- a/idt_handlers.asm +++ b/idt_handlers.asm @@ -2,7 +2,6 @@ extern seh_handler : proc .code __pf_handler proc -__de_handler proc __gp_handler proc push rax push rbx @@ -20,7 +19,7 @@ __gp_handler proc push r14 push r15 - sub rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... + sub rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... (you dont need any of these...) movaps [rsp], xmm0 movaps [rsp + 010h], xmm1 movaps [rsp + 020h], xmm2 @@ -59,7 +58,7 @@ __gp_handler proc movups xmm13, [rsp + 0D0h] movups xmm14, [rsp + 0E0h] movups xmm15, [rsp + 0F0h] - add rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... + add rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... (you dont need any of these...) pop r15 pop r14 @@ -80,6 +79,5 @@ __gp_handler proc iretq __gp_handler endp -__de_handler endp __pf_handler endp end \ No newline at end of file diff --git a/vmcs.cpp b/vmcs.cpp index 492f208..39755cf 100644 --- a/vmcs.cpp +++ b/vmcs.cpp @@ -2,121 +2,56 @@ namespace vmcs { - auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void + auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value, u64 gdt_base) -> void { - segment_descriptor_register_64 gdt_value; - _sgdt(&gdt_value); - __vmx_vmwrite(VMCS_HOST_CR0, __readcr0()); __vmx_vmwrite(VMCS_HOST_CR3, cr3_value.flags); __vmx_vmwrite(VMCS_HOST_CR4, __readcr4()); __vmx_vmwrite(VMCS_HOST_RSP, host_rsp + (PAGE_SIZE * HOST_STACK_PAGES)); __vmx_vmwrite(VMCS_HOST_RIP, reinterpret_cast(host_rip)); - - const auto current_vcpu = - vmxon::g_vmx_ctx->vcpus[KeGetCurrentProcessorNumber()]; - __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address); + __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_base); __vmx_vmwrite(VMCS_HOST_IDTR_BASE, reinterpret_cast(idt::table)); segment_selector es{ reades() }; es.request_privilege_level = NULL; es.table = NULL; - - const auto [es_descriptor, es_rights, es_limit, es_base] = - gdt::get_info(gdt_value, es); - - es.idx = gdt::idx::es; - current_vcpu->gdt[gdt::idx::es] = es_descriptor; __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, es.flags); segment_selector cs{ readcs() }; cs.request_privilege_level = NULL; cs.table = NULL; - - const auto [cs_descriptor, cs_rights, cs_limit, cs_base] = - gdt::get_info(gdt_value, cs); - - cs.idx = gdt::idx::cs; - current_vcpu->gdt[gdt::idx::cs] = cs_descriptor; __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, cs.flags); segment_selector ds{ readds() }; ds.request_privilege_level = NULL; ds.table = NULL; - - const auto [ds_descriptor, ds_rights, ds_limit, ds_base] = - gdt::get_info(gdt_value, ds); - - ds.idx = gdt::idx::ds; - current_vcpu->gdt[gdt::idx::ds] = ds_descriptor; __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, ds.flags); segment_selector fs{ readfs() }; fs.request_privilege_level = NULL; fs.table = NULL; - - const auto [fs_descriptor, fs_rights, fs_limit, fs_base] = - gdt::get_info(gdt_value, fs); - - fs.idx = gdt::idx::fs; - current_vcpu->gdt[gdt::idx::fs] = fs_descriptor; __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, fs.flags); __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_FS_BASE)); segment_selector gs{ readgs() }; gs.request_privilege_level = NULL; gs.table = NULL; - - const auto [gs_descriptor, gs_rights, gs_limit, gs_base] = - gdt::get_info(gdt_value, gs); - - gs.idx = gdt::idx::gs; - current_vcpu->gdt[gdt::idx::gs] = gs_descriptor; __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, gs.flags); __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); segment_selector ss{ readss() }; ss.request_privilege_level = NULL; ss.table = NULL; - - const auto [ss_descriptor, ss_rights, ss_limit, ss_base] = - gdt::get_info(gdt_value, ss); - - ss.idx = gdt::idx::ss; - current_vcpu->gdt[gdt::idx::ss] = ss_descriptor; __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, ss.flags); segment_selector tr{ readtr() }; tr.request_privilege_level = NULL; tr.table = NULL; - - const auto [tr_descriptor, tr_rights, tr_limit, tr_base] = - gdt::get_info(gdt_value, tr); - - tr.idx = gdt::idx::tr; - current_vcpu->gdt[gdt::idx::tr] = tr_descriptor; __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, tr.flags); - // setup interrupt stack table... - // windows is using 1-4... im using 5-7... - memcpy(¤t_vcpu->tss, (void*)tr_base, sizeof hv::tss64); - - current_vcpu->tss.interrupt_stack_table[5] = - ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); - - current_vcpu->tss.interrupt_stack_table[6] = - ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); - - current_vcpu->tss.interrupt_stack_table[7] = - ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); - hv::segment_descriptor_addr_t tss_addr{ ¤t_vcpu->tss }; - current_vcpu->gdt[gdt::idx::tr].base_address_upper = tss_addr.upper; - current_vcpu->gdt[gdt::idx::tr].base_address_high = tss_addr.high; - current_vcpu->gdt[gdt::idx::tr].base_address_middle = tss_addr.middle; - current_vcpu->gdt[gdt::idx::tr].base_address_low = tss_addr.low; } auto setup_guest() -> void diff --git a/vmcs.hpp b/vmcs.hpp index d0fbe3b..24349ad 100644 --- a/vmcs.hpp +++ b/vmcs.hpp @@ -3,12 +3,12 @@ #include "segment_intrin.h" #include "vmxexit_handler.h" #include "vmxon.hpp" -#include "gdt.hpp" #include "idt.hpp" +#include "gdt.hpp" namespace vmcs { - auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void; + auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value, u64 gdt_base) -> void; auto setup_guest() -> void; auto setup_controls() -> void; } \ No newline at end of file diff --git a/vmxlaunch.cpp b/vmxlaunch.cpp index afbe3a5..873a42c 100644 --- a/vmxlaunch.cpp +++ b/vmxlaunch.cpp @@ -9,7 +9,34 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void __vmx_vmclear(&vcpu->vmcs_phys); __vmx_vmptrld(&vcpu->vmcs_phys); - vmcs::setup_host(&vmxexit_handler, vcpu->host_stack, cr3_value); + segment_descriptor_register_64 gdt_value; + _sgdt(&gdt_value); + + const auto [tr_descriptor, tr_rights, tr_limit, tr_base] = + gdt::get_info(gdt_value, segment_selector{ readtr() }); + + // copy windows TSS and windows GDT... + // change TSS base to new TSS... + hv::segment_descriptor_addr_t tss{ &vcpu->tss }; + memcpy(&vcpu->tss, (void*)tr_base, sizeof hv::tss64); + memcpy(vcpu->gdt, (void*)gdt_value.base_address, PAGE_SIZE); + + vcpu->tss.interrupt_stack_table[idt::ist_idx::pf] = + reinterpret_cast(ExAllocatePool(NonPagedPool, + PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES); + + vcpu->tss.interrupt_stack_table[idt::ist_idx::gp] = + 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; + + vmcs::setup_host(&vmxexit_handler, + vcpu->host_stack, cr3_value, (u64)vcpu->gdt); + vmcs::setup_guest(); vmcs::setup_controls(); } diff --git a/vmxon.cpp b/vmxon.cpp index 361a2b3..50c2701 100644 --- a/vmxon.cpp +++ b/vmxon.cpp @@ -74,6 +74,10 @@ namespace vmxon ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES)); + vmx_ctx->vcpus[idx]->gdt = + reinterpret_cast( + ExAllocatePool(NonPagedPool, PAGE_SIZE)); + RtlZeroMemory(reinterpret_cast( vmx_ctx->vcpus[idx]->host_stack), PAGE_SIZE * HOST_STACK_PAGES); @@ -84,16 +88,10 @@ namespace vmxon auto init_vmxon() -> void { - hv::ia32_feature_control_msr_t feature_msr = { 0 }; hv::cr_fixed_t cr_fixed; hv::cr0_t cr0 = { 0 }; hv::cr4_t cr4 = { 0 }; - 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); - cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED0); cr0.flags = __readcr0(); cr0.flags |= cr_fixed.split.low; @@ -108,10 +106,6 @@ namespace vmxon cr4.flags &= cr_fixed.split.low; __writecr4(cr4.flags); - cr4.flags = __readcr4(); - cr4.vmx_enable = true; - __writecr4(cr4.flags); - const auto vmxon_result = __vmx_on((unsigned long long*) &vmxon::g_vmx_ctx->vcpus[