getting rekted by vmxerror 7 (invalid control fields)

merge-requests/1/head
IDontCode 4 years ago
parent 06af7e9dab
commit 84cee2e610

@ -56,6 +56,8 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="entry.cpp" /> <ClCompile Include="entry.cpp" />
<ClCompile Include="exit_handler.cpp" /> <ClCompile Include="exit_handler.cpp" />
<ClCompile Include="segment.cpp" />
<ClCompile Include="vmcs.cpp" />
<ClCompile Include="vmxlaunch.cpp" /> <ClCompile Include="vmxlaunch.cpp" />
<ClCompile Include="vmxon.cpp" /> <ClCompile Include="vmxon.cpp" />
</ItemGroup> </ItemGroup>
@ -63,6 +65,7 @@
<ClInclude Include="ia32.hpp" /> <ClInclude Include="ia32.hpp" />
<ClInclude Include="segment_intrin.h" /> <ClInclude Include="segment_intrin.h" />
<ClInclude Include="hv_types.hpp" /> <ClInclude Include="hv_types.hpp" />
<ClInclude Include="vmcs.hpp" />
<ClInclude Include="vmxexit_handler.h" /> <ClInclude Include="vmxexit_handler.h" />
<ClInclude Include="vmxlaunch.hpp" /> <ClInclude Include="vmxlaunch.hpp" />
<ClInclude Include="vmxon.hpp" /> <ClInclude Include="vmxon.hpp" />

@ -23,6 +23,12 @@
<ClCompile Include="exit_handler.cpp"> <ClCompile Include="exit_handler.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="vmcs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="segment.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="vmxon.hpp"> <ClInclude Include="vmxon.hpp">
@ -43,6 +49,9 @@
<ClInclude Include="hv_types.hpp"> <ClInclude Include="hv_types.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="vmcs.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MASM Include="segment_intrin.asm"> <MASM Include="segment_intrin.asm">

@ -53,7 +53,7 @@ auto driver_entry(
KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL); KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL);
// vmxlaunch for all cores... // vmxlaunch for all cores...
// KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL); KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
driver_object->DriverUnload = &driver_unload; driver_object->DriverUnload = &driver_unload;
return STATUS_SUCCESS; return STATUS_SUCCESS;

@ -19,6 +19,6 @@ auto exit_handler(hv::pguest_registers regs) -> void
case VMX_EXIT_REASON_EXECUTE_VMCLEAR: case VMX_EXIT_REASON_EXECUTE_VMCLEAR:
case VMX_EXIT_REASON_EXECUTE_RDTSC: case VMX_EXIT_REASON_EXECUTE_RDTSC:
default: default:
__vmx_off(); break;
} }
} }

@ -14,6 +14,11 @@ using s16 = short;
using s32 = int; using s32 = int;
using s64 = long long; 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 DBG_PRINT(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[hv]" __VA_ARGS__)
#define HOST_STACK_PAGES 6 #define HOST_STACK_PAGES 6
@ -378,4 +383,11 @@ namespace hv
u32 vcpu_num; u32 vcpu_num;
pvcpu_ctx* vcpus; pvcpu_ctx* vcpus;
} vmx_ctx, *pvmx_ctx; } 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;
} }

