init commit

merge-requests/1/head
xerox 3 years ago
parent da1654dd09
commit 06af7e9dab

@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30621.155
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bluepill", "bluepill.vcxproj", "{881CCCA6-80EB-486F-8923-4F4B7DD41F9A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.ActiveCfg = Release|x64
{881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.Build.0 = Release|x64
{881CCCA6-80EB-486F-8923-4F4B7DD41F9A}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {22636420-0DC7-4CDD-8C4B-01D117B2C331}
EndGlobalSection
EndGlobal

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{881CCCA6-80EB-486F-8923-4F4B7DD41F9A}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>hypervisor</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<ProjectName>bluepill</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<TreatLinkerWarningAsErrors>false</TreatLinkerWarningAsErrors>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="entry.cpp" />
<ClCompile Include="exit_handler.cpp" />
<ClCompile Include="vmxlaunch.cpp" />
<ClCompile Include="vmxon.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ia32.hpp" />
<ClInclude Include="segment_intrin.h" />
<ClInclude Include="hv_types.hpp" />
<ClInclude Include="vmxexit_handler.h" />
<ClInclude Include="vmxlaunch.hpp" />
<ClInclude Include="vmxon.hpp" />
</ItemGroup>
<ItemGroup>
<MASM Include="segment_intrin.asm" />
<MASM Include="vmxexit_handler.asm" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

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

21410
ia32.hpp

File diff suppressed because it is too large Load Diff

@ -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…
Cancel
Save