parent
da1654dd09
commit
06af7e9dab
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="entry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmxon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmxlaunch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="exit_handler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="vmxon.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmxlaunch.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ia32.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="segment_intrin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmxexit_handler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hv_types.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="segment_intrin.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
<MASM Include="vmxexit_handler.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<SignMode>Off</SignMode>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -0,0 +1,60 @@
|
||||
#include "vmxlaunch.hpp"
|
||||
|
||||
auto driver_unload(
|
||||
PDRIVER_OBJECT driver_object
|
||||
) -> void
|
||||
{
|
||||
// TODO vmcall and ask HV to vmxoff...
|
||||
KeIpiGenericCall(
|
||||
[](ULONG_PTR) -> ULONG_PTR
|
||||
{
|
||||
__vmx_off();
|
||||
hv::cr4_t cr4 = { __readcr4() };
|
||||
cr4.vmx_enable = false;
|
||||
__writecr4(cr4.flags);
|
||||
|
||||
hv::ia32_feature_control_msr_t feature_msr = { __readmsr(IA32_FEATURE_CONTROL) };
|
||||
feature_msr.bits.vmxon_outside_smx = false;
|
||||
feature_msr.bits.lock = false;
|
||||
__writemsr(IA32_FEATURE_CONTROL, feature_msr.control);
|
||||
return NULL;
|
||||
}, NULL
|
||||
);
|
||||
|
||||
for (auto idx = 0u; idx < vmxon::g_vmx_ctx->vcpu_num; ++idx)
|
||||
{
|
||||
MmFreeContiguousMemory(vmxon::g_vmx_ctx->vcpus[idx]->vmcs);
|
||||
MmFreeContiguousMemory(vmxon::g_vmx_ctx->vcpus[idx]->vmxon);
|
||||
|
||||
ExFreePool((void*)vmxon::g_vmx_ctx->vcpus[idx]->host_stack);
|
||||
ExFreePool(vmxon::g_vmx_ctx->vcpus[idx]);
|
||||
}
|
||||
|
||||
ExFreePool(vmxon::g_vmx_ctx->vcpus);
|
||||
ExFreePool(vmxon::g_vmx_ctx);
|
||||
}
|
||||
|
||||
auto driver_entry(
|
||||
PDRIVER_OBJECT driver_object,
|
||||
PUNICODE_STRING registry_path
|
||||
) -> NTSTATUS
|
||||
{
|
||||
vmxon::g_vmx_ctx =
|
||||
reinterpret_cast<hv::pvmx_ctx>(
|
||||
ExAllocatePool(NonPagedPool, sizeof hv::vmx_ctx));
|
||||
|
||||
// setup vcpu structures (vmx on region and vmcs...)
|
||||
vmxon::create_vcpus(vmxon::g_vmx_ctx);
|
||||
|
||||
// enable vmx operation on all cores...
|
||||
KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxon::init_vmxon, NULL);
|
||||
|
||||
// setup VMCS for all logical cores...
|
||||
KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL);
|
||||
|
||||
// vmxlaunch for all cores...
|
||||
// KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
|
||||
|
||||
driver_object->DriverUnload = &driver_unload;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#include "vmxexit_handler.h"
|
||||
|
||||
auto exit_handler(hv::pguest_registers regs) -> void
|
||||
{
|
||||
u64 exit_reason;
|
||||
__vmx_vmread(VMCS_EXIT_REASON, &exit_reason);
|
||||
|
||||
switch (exit_reason)
|
||||
{
|
||||
case VMX_EXIT_REASON_EXECUTE_CPUID:
|
||||
case VMX_EXIT_REASON_EXECUTE_INVLPG:
|
||||
case VMX_EXIT_REASON_EXECUTE_XSETBV:
|
||||
case VMX_EXIT_REASON_EXECUTE_HLT:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMCALL:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMREAD:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMWRITE:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMPTRLD:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMPTRST:
|
||||
case VMX_EXIT_REASON_EXECUTE_VMCLEAR:
|
||||
case VMX_EXIT_REASON_EXECUTE_RDTSC:
|
||||
default:
|
||||
__vmx_off();
|
||||
}
|
||||
}
|
@ -0,0 +1,381 @@
|
||||
#pragma once
|
||||
#include <ntifs.h>
|
||||
#include <intrin.h>
|
||||
#include "ia32.hpp"
|
||||
|
||||
using u8 = unsigned char;
|
||||
using u16 = unsigned short;
|
||||
using u32 = unsigned int;
|
||||
using u64 = unsigned long long;
|
||||
using u128 = __m128;
|
||||
|
||||
using s8 = char;
|
||||
using s16 = short;
|
||||
using s32 = int;
|
||||
using s64 = long long;
|
||||
|
||||
#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;
|
||||
u128 xmm3;
|
||||
u128 xmm4;
|
||||
u128 xmm5;
|
||||
u128 xmm6;
|
||||
u128 xmm7;
|
||||
u128 xmm8;
|
||||
u128 xmm9;
|
||||
u128 xmm10;
|
||||
u128 xmm11;
|
||||
u128 xmm12;
|
||||
u128 xmm13;
|
||||
u128 xmm14;
|
||||
u128 xmm15;
|
||||
} guest_registers, * pguest_registers;
|
||||
|
||||
union ia32_efer_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 syscall_enable : 1;
|
||||
unsigned __int64 reserved_0 : 7;
|
||||
unsigned __int64 long_mode_enable : 1;
|
||||
unsigned __int64 reserved_1 : 1;
|
||||
unsigned __int64 long_mode_active : 1;
|
||||
unsigned __int64 execute_disable : 1;
|
||||
unsigned __int64 reserved_2 : 52;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ia32_feature_control_msr_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 lock : 1;
|
||||
unsigned __int64 vmxon_inside_smx : 1;
|
||||
unsigned __int64 vmxon_outside_smx : 1;
|
||||
unsigned __int64 reserved_0 : 5;
|
||||
unsigned __int64 senter_local : 6;
|
||||
unsigned __int64 senter_global : 1;
|
||||
unsigned __int64 reserved_1 : 1;
|
||||
unsigned __int64 sgx_launch_control_enable : 1;
|
||||
unsigned __int64 sgx_global_enable : 1;
|
||||
unsigned __int64 reserved_2 : 1;
|
||||
unsigned __int64 lmce : 1;
|
||||
unsigned __int64 system_reserved : 42;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_misc_msr_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 vmx_preemption_tsc_rate : 5;
|
||||
unsigned __int64 store_lma_in_vmentry_control : 1;
|
||||
unsigned __int64 activate_state_bitmap : 3;
|
||||
unsigned __int64 reserved_0 : 5;
|
||||
unsigned __int64 pt_in_vmx : 1;
|
||||
unsigned __int64 rdmsr_in_smm : 1;
|
||||
unsigned __int64 cr3_target_value_count : 9;
|
||||
unsigned __int64 max_msr_vmexit : 3;
|
||||
unsigned __int64 allow_smi_blocking : 1;
|
||||
unsigned __int64 vmwrite_to_any : 1;
|
||||
unsigned __int64 interrupt_mod : 1;
|
||||
unsigned __int64 reserved_1 : 1;
|
||||
unsigned __int64 mseg_revision_identifier : 32;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_pinbased_control_msr_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 external_interrupt_exiting : 1;
|
||||
unsigned __int64 reserved_0 : 2;
|
||||
unsigned __int64 nmi_exiting : 1;
|
||||
unsigned __int64 reserved_1 : 1;
|
||||
unsigned __int64 virtual_nmis : 1;
|
||||
unsigned __int64 vmx_preemption_timer : 1;
|
||||
unsigned __int64 process_posted_interrupts : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_primary_processor_based_control_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 reserved_0 : 2;
|
||||
unsigned __int64 interrupt_window_exiting : 1;
|
||||
unsigned __int64 use_tsc_offsetting : 1;
|
||||
unsigned __int64 reserved_1 : 3;
|
||||
unsigned __int64 hlt_exiting : 1;
|
||||
unsigned __int64 reserved_2 : 1;
|
||||
unsigned __int64 invldpg_exiting : 1;
|
||||
unsigned __int64 mwait_exiting : 1;
|
||||
unsigned __int64 rdpmc_exiting : 1;
|
||||
unsigned __int64 rdtsc_exiting : 1;
|
||||
unsigned __int64 reserved_3 : 2;
|
||||
unsigned __int64 cr3_load_exiting : 1;
|
||||
unsigned __int64 cr3_store_exiting : 1;
|
||||
unsigned __int64 reserved_4 : 2;
|
||||
unsigned __int64 cr8_load_exiting : 1;
|
||||
unsigned __int64 cr8_store_exiting : 1;
|
||||
unsigned __int64 use_tpr_shadow : 1;
|
||||
unsigned __int64 nmi_window_exiting : 1;
|
||||
unsigned __int64 mov_dr_exiting : 1;
|
||||
unsigned __int64 unconditional_io_exiting : 1;
|
||||
unsigned __int64 use_io_bitmaps : 1;
|
||||
unsigned __int64 reserved_5 : 1;
|
||||
unsigned __int64 monitor_trap_flag : 1;
|
||||
unsigned __int64 use_msr_bitmaps : 1;
|
||||
unsigned __int64 monitor_exiting : 1;
|
||||
unsigned __int64 pause_exiting : 1;
|
||||
unsigned __int64 active_secondary_controls : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_secondary_processor_based_control_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 virtualize_apic_accesses : 1;
|
||||
unsigned __int64 enable_ept : 1;
|
||||
unsigned __int64 descriptor_table_exiting : 1;
|
||||
unsigned __int64 enable_rdtscp : 1;
|
||||
unsigned __int64 virtualize_x2apic : 1;
|
||||
unsigned __int64 enable_vpid : 1;
|
||||
unsigned __int64 wbinvd_exiting : 1;
|
||||
unsigned __int64 unrestricted_guest : 1;
|
||||
unsigned __int64 apic_register_virtualization : 1;
|
||||
unsigned __int64 virtual_interrupt_delivery : 1;
|
||||
unsigned __int64 pause_loop_exiting : 1;
|
||||
unsigned __int64 rdrand_exiting : 1;
|
||||
unsigned __int64 enable_invpcid : 1;
|
||||
unsigned __int64 enable_vmfunc : 1;
|
||||
unsigned __int64 vmcs_shadowing : 1;
|
||||
unsigned __int64 enable_encls_exiting : 1;
|
||||
unsigned __int64 rdseed_exiting : 1;
|
||||
unsigned __int64 enable_pml : 1;
|
||||
unsigned __int64 use_virtualization_exception : 1;
|
||||
unsigned __int64 conceal_vmx_from_pt : 1;
|
||||
unsigned __int64 enable_xsave_xrstor : 1;
|
||||
unsigned __int64 reserved_0 : 1;
|
||||
unsigned __int64 mode_based_execute_control_ept : 1;
|
||||
unsigned __int64 reserved_1 : 2;
|
||||
unsigned __int64 use_tsc_scaling : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_entry_control_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 reserved_0 : 2;
|
||||
unsigned __int64 load_dbg_controls : 1;
|
||||
unsigned __int64 reserved_1 : 6;
|
||||
unsigned __int64 ia32e_mode_guest : 1;
|
||||
unsigned __int64 entry_to_smm : 1;
|
||||
unsigned __int64 deactivate_dual_monitor_treament : 1;
|
||||
unsigned __int64 reserved_3 : 1;
|
||||
unsigned __int64 load_ia32_perf_global_control : 1;
|
||||
unsigned __int64 load_ia32_pat : 1;
|
||||
unsigned __int64 load_ia32_efer : 1;
|
||||
unsigned __int64 load_ia32_bndcfgs : 1;
|
||||
unsigned __int64 conceal_vmx_from_pt : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union cr_fixed_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long low;
|
||||
long high;
|
||||
} split;
|
||||
struct
|
||||
{
|
||||
unsigned long low;
|
||||
long high;
|
||||
} u;
|
||||
long long all;
|
||||
};
|
||||
|
||||
union cr8_t
|
||||
{
|
||||
u64 control;
|
||||
struct
|
||||
{
|
||||
u64 task_priority_level : 4;
|
||||
u64 reserved : 59;
|
||||
} bits;
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u64 protection_enable : 1;
|
||||
u64 monitor_coprocessor : 1;
|
||||
u64 emulate_fpu : 1;
|
||||
u64 task_switched : 1;
|
||||
u64 extension_type : 1;
|
||||
u64 numeric_error : 1;
|
||||
u64 reserved1 : 10;
|
||||
u64 write_protect : 1;
|
||||
u64 reserved2 : 1;
|
||||
u64 alignment_mask : 1;
|
||||
u64 reserved3 : 10;
|
||||
u64 not_write_through : 1;
|
||||
u64 cache_disable : 1;
|
||||
u64 paging_enable : 1;
|
||||
u64 reserved4 : 32;
|
||||
};
|
||||
u64 flags;
|
||||
} cr0_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
u64 flags;
|
||||
struct
|
||||
{
|
||||
u64 virtual_mode_extensions : 1;
|
||||
u64 protected_mode_virtual_interrupts : 1;
|
||||
u64 timestamp_disable : 1;
|
||||
u64 debugging_extensions : 1;
|
||||
u64 page_size_extensions : 1;
|
||||
u64 physical_address_extension : 1;
|
||||
u64 machine_check_enable : 1;
|
||||
u64 page_global_enable : 1;
|
||||
u64 performance_monitoring_counter_enable : 1;
|
||||
u64 os_fxsave_fxrstor_support : 1;
|
||||
u64 os_xmm_exception_support : 1;
|
||||
u64 usermode_instruction_prevention : 1;
|
||||
u64 reserved1 : 1;
|
||||
u64 vmx_enable : 1;
|
||||
u64 smx_enable : 1;
|
||||
u64 reserved2 : 1;
|
||||
u64 fsgsbase_enable : 1;
|
||||
u64 pcid_enable : 1;
|
||||
u64 os_xsave : 1;
|
||||
u64 reserved3 : 1;
|
||||
u64 smep_enable : 1;
|
||||
u64 smap_enable : 1;
|
||||
u64 protection_key_enable : 1;
|
||||
u64 reserved4 : 41;
|
||||
};
|
||||
} cr4_t;
|
||||
|
||||
union vmx_exit_control_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 reserved_0 : 2;
|
||||
unsigned __int64 save_dbg_controls : 1;
|
||||
unsigned __int64 reserved_1 : 6;
|
||||
unsigned __int64 host_address_space_size : 1;
|
||||
unsigned __int64 reserved_2 : 2;
|
||||
unsigned __int64 load_ia32_perf_global_control : 1;
|
||||
unsigned __int64 reserved_3 : 2;
|
||||
unsigned __int64 ack_interrupt_on_exit : 1;
|
||||
unsigned __int64 reserved_4 : 2;
|
||||
unsigned __int64 save_ia32_pat : 1;
|
||||
unsigned __int64 load_ia32_pat : 1;
|
||||
unsigned __int64 save_ia32_efer : 1;
|
||||
unsigned __int64 load_ia32_efer : 1;
|
||||
unsigned __int64 save_vmx_preemption_timer_value : 1;
|
||||
unsigned __int64 clear_ia32_bndcfgs : 1;
|
||||
unsigned __int64 conceal_vmx_from_pt : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union vmx_basic_msr_t
|
||||
{
|
||||
unsigned __int64 control;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 vmcs_revision_identifier : 31;
|
||||
unsigned __int64 always_0 : 1;
|
||||
unsigned __int64 vmxon_region_size : 13;
|
||||
unsigned __int64 reserved_1 : 3;
|
||||
unsigned __int64 vmxon_physical_address_width : 1;
|
||||
unsigned __int64 dual_monitor_smi : 1;
|
||||
unsigned __int64 memory_type : 4;
|
||||
unsigned __int64 io_instruction_reporting : 1;
|
||||
unsigned __int64 true_controls : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
typedef struct _vmcs_ctx
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned int all;
|
||||
struct
|
||||
{
|
||||
unsigned int revision_identifier : 31;
|
||||
unsigned int shadow_vmcs_indicator : 1;
|
||||
} bits;
|
||||
} header;
|
||||
unsigned int abort_indicator;
|
||||
char data[0x1000 - 2 * sizeof(unsigned)];
|
||||
} vmcs_ctx, *pvmcs_ctx;
|
||||
|
||||
typedef struct _vmxon_region_ctx
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned int all;
|
||||
struct
|
||||
{
|
||||
unsigned int revision_identifier : 31;
|
||||
} bits;
|
||||
} header;
|
||||
char data[0x1000 - 1 * sizeof(unsigned)];
|
||||
} vmxon_region_ctx, *pvmxon_region_ctx;
|
||||
|
||||
typedef struct _vcpu_ctx
|
||||
{
|
||||
pvmcs_ctx vmcs;
|
||||
u64 vmcs_phys;
|
||||
|
||||
pvmxon_region_ctx vmxon;
|
||||
u64 vmxon_phys;
|
||||
|
||||
u64 host_stack;
|
||||
} vcpu_ctx, * pvcpu_ctx;
|
||||
|
||||
typedef struct _vmx_ctx
|
||||
{
|
||||
u32 vcpu_num;
|
||||
pvcpu_ctx* vcpus;
|
||||
} vmx_ctx, *pvmx_ctx;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
.code
|
||||
readfs proc
|
||||
mov rax, fs
|
||||
ret
|
||||
readfs endp
|
||||
|
||||
readgs proc
|
||||
mov rax, gs
|
||||
ret
|
||||
readgs endp
|
||||
|
||||
reades proc
|
||||
mov rax, es
|
||||
ret
|
||||
reades endp
|
||||
|
||||
readds proc
|
||||
mov rax, ds
|
||||
ret
|
||||
readds endp
|
||||
|
||||
readss proc
|
||||
mov rax, ss
|
||||
ret
|
||||
readss endp
|
||||
|
||||
readcs proc
|
||||
mov rax, cs
|
||||
ret
|
||||
readcs endp
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
#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);
|
@ -0,0 +1,81 @@
|
||||
extern exit_handler : proc
|
||||
|
||||
.code
|
||||
vmxexit_handler proc
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
push rbp ; gotta keep the stack aligned...
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, 0100h ; 16 xmm registers... probably dont need to do all of them...
|
||||
movaps [rsp], xmm0
|
||||
movaps [rsp + 010h], xmm1
|
||||
movaps [rsp + 020h], xmm2
|
||||
movaps [rsp + 030h], xmm3
|
||||
movaps [rsp + 040h], xmm4
|
||||
movaps [rsp + 050h], xmm5
|
||||
movaps [rsp + 060h], xmm6
|
||||
movaps [rsp + 070h], xmm7
|
||||
movaps [rsp + 080h], xmm8
|
||||
movaps [rsp + 090h], xmm9
|
||||
movaps [rsp + 0A0h], xmm10
|
||||
movaps [rsp + 0B0h], xmm11
|
||||
movaps [rsp + 0C0h], xmm12
|
||||
movaps [rsp + 0D0h], xmm13
|
||||
movaps [rsp + 0E0h], xmm14
|
||||
movaps [rsp + 0F0h], xmm15
|
||||
|
||||
mov rcx, rsp
|
||||
sub rsp, 28h ; shadow space or some shit MSVC does it so i do it...
|
||||
call exit_handler
|
||||
add rsp, 28h
|
||||
|
||||
movaps xmm0, [rsp]
|
||||
movaps xmm1, [rsp + 010h]
|
||||
movaps xmm2, [rsp + 020h]
|
||||
movaps xmm3, [rsp + 030h]
|
||||
movaps xmm4, [rsp + 040h]
|
||||
movaps xmm5, [rsp + 050h]
|
||||
movaps xmm6, [rsp + 060h]
|
||||
movaps xmm7, [rsp + 070h]
|
||||
movaps xmm8, [rsp + 080h]
|
||||
movaps xmm9, [rsp + 090h]
|
||||
movaps xmm10, [rsp + 0A0h]
|
||||
movaps xmm11, [rsp + 0B0h]
|
||||
movaps xmm12, [rsp + 0C0h]
|
||||
movaps xmm13, [rsp + 0D0h]
|
||||
movaps xmm14, [rsp + 0E0h]
|
||||
movaps xmm15, [rsp + 0F0h]
|
||||
add rsp, 0100h ; 16 xmm registers... probably dont need to do all of them...
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rbp ; gotta keep the stack aligned...
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
|
||||
vmresume ; resume guest execution...
|
||||
vmxexit_handler endp
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "hv_types.hpp"
|
||||
|
||||
extern "C" auto vmxexit_handler() -> void;
|
||||
extern "C" auto exit_handler(hv::pguest_registers regs) -> void;
|
@ -0,0 +1,105 @@
|
||||
#include "vmxlaunch.hpp"
|
||||
|
||||
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<u64>(&::vmxexit_handler));
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_RSP,
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
auto vmxlaunch::launch() -> void
|
||||
{
|
||||
DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber());
|
||||
DBG_PRINT(" - vmxlaunch result (0 == success): %d\n", __vmx_vmlaunch());
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "segment_intrin.h"
|
||||
#include "vmxexit_handler.h"
|
||||
#include "vmxon.hpp"
|
||||
|
||||
namespace vmxlaunch
|
||||
{
|
||||
auto init_vmcs() -> void;
|
||||
auto launch() -> void;
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
#include "vmxon.hpp"
|
||||
|
||||
namespace vmxon
|
||||
{
|
||||
auto create_vmxon_region(hv::pvcpu_ctx vcpu_ctx) -> void
|
||||
{
|
||||
PHYSICAL_ADDRESS mem_range;
|
||||
mem_range.QuadPart = ~0ull;
|
||||
|
||||
hv::vmx_basic_msr_t vmx_basic;
|
||||
vmx_basic.control = __readmsr(IA32_VMX_BASIC);
|
||||
|
||||
vcpu_ctx->vmxon =
|
||||
reinterpret_cast<hv::pvmxon_region_ctx>(
|
||||
MmAllocateContiguousMemory(PAGE_SIZE, mem_range));
|
||||
|
||||
vcpu_ctx->vmxon_phys =
|
||||
MmGetPhysicalAddress(vcpu_ctx->vmxon).QuadPart;
|
||||
|
||||
RtlSecureZeroMemory(
|
||||
vcpu_ctx->vmxon, PAGE_SIZE);
|
||||
|
||||
vcpu_ctx->vmxon->header
|
||||
.bits
|
||||
.revision_identifier =
|
||||
vmx_basic.bits
|
||||
.vmcs_revision_identifier;
|
||||
}
|
||||
|
||||
auto create_vmcs(hv::pvcpu_ctx vcpu_ctx) -> void
|
||||
{
|
||||
PHYSICAL_ADDRESS mem_range;
|
||||
mem_range.QuadPart = ~0ull;
|
||||
|
||||
hv::vmx_basic_msr_t vmx_basic;
|
||||
vmx_basic.control = __readmsr(IA32_VMX_BASIC);
|
||||
|
||||
vcpu_ctx->vmcs =
|
||||
reinterpret_cast<hv::pvmcs_ctx>(
|
||||
MmAllocateContiguousMemory(PAGE_SIZE, mem_range));
|
||||
|
||||
vcpu_ctx->vmcs_phys =
|
||||
MmGetPhysicalAddress(vcpu_ctx->vmcs).QuadPart;
|
||||
|
||||
RtlSecureZeroMemory(
|
||||
vcpu_ctx->vmcs, PAGE_SIZE);
|
||||
|
||||
vcpu_ctx->vmcs->header
|
||||
.bits
|
||||
.revision_identifier =
|
||||
vmx_basic.bits
|
||||
.vmcs_revision_identifier;
|
||||
}
|
||||
|
||||
auto create_vcpus(hv::pvmx_ctx vmx_ctx) -> void
|
||||
{
|
||||
vmx_ctx->vcpu_num =
|
||||
KeQueryActiveProcessorCountEx(
|
||||
ALL_PROCESSOR_GROUPS);
|
||||
|
||||
// allocate buffer for vcpu pointers...
|
||||
vmx_ctx->vcpus =
|
||||
reinterpret_cast<hv::pvcpu_ctx*>(
|
||||
ExAllocatePool(NonPagedPool,
|
||||
sizeof(hv::pvcpu_ctx) * vmx_ctx->vcpu_num));
|
||||
|
||||
// allocate vcpu for each logical processor along with
|
||||
// vmxon region and vmcs memory for each logical processor...
|
||||
for (auto idx = 0u; idx < g_vmx_ctx->vcpu_num; ++idx)
|
||||
{
|
||||
vmx_ctx->vcpus[idx] =
|
||||
reinterpret_cast<hv::pvcpu_ctx>(
|
||||
ExAllocatePool(NonPagedPool, sizeof hv::vcpu_ctx));
|
||||
|
||||
vmx_ctx->vcpus[idx]->host_stack =
|
||||
reinterpret_cast<u64>(
|
||||
ExAllocatePool(NonPagedPool,
|
||||
PAGE_SIZE * HOST_STACK_PAGES));
|
||||
|
||||
create_vmxon_region(vmx_ctx->vcpus[idx]);
|
||||
create_vmcs(vmx_ctx->vcpus[idx]);
|
||||
|
||||
DBG_PRINT("setup vcpu for processor: %d\n", idx);
|
||||
DBG_PRINT(" - vmxon region (virtual): 0x%p\n", vmx_ctx->vcpus[idx]->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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED1);
|
||||
cr0.flags &= cr_fixed.split.low;
|
||||
__writecr0(cr0.flags);
|
||||
|
||||
cr_fixed.all = __readmsr(IA32_VMX_CR4_FIXED0);
|
||||
cr4.flags = __readcr4();
|
||||
cr4.flags |= cr_fixed.split.low;
|
||||
cr_fixed.all = __readmsr(IA32_VMX_CR4_FIXED1);
|
||||
cr4.flags &= cr_fixed.split.low;
|
||||
__writecr4(cr4.flags);
|
||||
|
||||
cr4.flags = __readcr4();
|
||||
cr4.vmx_enable = true;
|
||||
__writecr4(cr4.flags);
|
||||
|
||||
__try
|
||||
{
|
||||
DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber());
|
||||
|
||||
__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());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "hv_types.hpp"
|
||||
|
||||
namespace vmxon
|
||||
{
|
||||
auto create_vmxon_region(hv::pvcpu_ctx vcpu_ctx) -> void;
|
||||
auto create_vmcs(hv::pvcpu_ctx vcpu_ctx) -> void;
|
||||
auto create_vcpus(hv::pvmx_ctx vmx_ctx) -> void;
|
||||
auto init_vmxon() -> void;
|
||||
|
||||
// vmxroot global object... contains all vcpu information...
|
||||
inline hv::pvmx_ctx g_vmx_ctx;
|
||||
}
|
Loading…
Reference in new issue