@ -9936,6 +9936,7 @@ typedef union
#define IA32_VMX_BASIC 0x00000480 #define IA32_VMX_BASIC 0x00000480
typedef union typedef union
{ {
uint64_t flags;
struct struct
{ {
/** /**
@ -10054,8 +10055,6 @@ typedef union
#define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01) #define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01)
uint64_t reserved2 : 8; uint64_t reserved2 : 8;
}; };
uint64_t flags;
} ia32_vmx_basic_register; } ia32_vmx_basic_register;
@ -10069,6 +10068,7 @@ typedef union
#define IA32_VMX_PINBASED_CTLS 0x00000481 #define IA32_VMX_PINBASED_CTLS 0x00000481
typedef union typedef union
{ {
uint64_t flags;
struct struct
{ {
/** /**
@ -10144,8 +10144,6 @@ typedef union
#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01) #define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01)
uint64_t reserved3 : 56; uint64_t reserved3 : 56;
}; };
uint64_t flags;
} ia32_vmx_pinbased_ctls_register; } 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. * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details.
*/ */
uint32_t base_address_middle : 8; 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_FLAG 0xFF
#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF #define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF
#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 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. * Base address field (32:63); see description of $BASE_LOW for more details.
*/ */
uint32_t base_address_upper; uint32_t base_address_upper;
#define SEGMENT__BASE_ADDRESS_SHIFT 32
/** /**
* Base address field (32:63); see description of $BASE_LOW for more details. * Base address field (32:63); see description of $BASE_LOW for more details.
@ -15844,6 +15843,8 @@ typedef struct
*/ */
typedef union typedef union
{ {
uint16_t flags;
struct struct
{ {
/** /**
@ -15879,8 +15880,6 @@ typedef union
#define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF #define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF
#define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF) #define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF)
}; };
uint16_t flags;
} segment_selector; } segment_selector;
/** /**

@ -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<segment_descriptor_64*>(
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;
}
}

@ -28,4 +28,14 @@ readcs proc
mov rax, cs mov rax, cs
ret ret
readcs endp readcs endp
readtr proc
str ax
ret
readtr endp
readldt proc
sldt ax
ret
readldt endp
end end

@ -1,9 +1,17 @@
#pragma once #pragma once
#include "hv_types.hpp" #include "hv_types.hpp"
extern "C" u64 readfs(void); extern "C" u16 readfs(void);
extern "C" u64 readgs(void); extern "C" u16 readgs(void);
extern "C" u64 reades(void); extern "C" u16 reades(void);
extern "C" u64 readds(void); extern "C" u16 readds(void);
extern "C" u64 readss(void); extern "C" u16 readss(void);
extern "C" u64 readcs(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;
}

@ -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<u64>(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);
}
}

@ -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;
}

@ -2,6 +2,7 @@ extern exit_handler : proc
.code .code
vmxexit_handler proc vmxexit_handler proc
int 3 ; see if vmexit get called...
push rax push rax
push rbx push rbx
push rcx push rcx
@ -38,9 +39,9 @@ vmxexit_handler proc
movaps [rsp + 0F0h], xmm15 movaps [rsp + 0F0h], xmm15
mov rcx, rsp mov rcx, rsp
sub rsp, 28h ; shadow space or some shit MSVC does it so i do it... sub rsp, 20h
call exit_handler call exit_handler
add rsp, 28h add rsp, 20h
movaps xmm0, [rsp] movaps xmm0, [rsp]
movaps xmm1, [rsp + 010h] movaps xmm1, [rsp + 010h]
@ -76,6 +77,6 @@ vmxexit_handler proc
pop rcx pop rcx
pop rax pop rax
vmresume ; resume guest execution... vmresume
vmxexit_handler endp vmxexit_handler endp
end end

@ -2,104 +2,28 @@
auto vmxlaunch::init_vmcs() -> void auto vmxlaunch::init_vmcs() -> void
{ {
__vmx_vmclear(&vmxon::g_vmx_ctx->vcpus[ const auto vcpu =
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<u64>(&::vmxexit_handler));
__vmx_vmwrite(VMCS_HOST_RSP,
vmxon::g_vmx_ctx->vcpus[ vmxon::g_vmx_ctx->vcpus[
KeGetCurrentProcessorNumber()]->host_stack); KeGetCurrentProcessorNumber()];
// 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);
ia32_vmx_pinbased_ctls_register pinbased_ctls; __vmx_vmclear(&vcpu->vmcs_phys);
pinbased_ctls.activate_vmx_preemption_timer = false; __vmx_vmptrld(&vcpu->vmcs_phys);
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);
ia32_vmx_entry_ctls_register entry_ctls; vmcs::setup_host(&vmxexit_handler, vcpu->host_stack);
entry_ctls.conceal_vmx_from_pt = true; vmcs::setup_guest();
entry_ctls.deactivate_dual_monitor_treatment = false; vmcs::setup_controls();
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);
} }
auto vmxlaunch::launch() -> void auto vmxlaunch::launch() -> void
{ {
const auto vmlaunch_result = __vmx_vmlaunch();
DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber()); 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);
}
} }

@ -2,6 +2,7 @@
#include "segment_intrin.h" #include "segment_intrin.h"
#include "vmxexit_handler.h" #include "vmxexit_handler.h"
#include "vmxon.hpp" #include "vmxon.hpp"
#include "vmcs.hpp"
namespace vmxlaunch namespace vmxlaunch
{ {

@ -95,11 +95,14 @@ namespace vmxon
hv::cr0_t cr0 = { 0 }; hv::cr0_t cr0 = { 0 };
hv::cr4_t cr4 = { 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.control = __readmsr(IA32_FEATURE_CONTROL);
feature_msr.bits.vmxon_outside_smx = true; feature_msr.bits.vmxon_outside_smx = true;
feature_msr.bits.lock = true; feature_msr.bits.lock = true;
__writemsr(IA32_FEATURE_CONTROL, feature_msr.control); __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); cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED0);
cr0.flags = __readcr0(); cr0.flags = __readcr0();
cr0.flags |= cr_fixed.split.low; cr0.flags |= cr_fixed.split.low;
@ -118,17 +121,10 @@ namespace vmxon
cr4.vmx_enable = true; cr4.vmx_enable = true;
__writecr4(cr4.flags); __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*) __vmx_on((unsigned long long*)
&vmxon::g_vmx_ctx->vcpus[ &vmxon::g_vmx_ctx->vcpus[
KeGetCurrentProcessorNumber()]->vmxon_phys); KeGetCurrentProcessorNumber()]->vmxon_phys));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DBG_PRINT("vmxon failed for processor: %d\n", KeGetCurrentProcessorNumber());
}
} }
} }
Loading…
Cancel
Save