Merge pull request 'Voager_EPTHook_Injector' (#1) from Voager_EPTHook_Injector into master

Reviewed-on: #1
master
Zero Hu 2 years ago
commit 3c6418abfb

@ -664,17 +664,34 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="debug.cpp" />
<ClCompile Include="ept.cpp" />
<ClCompile Include="mm.cpp" />
<ClCompile Include="vmexit.cpp" />
<ClCompile Include="vmexit_handler.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="asm.h" />
<ClInclude Include="debug.h" />
<ClInclude Include="ept.h" />
<ClInclude Include="ia32.hpp" />
<ClInclude Include="mm.h" />
<ClInclude Include="types.h" />
<ClInclude Include="vmexit.h" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="x64.asm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='1903|x64'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='1903|x64'">true</DeploymentContent>
<Command Condition="'$(Configuration)|$(Platform)'=='1903|x64'">ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='1903|x64'">$(IntDir)%(fileName).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='1909|x64'">false</ExcludedFromBuild>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='1909|x64'">true</DeploymentContent>
<Command Condition="'$(Configuration)|$(Platform)'=='1909|x64'">ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='1909|x64'">$(IntDir)%(fileName).obj;%(Outputs)</Outputs>
<DeploymentContent>true</DeploymentContent>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

@ -23,6 +23,9 @@
<ClCompile Include="mm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ept.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="types.h">
@ -40,5 +43,16 @@
<ClInclude Include="mm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ept.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="asm.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="x64.asm">
<Filter>Source Files</Filter>
</CustomBuild>
</ItemGroup>
</Project>

@ -0,0 +1,7 @@
#pragma once
#include "types.h"
extern "C" {
unsigned char __stdcall AsmInvept(
_In_ InvEptType invept_type,
_In_ const InvEptDescriptor* invept_descriptor);
}

@ -4,6 +4,7 @@
#include "types.h"
#define PORT_NUM 0x2F8
namespace dbg
{
constexpr char alphabet[] = "0123456789ABCDEF";

@ -0,0 +1,520 @@
#include "asm.h"
#include "ept.h"
#include "mm.h"
VmxStatus UtilInveptGlobal(ept_pointer eptPoint) {
InvEptDescriptor desc = {};
desc.ept_pointer = eptPoint.flags;
desc.reserved1 = 0;
//return VmxStatus::kOk;
return static_cast<VmxStatus>(
AsmInvept(InvEptType::kGlobalInvalidation, &desc));
}
HookInformation* ShpFindPatchInfoByPage(SharedShadowHookData* shared_sh_data, void* address)
{
BOOL haveFound = FALSE;
int i;
for (i = 0; i < MAX_HOOKS; i++)
{
if (PAGE_ALIGN(shared_sh_data->hooks[i].patch_address) == PAGE_ALIGN(address))
{
haveFound = TRUE;
break;
}
}
if (haveFound)
{
return &shared_sh_data->hooks[i];
}
else
{
return nullptr;
}
}
HookInformation* ShpFindPatchInfoBy2MPage(SharedShadowHookData* shared_sh_data, void* address)
{
BOOL haveFound = FALSE;
int i;
for (i = 0; i < MAX_HOOKS; i++)
{
if (PAGE_ALIGN2M(shared_sh_data->hooks[i].patch_address) == PAGE_ALIGN2M(address))
{
haveFound = TRUE;
break;
}
}
if (haveFound)
{
return &shared_sh_data->hooks[i];
}
else
{
return nullptr;
}
}
HookInformation* ShpFindPatchInfoByAddress(SharedShadowHookData* shared_sh_data, void* address)
{
BOOL haveFound = FALSE;
int i;
for (i = 0; i < MAX_HOOKS; i++)
{
if (shared_sh_data->hooks[i].patch_address == address)
{
haveFound = TRUE;
break;
}
}
if (haveFound)
{
return &shared_sh_data->hooks[i];
}
else
{
return nullptr;
}
}
#define EPT_PD_MASK (~((ULONG64)(0x200000 - 1)))
void split_2mb_to_4kb(ept_pointer eptp,guest_phys_t guest_pa,host_phys_t host_pa)
{
int hookNum = 0;
u64 ptPhyAddr = 0;
mm::phys_addr_t guest_phys{ guest_pa };
const auto epml4 = reinterpret_cast<ept_pml4e*>(
map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1g page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
{
dbg::print("ERROR:This is a fucking 1G page\n");
return;
}
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
//dbg::print("epdpt:%llx\n",epdpt);
const auto epd_large =
reinterpret_cast<epde_2mb*>(map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
{
dbg::print("This is a 2 MB page\n");
for (hookNum = 0; hookNum < MAX_HOOKS; hookNum++)
{
PShadowPte pShadowPte = (PShadowPte)&mm::shadow[hookNum];
if ((pShadowPte->pa_base_for_2m & EPT_PD_MASK) == guest_pa) //it already recorded
{
dbg::print("Have Already built the pt\n");
ptPhyAddr = mm::translate((host_virt_t)pShadowPte->shadowPte);
epd_large[guest_phys.pd_index].large_page = FALSE;
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
epd[guest_phys.pd_index].execute_access = 1;
epd[guest_phys.pd_index].read_access = 1;
epd[guest_phys.pd_index].write_access = 1;
epd[guest_phys.pd_index].reserved1 = 0;
epd[guest_phys.pd_index].reserved2 = 0;
epd[guest_phys.pd_index].reserved3 = 0;
epd[guest_phys.pd_index].reserved4 = 0;
epd[guest_phys.pd_index].page_frame_number = ptPhyAddr >> 12; //store
UtilInveptGlobal(eptp);
return;
}
}
for (hookNum = 0; hookNum < MAX_HOOKS; hookNum++)
{
PShadowPte pShadowPte = (PShadowPte)&mm::shadow[hookNum];
if (pShadowPte->pa_base_for_2m == 0) //search for an empty place
{
pShadowPte->pa_base_for_2m = guest_pa;
ptPhyAddr = mm::translate((host_virt_t)pShadowPte->shadowPte);
break;
}
}
//init
ept_pte epte = { 0 };
epte.flags = 0;
epte.read_access = 1;
epte.write_access = 1;
epte.execute_access = 1;
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
ept_pde newEpde = { 0 };
newEpde.flags = 0;
newEpde.execute_access = 1;
newEpde.read_access = 1;
newEpde.write_access = 1;
newEpde.page_frame_number = ptPhyAddr >> 12; //store the phy addr
const auto ept =
reinterpret_cast<ept_pte*>(map_page(
newEpde.page_frame_number << 12, mm::map_type_t::map_src));
for (u64 i = 0; i < 512; i++)
{
epte.page_frame_number = (host_pa + i * PAGE_4KB) >> 12;
ept[i] = epte;
//dbg::print("index:%d point to:%llx\n",i,epte.page_frame_number << 12);
}
epd[guest_phys.pd_index].flags = newEpde.flags;
UtilInveptGlobal(eptp);
}
}
void merge_4kb_to_2mb(ept_pointer eptp, guest_phys_t guest_pa, host_phys_t host_pa)
{
int hookNum = 0;
u64 ptPhyAddr = 0;
mm::phys_addr_t guest_phys{ guest_pa };
const auto epml4 = reinterpret_cast<ept_pml4e*>(
map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1g page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
return;
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
const auto epd_large =
reinterpret_cast<epde_2mb*>(map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
return;
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
const auto ept =
reinterpret_cast<ept_pte*>(mm::map_page(
epd[guest_phys.pd_index].page_frame_number << 12, mm::map_type_t::map_src));
epde_2mb epde = { 0 };
epde.flags = 0;
epde.execute_access = 1;
epde.large_page = 1;
epde.read_access = 1;
epde.write_access = 1;
epde.page_frame_number = host_pa >> 21;
epd_large[guest_phys.pd_index].flags = epde.flags;
//begin to search
UtilInveptGlobal(eptp);
for (hookNum = 0; hookNum < MAX_HOOKS; hookNum++)
{
PShadowPte pShadowPte = (PShadowPte)&mm::shadow[hookNum];
if ((pShadowPte->pa_base_for_2m & EPT_PD_MASK) == (guest_pa & EPT_PD_MASK))
{
pShadowPte->pa_base_for_2m = 0; //marked as unused
break;
}
}
}
void changeEPTAttribute(ept_pointer eptp, guest_phys_t guest_pa,bool bCanExecute)
{
mm::phys_addr_t guest_phys{ guest_pa };
const auto epml4 = reinterpret_cast<ept_pml4e*>(
mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(mm::map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1gb page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
{
dbg::print("[changeEPTAttribute]:1GB page\n");
return;
}
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
const auto epd_large =
reinterpret_cast<epde_2mb*>(mm::map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
{
dbg::print("[changeEPTAttribute]:2MB page\n");
return;
}
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
const auto ept =
reinterpret_cast<ept_pte*>(mm::map_page(
epd[guest_phys.pd_index].page_frame_number << 12, mm::map_type_t::map_src));
if (bCanExecute)
{
dbg::print("set:%llx to can't read or write\n", guest_pa);
ept_pte newEpte = ept[guest_phys.pt_index];
newEpte.execute_access = 1;
newEpte.read_access = 0;
newEpte.write_access = 0;
ept[guest_phys.pt_index].flags = newEpte.flags;
}
else
{
dbg::print("set:%llx to can't execute\n",guest_pa);
ept_pte newEpte = ept[guest_phys.pt_index];
newEpte.execute_access = 0;
newEpte.read_access = 1;
newEpte.write_access = 1;
ept[guest_phys.pt_index].flags = newEpte.flags;
}
UtilInveptGlobal(eptp);
}
void disablePageProtection(ept_pointer eptp, guest_phys_t guest_pa)
{
mm::phys_addr_t guest_phys{ guest_pa };
const auto epml4 = reinterpret_cast<ept_pml4e*>(
mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(mm::map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1gb page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
{
epdpt_large[guest_phys.pdpt_index].execute_access = 1;
epdpt_large[guest_phys.pdpt_index].read_access = 1;
epdpt_large[guest_phys.pdpt_index].write_access = 1;
UtilInveptGlobal(eptp);
//dbg::print("[changeEPTAttribute]:1GB page\n");
return;
}
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
const auto epd_large =
reinterpret_cast<epde_2mb*>(mm::map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
{
epd_large[guest_phys.pd_index].execute_access = 1;
epd_large[guest_phys.pd_index].write_access = 1;
epd_large[guest_phys.pd_index].read_access = 1;
UtilInveptGlobal(eptp);
//dbg::print("[changeEPTAttribute]:2MB page\n");
return;
}
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
const auto ept =
reinterpret_cast<ept_pte*>(mm::map_page(
epd[guest_phys.pd_index].page_frame_number << 12, mm::map_type_t::map_src));
ept[guest_phys.pt_index].execute_access = 1;
ept[guest_phys.pt_index].read_access = 1;
ept[guest_phys.pt_index].write_access = 1;
UtilInveptGlobal(eptp);
}
NTSTATUS VoyagerEptAddFakePage(u64 uHookAddr,u64 uPageRead,u64 uPageExec)
{
PSharedShadowHookData pShadowHook = (PSharedShadowHookData)&mm::ShadowHookData;
PHookInformation pInfo = NULL;
for (int i = 0; i < MAX_HOOKS; i++)
{
if (pShadowHook->hooks[i].isEnable == TRUE)
{
if (pShadowHook->hooks[i].patch_address == (void*)uHookAddr)
{
return STATUS_SUCCESS;
}
}
}
for (int i = 0; i < MAX_HOOKS; i++)
{
if (pShadowHook->hooks[i].isEnable == FALSE)
{
pInfo = &pShadowHook->hooks[i];
break;
}
}
if (!pInfo)
{
return STATUS_UNSUCCESSFUL;
}
dbg::print("Add Hook Addr:%llx\n", uHookAddr);
pInfo->isEnable = TRUE;
pInfo->patch_address = (void*)uHookAddr;
pInfo->pa_base_for_rw = uPageRead;
pInfo->pa_base_for_exec = uPageExec;
return STATUS_SUCCESS;
}
NTSTATUS VoyagerEptDelteFakePage(u64 uHookAddr)
{
PSharedShadowHookData pShadowHook = (PSharedShadowHookData)&mm::ShadowHookData;
PHookInformation pInfo = NULL;
pInfo = ShpFindPatchInfoByAddress(pShadowHook, (void*)uHookAddr);
if (!pInfo)
{
return STATUS_UNSUCCESSFUL;
}
pInfo->isEnable = FALSE;
pInfo->patch_address = 0;
pInfo->pa_base_for_rw = 0;
pInfo->pa_base_for_exec = 0;
return STATUS_SUCCESS;
}
bool map_4k(ept_pointer eptp, guest_phys_t guest_pa, guest_phys_t host_pa)
{
mm::phys_addr_t guest_phys{ guest_pa };
const auto epml4 = reinterpret_cast<ept_pml4e*>(
mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(mm::map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1gb page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
{
dbg::print("[mapError]:1GB page\n");
return false;
}
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
const auto epd_large =
reinterpret_cast<epde_2mb*>(mm::map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
{
dbg::print("[mapError]:2MB page\n");
return false;
}
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
const auto ept =
reinterpret_cast<ept_pte*>(mm::map_page(
epd[guest_phys.pd_index].page_frame_number << 12, mm::map_type_t::map_src));
ept_pte newEpte = { 0 };
newEpte.flags = 0;
newEpte.read_access = 1;
newEpte.write_access = 1;
newEpte.execute_access = 1;
newEpte.page_frame_number = host_pa >> 12;
ept[guest_phys.pt_index].flags = newEpte.flags;
UtilInveptGlobal(eptp);
return true;
}
bool VoyagerHandleEptViolation(EptViolationQualification* eptQualification, void* fault_va)
{
const auto read_failure = (eptQualification->fields.read_access) && (!eptQualification->fields.ept_readable);
const auto write_failure = (eptQualification->fields.write_access) && (!eptQualification->fields.ept_writeable);
const auto exec_failure = (eptQualification->fields.execute_access) && (!eptQualification->fields.ept_executable);
const auto info = ShpFindPatchInfoByPage((PSharedShadowHookData)&mm::ShadowHookData, fault_va);
if (!info) {
dbg::print("Info not found\n");
return false;
}
guest_phys_t uPageExec = info->pa_base_for_exec; //for exec
guest_phys_t uPageRead = info->pa_base_for_rw; //for rw
dbg::print("Have found,ReadPage:%llx,ExecPage:%llx\n", uPageRead,uPageExec);
ept_pointer eptp;
mm::phys_addr_t guest_phys{ uPageExec };
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
const auto epml4 = reinterpret_cast<ept_pml4e*>(
mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src));
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(mm::map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 1gb page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
{
dbg::print("[VoyagerHandleEptViolation]:1GB page\n");
return false;
}
const auto epdpt =
reinterpret_cast<ept_pdpte*>(epdpt_large);
const auto epd_large =
reinterpret_cast<epde_2mb*>(mm::map_page(
epdpt[guest_phys.pdpt_index].page_frame_number << 12, mm::map_type_t::map_src));
// handle 2mb page...
if (epd_large[guest_phys.pd_index].large_page)
{
dbg::print("[VoyagerHandleEptViolation]:2MB page\n");
return false;
}
const auto epd =
reinterpret_cast<ept_pde*>(epd_large);
const auto ept =
reinterpret_cast<ept_pte*>(mm::map_page(
epd[guest_phys.pd_index].page_frame_number << 12, mm::map_type_t::map_src));
if (read_failure || write_failure)
{
dbg::print("read_failure occur\n");
ept[guest_phys.pt_index].read_access = 1;
ept[guest_phys.pt_index].write_access = 1;
ept[guest_phys.pt_index].execute_access = 0;
ept[guest_phys.pt_index].page_frame_number = uPageRead >> 12; //load page for rw
return true;
}
else if (exec_failure)
{
dbg::print("exec_failure occur\n");
ept[guest_phys.pt_index].read_access = 0;
ept[guest_phys.pt_index].write_access = 0;
ept[guest_phys.pt_index].execute_access = 1;
ept[guest_phys.pt_index].page_frame_number = uPageExec >> 12; //load page for exec
return true;
}
return false;
}

@ -0,0 +1,49 @@
#pragma once
#include "types.h"
enum class VmxStatus : unsigned __int8 {
kOk = 0, //!< Operation succeeded
kErrorWithStatus = 1, //!< Operation failed with extended status available
kErrorWithoutStatus = 2, //!< Operation failed without status available
};
#define PAGE_SIZE 0x1000
#define PAGE_SIZE2M PAGE_SIZE * 512
#define PAGE_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_SIZE - 1)))
#define PAGE_ALIGN2M(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_SIZE2M - 1)))
// Contains a single steal hook information
typedef struct HookInformation {
void* patch_address; // An address where a hook is installed
// Physical address of the above two copied pages
ULONG64 pa_base_for_rw;
ULONG64 pa_base_for_exec;
bool isEnable;
}HookInformation, * PHookInformation;
// Data structure shared across all processors
typedef struct SharedShadowHookData {
HookInformation hooks[MAX_HOOKS]; // Hold installed hooks
}SharedShadowHookData, *PSharedShadowHookData;
typedef struct ShadowPte
{
ULONG64 pa_base_for_2m; //±£´æÕâ¸öÒ³±í¶ÔÓ¦µÄ2MÒ³
ept_pte shadowPte[512];
}ShadowPte,*PShadowPte;
//
// EPT entry and common fields
//
VmxStatus UtilInveptGlobal(ept_pointer eptPoint);
NTSTATUS VoyagerEptAddFakePage(u64 uHookAddr, u64 uPageRead, u64 uPageExec);
NTSTATUS VoyagerEptDelteFakePage(u64 uHookAddr);
bool VoyagerHandleEptViolation(EptViolationQualification* eptQualification,void* fault_va);
void changeEPTAttribute(ept_pointer eptp, guest_phys_t guest_pa, bool bCanExecute);
void disablePageProtection(ept_pointer eptp, guest_phys_t guest_pa);
void split_2mb_to_4kb(ept_pointer eptp, guest_phys_t guest_pa, host_phys_t host_pa);
void merge_4kb_to_2mb(ept_pointer eptp, guest_phys_t guest_pa, host_phys_t host_pa);
bool map_4k(ept_pointer eptp,guest_phys_t guest_pa, guest_phys_t host_pa);
HookInformation* ShpFindPatchInfoByPage(SharedShadowHookData* shared_sh_data, void* address);
HookInformation* ShpFindPatchInfoBy2MPage(SharedShadowHookData* shared_sh_data, void* address);
HookInformation* ShpFindPatchInfoByAddress(SharedShadowHookData* shared_sh_data, void* address);

@ -144,7 +144,7 @@ auto mm::translate_guest_physical(guest_phys_t phys_addr, map_type_t map_type) -
const auto epdpt_large =
reinterpret_cast<ept_pdpte_1gb*>(map_page(
epml4[guest_phys.pml4_index].page_frame_number << 12, map_type));
// handle 1gb page...
if (epdpt_large[guest_phys.pdpt_index].large_page)
return (epdpt_large[guest_phys.pdpt_index].page_frame_number
@ -184,7 +184,13 @@ auto mm::init() -> vmxroot_error_t
const auto pt_phys =
translate(reinterpret_cast<u64>(pt));
if (!pdpt_phys || !pd_phys || !pt_phys)
const auto shadHookData_phys =
translate(reinterpret_cast<u64>(&ShadowHookData));
const auto shadow_phys =
translate(reinterpret_cast<u64>(&shadow));
if (!pdpt_phys || !pd_phys || !pt_phys || !shadHookData_phys || !shadow_phys)
return vmxroot_error_t::invalid_host_virtual;
// setup mapping page table entries...

@ -1,6 +1,8 @@
#pragma once
#include "types.h"
#include "debug.h"
#include "ept.h"
#define MAX_CPU_COUNT 256 //最多多少个核
#define SELF_REF_PML4_IDX 510
#define MAPPING_PML4_IDX 100
@ -14,7 +16,8 @@
#pragma section(".pdpt", read, write)
#pragma section(".pd", read, write)
#pragma section(".pt", read, write)
#pragma section(".shadowhook",read,write)
#pragma section(".shadowpte",read,write)
namespace mm
{
enum class map_type_t
@ -145,6 +148,10 @@ namespace mm
__declspec(allocate(".pdpt")) inline pdpte pdpt[512];
__declspec(allocate(".pd")) inline pde pd[512];
__declspec(allocate(".pt")) inline pte pt[512];
__declspec(allocate(".shadowhook")) inline SharedShadowHookData ShadowHookData;
__declspec(allocate(".shadowpte")) inline ShadowPte shadow[MAX_HOOKS];
//__declspec(allocate(".shadMrk")) inline bool shadowMark[256][4];
inline const ppml4e hyperv_pml4{ reinterpret_cast<ppml4e>(SELF_REF_PML4) };

@ -7,7 +7,11 @@
#include <ntstatus.h>
#include "ia32.hpp"
#define MAX_HOOKS 4 //×î¶à¼¸¸öhook
#define VMEXIT_KEY 0xDEADBEEFDEADBEEF
#define VMEXIT_ADDPAGE 0xEEEEEEEABCEEEEEE
#define VMEXIT_DELETEPAGE 0xEEEEEEEABCEEEEEF
#define PAGE_4KB 0x1000
#define PAGE_2MB PAGE_4KB * 512
#define PAGE_1GB PAGE_2MB * 512
@ -30,7 +34,13 @@ enum class vmexit_command_t
write_guest_phys,
copy_guest_virt,
get_dirbase,
translate
translate,
add_shadow_page,
add_shadow_page_phys,
delete_shadow_page,
unhide_shadow_page,
disable_page_protection,
DiablePCID
};
enum class vmxroot_error_t
@ -73,6 +83,36 @@ typedef union _command_t
guest_phys_t phys_addr;
} translate_virt;
struct _addShadowPage
{
guest_virt_t uVirtualAddrToHook;
guest_virt_t uPageRead;
guest_virt_t uPageExecute;
}addShadowPage;
struct _addShadowPagePhys
{
guest_virt_t uVirtualAddrToHook;
guest_phys_t uPageRead;
guest_phys_t uPageExecute;
}addShadowPagePhys;
struct _deleteShaowPage
{
guest_virt_t uVirtualAddrToHook;
}deleteShaowPage;
struct _unHideShaowPage
{
guest_virt_t uVirtualAddrToHook;
}unHideShaowPage;
struct _disablePageProtection
{
guest_phys_t phys_addr;
}disablePageProtection;
guest_phys_t dirbase;
} command_t, * pcommand_t;
@ -120,4 +160,45 @@ typedef struct _voyager_t
} voyager_t, *pvoyager_t;
#pragma pack(pop)
__declspec(dllexport) inline voyager_t voyager_context;
__declspec(dllexport) inline voyager_t voyager_context;
union EptViolationQualification {
ULONG64 all;
struct {
ULONG64 read_access : 1; //!< [0]
ULONG64 write_access : 1; //!< [1]
ULONG64 execute_access : 1; //!< [2]
ULONG64 ept_readable : 1; //!< [3]
ULONG64 ept_writeable : 1; //!< [4]
ULONG64 ept_executable : 1; //!< [5]
ULONG64 ept_executable_for_user_mode : 1; //!< [6]
ULONG64 valid_guest_linear_address : 1; //!< [7]
ULONG64 caused_by_translation : 1; //!< [8]
ULONG64 user_mode_linear_address : 1; //!< [9]
ULONG64 readable_writable_page : 1; //!< [10]
ULONG64 execute_disable_page : 1; //!< [11]
ULONG64 nmi_unblocking : 1; //!< [12]
} fields;
};
enum class InvEptType : ULONG_PTR {
kSingleContextInvalidation = 1,
kGlobalInvalidation = 2,
};
union EptPointer {
ULONG64 all;
struct {
ULONG64 memory_type : 3; //!< [0:2]
ULONG64 page_walk_length : 3; //!< [3:5]
ULONG64 enable_accessed_and_dirty_flags : 1; //!< [6]
ULONG64 reserved1 : 5; //!< [7:11]
ULONG64 pml4_address : 36; //!< [12:48-1]
ULONG64 reserved2 : 16; //!< [48:63]
} fields;
};
struct InvEptDescriptor {
ULONG64 ept_pointer;
ULONG64 reserved1;
};

@ -11,7 +11,7 @@ namespace vmexit
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
const auto command_page =
const auto command_page =
mm::map_guest_virt(guest_dirbase, command_ptr);
return *reinterpret_cast<command_t*>(command_page);
@ -28,7 +28,7 @@ namespace vmexit
const auto command_page =
mm::map_guest_virt(guest_dirbase, command_ptr);
//memcpy((void*)command_page, &command_data, sizeof(command_t));
*reinterpret_cast<command_t*>(command_page) = command_data;
}
}

@ -4,6 +4,6 @@
namespace vmexit
{
auto get_command(guest_virt_t command_ptr) -> command_t;
auto get_command(guest_virt_t command_ptr)->command_t;
auto set_command(guest_virt_t command_ptr, command_t& command_data) -> void;
}

@ -1,5 +1,11 @@
//#include "ept.h"
#include "vmexit.h"
typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS;
#define EPT_PD_MASK (~((ULONG64)(0x200000 - 1)))
#if WINVER > 1803
void vmexit_handler(pcontext_t* context, void* unknown)
#else
@ -21,110 +27,240 @@ void vmexit_handler(pcontext_t context, void* unknown)
{
switch ((vmexit_command_t)guest_registers->rdx)
{
case vmexit_command_t::init_page_tables:
{
guest_registers->rax = (u64) mm::init();
break;
}
case vmexit_command_t::get_dirbase:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
case vmexit_command_t::init_page_tables:
{
dbg::print("init_page_tables:\n");
guest_registers->rax = (u64)mm::init();
break;
}
case vmexit_command_t::get_dirbase:
{
//dbg::print("get_dirbase\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// cr3 can contain other high bits so just to be safe
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
command_data.dirbase = guest_dirbase;
guest_registers->rax = (u64) vmxroot_error_t::error_success;
// cr3 can contain other high bits so just to be safe
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
command_data.dirbase = guest_dirbase;
guest_registers->rax = (u64)vmxroot_error_t::error_success;
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::read_guest_phys:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// from 1809-1909 PCIDE is enabled in CR4 and so cr3 contains some other stuff...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
guest_registers->rax =
(u64) mm::read_guest_phys(
guest_dirbase,
command_data.copy_phys.phys_addr,
command_data.copy_phys.buffer,
command_data.copy_phys.size);
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::write_guest_phys:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// from 1809-1909 PCIDE is enabled in CR4 and so cr3 contains some other stuff...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
guest_registers->rax =
(u64) mm::write_guest_phys(
guest_dirbase,
command_data.copy_phys.phys_addr,
command_data.copy_phys.buffer,
command_data.copy_phys.size);
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::copy_guest_virt:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
auto virt_data = command_data.copy_virt;
guest_registers->rax =
(u64)mm::copy_guest_virt(
virt_data.dirbase_src,
virt_data.virt_src,
virt_data.dirbase_dest,
virt_data.virt_dest,
virt_data.size);
break;
}
case vmexit_command_t::translate:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::read_guest_phys:
{
//dbg::print("read_guest_phys\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// from 1809-1909 PCIDE is enabled in CR4 and so cr3 contains some other stuff...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
command_data.translate_virt.phys_addr =
mm::translate_guest_virtual(guest_dirbase,
command_data.translate_virt.virt_src);
guest_registers->rax =
(u64)mm::read_guest_phys(
guest_dirbase,
command_data.copy_phys.phys_addr,
command_data.copy_phys.buffer,
command_data.copy_phys.size);
guest_registers->rax =
(u64) vmxroot_error_t::error_success;
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::write_guest_phys:
{
//dbg::print("write_guest_phys\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
default:
break;
}
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// from 1809-1909 PCIDE is enabled in CR4 and so cr3 contains some other stuff...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
guest_registers->rax =
(u64)mm::write_guest_phys(
guest_dirbase,
command_data.copy_phys.phys_addr,
command_data.copy_phys.buffer,
command_data.copy_phys.size);
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::copy_guest_virt:
{
//dbg::print("copy_guest_virt\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
auto virt_data = command_data.copy_virt;
guest_registers->rax =
(u64)mm::copy_guest_virt(
virt_data.dirbase_src,
virt_data.virt_src,
virt_data.dirbase_dest,
virt_data.virt_dest,
virt_data.size);
break;
}
case vmexit_command_t::translate:
{
//dbg::print("translate\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
command_data.translate_virt.phys_addr =
mm::translate_guest_virtual(guest_dirbase,
command_data.translate_virt.virt_src);
guest_registers->rax =
(u64)vmxroot_error_t::error_success;
vmexit::set_command(
guest_registers->r8, command_data);
break;
}
case vmexit_command_t::add_shadow_page:
{
dbg::print("add_shadow_page\n");
auto command_data =
vmexit::get_command(guest_registers->r8);
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
// cr3 can contain other high bits so just to be safe
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
cpuid_eax_01 cpuid_value;
__cpuid((int*)&cpuid_value, 1);
UINT32_t uProcessorNum = cpuid_value.cpuid_additional_information.initial_apic_id;
guest_virt_t uAddr = command_data.addShadowPage.uVirtualAddrToHook;
guest_virt_t virtualRead = command_data.addShadowPage.uPageRead;
guest_virt_t virtualExecute = command_data.addShadowPage.uPageExecute;
dbg::print("ProcessorNum:%d,uAddr:%llx,virtualRead:%llx,virtualExecute:%llx\n", uProcessorNum, uAddr, virtualRead, virtualExecute);
guest_phys_t uPageRead = mm::translate_guest_virtual(guest_dirbase, virtualRead, mm::map_type_t::map_src); //save the page for read
guest_phys_t uPageExec = mm::translate_guest_virtual(guest_dirbase, virtualExecute, mm::map_type_t::map_src); //save the page for exec
dbg::print("ReadPhysical:%llx,ExecPhysical:%llx\n", uPageRead,uPageExec);
ept_pointer eptp;
mm::phys_addr_t guest_phys{ uPageExec };
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
VoyagerEptAddFakePage(uAddr, uPageRead, uPageExec); //record hook information
split_2mb_to_4kb(eptp, uPageExec& EPT_PD_MASK, uPageExec& EPT_PD_MASK);
//it's all 4k page now
changeEPTAttribute(eptp, uPageExec, true);//set the page attribute to exec only
break;
}
case vmexit_command_t::add_shadow_page_phys:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
guest_virt_t uAddr = command_data.addShadowPagePhys.uVirtualAddrToHook;
guest_phys_t uPageRead = command_data.addShadowPagePhys.uPageRead; //save the page for read
guest_phys_t uPageExec = command_data.addShadowPagePhys.uPageExecute; //save the page for exec
dbg::print("ReadPhysical:%llx,ExecPhysical:%llx\n", uPageRead, uPageExec);
ept_pointer eptp;
mm::phys_addr_t guest_phys{ uPageExec };
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
VoyagerEptAddFakePage(uAddr, uPageRead, uPageExec); //record hook information
split_2mb_to_4kb(eptp, uPageExec&EPT_PD_MASK, uPageExec&EPT_PD_MASK);
//it's all 4k page now
changeEPTAttribute(eptp, uPageExec, true);//set the page attribute to exec only
break;
}
case vmexit_command_t::delete_shadow_page:
{
dbg::print("delete_shadow_page\n");
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
auto command_data =
vmexit::get_command(guest_registers->r8);
// cr3 can contain other high bits so just to be safe
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
u64 uAddr = command_data.deleteShaowPage.uVirtualAddrToHook; //begin to search for the page
dbg::print("delete addr:%llx\n", uAddr);
PSharedShadowHookData pShadowHook = (PSharedShadowHookData)&mm::ShadowHookData;
PHookInformation pInfo = NULL;
pInfo = ShpFindPatchInfoByAddress(pShadowHook, (void*)uAddr);
if (!pInfo)
{
break;
}
ept_pointer eptp;
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
u64 uPhyExe = pInfo->pa_base_for_exec;
u64 uPhyRW = pInfo->pa_base_for_rw;
map_4k(eptp, uPhyExe, uPhyExe); //remap to the exec page,and set page attribute to R/W only
VoyagerEptDelteFakePage(uAddr); //delete
pInfo = ShpFindPatchInfoBy2MPage((PSharedShadowHookData)&mm::ShadowHookData, (void*)uAddr);
if (!pInfo) //if no other hook information in 2M,then delete the resource
{
dbg::print("merge_4kb_to_2mb\n");
merge_4kb_to_2mb(eptp, uPhyExe & EPT_PD_MASK, uPhyExe & EPT_PD_MASK);
}
break;
}
case vmexit_command_t::unhide_shadow_page:
{
dbg::print("unhide_shadow_page\n");
u64 guest_dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &guest_dirbase);
auto command_data =
vmexit::get_command(guest_registers->r8);
// cr3 can contain other high bits so just to be safe
// get the pfn and bitshift it...
guest_dirbase = cr3{ guest_dirbase }.pml4_pfn << 12;
u64 uAddr = command_data.unHideShaowPage.uVirtualAddrToHook; //begin to search for the page
dbg::print("unHide addr:%llx\n", uAddr);
PSharedShadowHookData pShadowHook = (PSharedShadowHookData)&mm::ShadowHookData;
PHookInformation pInfo = NULL;
pInfo = ShpFindPatchInfoByAddress(pShadowHook, (void*)uAddr);
if (!pInfo)
{
break;
}
ept_pointer eptp;
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
u64 uPhyExe = pInfo->pa_base_for_exec;
u64 uPhyRW = pInfo->pa_base_for_rw;
map_4k(eptp, uPhyExe, uPhyExe); //remap to exec,and set page attribute to RWE
break;
}
case vmexit_command_t::disable_page_protection:
{
auto command_data =
vmexit::get_command(guest_registers->r8);
guest_phys_t uPagePhyAddr = command_data.disablePageProtection.phys_addr;
ept_pointer eptp;
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
disablePageProtection(eptp, uPagePhyAddr);
break;
}
default:
break;
}
// advance instruction pointer...
size_t rip, exec_len;
__vmx_vmread(VMCS_GUEST_RIP, &rip);
@ -133,6 +269,44 @@ void vmexit_handler(pcontext_t context, void* unknown)
return;
}
}
else if (vmexit_reason == VMX_EXIT_REASON_EPT_VIOLATION)
{
//dbg::print("[EPT Violation]\n");
EptViolationQualification exit_qualification;
__vmx_vmread(VMCS_EXIT_QUALIFICATION, (size_t*)&exit_qualification);
u64 fault_pa = 0, fault_va = 0;
__vmx_vmread(VMCS_GUEST_PHYSICAL_ADDRESS, (size_t*)&fault_pa);
if (exit_qualification.fields.valid_guest_linear_address)
{
__vmx_vmread(VMCS_EXIT_GUEST_LINEAR_ADDRESS, (size_t*)&fault_va);
}
else
{
fault_va = 0;
}
if (exit_qualification.fields.ept_readable ||
exit_qualification.fields.ept_writeable ||
exit_qualification.fields.ept_executable)
{
dbg::print("[EPT Violation] fault_va:%llx,fault_pa:%llx\n", fault_va, fault_pa);
ept_pointer eptp;
__vmx_vmread(VMCS_CTRL_EPT_POINTER, (size_t*)&eptp);
// EPT entry is present. Permission violation.
if (exit_qualification.fields.caused_by_translation)
{
bool isHandled = VoyagerHandleEptViolation(&exit_qualification,(void*)fault_va);//replace
if (isHandled)
{
dbg::print("Ept Violation have handled\n");
UtilInveptGlobal(eptp);
return;
}
}
}
}
// call original vmexit handler...
reinterpret_cast<vmexit_handler_t>(

@ -0,0 +1,29 @@
.CONST
VMX_OK EQU 0
VMX_ERROR_WITH_STATUS EQU 1
VMX_ERROR_WITHOUT_STATUS EQU 2
.CODE
; unsigned char __stdcall AsmInvept(
; _In_ InvEptType invept_type,
; _In_ const InvEptDescriptor *invept_descriptor);
AsmInvept PROC
; invept ecx, oword ptr [rdx]
db 66h, 0fh, 38h, 80h, 0ah
jz errorWithCode ; if (ZF) jmp
jc errorWithoutCode ; if (CF) jmp
xor rax, rax ; return VMX_OK
ret
errorWithoutCode:
mov rax, VMX_ERROR_WITHOUT_STATUS
ret
errorWithCode:
mov rax, VMX_ERROR_WITH_STATUS
ret
AsmInvept ENDP
END

@ -27,6 +27,7 @@ auto voyager::init() -> vmxroot_error_t
auto result = hypercall(VMEXIT_KEY, vmexit_command_t::init_page_tables, nullptr);
if (result != vmxroot_error_t::error_success)
return result;
//hypercall(VMEXIT_KEY, vmexit_command_t::DiablePCID, nullptr);
}
}
@ -34,9 +35,44 @@ auto voyager::init() -> vmxroot_error_t
return vmxroot_error_t::error_success;
}
auto voyager::addShadowPage(guest_virt_t uAddr, guest_virt_t uPageRead, guest_virt_t uPageExecute)->vmxroot_error_t
{
command_t command = {0};
command.addShadowPage = { uAddr,uPageRead,uPageExecute };
return hypercall(VMEXIT_KEY,vmexit_command_t::add_shadow_page, &command);
}
auto voyager::addShadowPagePhys(guest_virt_t uAddr, guest_phys_t uPageRead, guest_phys_t uPageExecute)->vmxroot_error_t
{
command_t command = { 0 };
command.addShadowPagePhys = { uAddr,uPageRead,uPageExecute };
return hypercall(VMEXIT_KEY, vmexit_command_t::add_shadow_page_phys, &command);
}
auto voyager::deleteShadowPage(guest_virt_t uAddr)->vmxroot_error_t
{
command_t command = { 0 };
command.deleteShaowPage = { uAddr };
return hypercall(VMEXIT_KEY, vmexit_command_t::delete_shadow_page, &command);
}
auto voyager::unHideShadowPage(guest_virt_t uAddr)->vmxroot_error_t
{
command_t command = { 0 };
command.unHideShaowPage = { uAddr };
return hypercall(VMEXIT_KEY, vmexit_command_t::unhide_shadow_page, &command);
}
auto voyager::disablePageProtection(guest_phys_t phys_addr)->vmxroot_error_t
{
command_t command = { 0 };
command.disablePageProtection.phys_addr = phys_addr;
return hypercall(VMEXIT_KEY, vmexit_command_t::disable_page_protection, &command);
}
auto voyager::current_dirbase()->guest_phys_t
{
command_t command;
command_t command = {0};
auto result = hypercall(VMEXIT_KEY, vmexit_command_t::get_dirbase, &command);
if (result != vmxroot_error_t::error_success)
@ -47,7 +83,7 @@ auto voyager::current_dirbase()->guest_phys_t
auto voyager::translate(guest_virt_t virt_addr) -> guest_phys_t
{
command_t command;
command_t command = {0};
command.translate_virt.virt_src = virt_addr;
const auto result = hypercall(VMEXIT_KEY, vmexit_command_t::translate, &command);
@ -60,14 +96,14 @@ auto voyager::translate(guest_virt_t virt_addr) -> guest_phys_t
auto voyager::read_phys(guest_phys_t phys_addr, guest_virt_t buffer, u64 size) -> vmxroot_error_t
{
command_t command;
command_t command = {0};
command.copy_phys = { phys_addr, buffer, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::read_guest_phys, &command);
}
auto voyager::write_phys(guest_phys_t phys_addr, guest_virt_t buffer, u64 size) -> vmxroot_error_t
{
command_t command;
command_t command = {0};
command.copy_phys = { phys_addr, buffer, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::write_guest_phys, &command);
}
@ -75,7 +111,7 @@ auto voyager::write_phys(guest_phys_t phys_addr, guest_virt_t buffer, u64 size)
auto voyager::copy_virt(guest_phys_t dirbase_src, guest_virt_t virt_src, guest_phys_t dirbase_dest,
guest_virt_t virt_dest, u64 size) -> vmxroot_error_t
{
command_t command;
command_t command = {0};
command.copy_virt = { dirbase_src, virt_src, dirbase_dest, virt_dest, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::copy_guest_virt, &command);
}

@ -27,7 +27,13 @@ namespace voyager
write_guest_phys,
copy_guest_virt,
get_dirbase,
translate
translate,
add_shadow_page,
add_shadow_page_phys,
delete_shadow_page,
unhide_shadow_page,
disable_page_protection,
DiablePCID
};
enum class vmxroot_error_t
@ -70,6 +76,35 @@ namespace voyager
guest_phys_t phys_addr;
} translate_virt;
struct _addShadowPage
{
guest_virt_t uVirtualAddrToHook;
guest_virt_t uPageRead;
guest_virt_t uPageExecute;
}addShadowPage;
struct _addShadowPagePhys
{
guest_virt_t uVirtualAddrToHook;
guest_phys_t uPageRead;
guest_phys_t uPageExecute;
}addShadowPagePhys;
struct _deleteShaowPage
{
guest_virt_t uVirtualAddrToHook;
}deleteShaowPage;
struct _unHideShaowPage
{
guest_virt_t uVirtualAddrToHook;
}unHideShaowPage;
struct _disablePageProtection
{
guest_phys_t phys_addr;
}disablePageProtection;
guest_phys_t dirbase;
} command_t, * pcommand_t;
@ -79,6 +114,15 @@ namespace voyager
/// </summary>
extern "C" auto hypercall(u64 key, vmexit_command_t, pcommand_t command)->vmxroot_error_t;
auto addShadowPage(guest_virt_t uAddr, guest_virt_t uPageRead, guest_virt_t uPageExecute)->vmxroot_error_t;
auto addShadowPagePhys(guest_virt_t uAddr, guest_phys_t uPageRead, guest_phys_t uPageExecute)->vmxroot_error_t;
auto deleteShadowPage(guest_virt_t uAddr)->vmxroot_error_t;
auto unHideShadowPage(guest_virt_t uAddr)->vmxroot_error_t;
auto disablePageProtection(guest_phys_t phys_addr)->vmxroot_error_t;
/// <summary>
/// gets the current cores CR3 value (current address space pml4)...
/// </summary>

@ -53,6 +53,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

Loading…
Cancel
Save