diff --git a/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj b/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj index cd82d24..2defcf8 100644 --- a/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj +++ b/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj @@ -664,17 +664,34 @@ + + + + + + false + Document + true + ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm + $(IntDir)%(fileName).obj;%(Outputs) + false + true + ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm + $(IntDir)%(fileName).obj;%(Outputs) + true + + diff --git a/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj.filters b/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj.filters index 30ce426..eeec10c 100644 --- a/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj.filters +++ b/Voyager/PayLoad (Intel)/PayLoad (Intel).vcxproj.filters @@ -23,6 +23,9 @@ Source Files + + Source Files + @@ -40,5 +43,16 @@ Header Files + + Header Files + + + Header Files + + + + + Source Files + \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/asm.h b/Voyager/PayLoad (Intel)/asm.h new file mode 100644 index 0000000..38b6d6f --- /dev/null +++ b/Voyager/PayLoad (Intel)/asm.h @@ -0,0 +1,7 @@ +#pragma once +#include "types.h" +extern "C" { + unsigned char __stdcall AsmInvept( + _In_ InvEptType invept_type, + _In_ const InvEptDescriptor* invept_descriptor); +} \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/debug.h b/Voyager/PayLoad (Intel)/debug.h index fda84d7..b551417 100644 --- a/Voyager/PayLoad (Intel)/debug.h +++ b/Voyager/PayLoad (Intel)/debug.h @@ -4,6 +4,7 @@ #include "types.h" #define PORT_NUM 0x2F8 + namespace dbg { constexpr char alphabet[] = "0123456789ABCDEF"; diff --git a/Voyager/PayLoad (Intel)/ept.cpp b/Voyager/PayLoad (Intel)/ept.cpp new file mode 100644 index 0000000..c21810f --- /dev/null +++ b/Voyager/PayLoad (Intel)/ept.cpp @@ -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( + 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( + map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + //dbg::print("epdpt:%llx\n",epdpt); + const auto epd_large = + reinterpret_cast(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(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(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(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( + map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + + const auto epd_large = + reinterpret_cast(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(epd_large); + + const auto ept = + reinterpret_cast(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( + mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + + const auto epd_large = + reinterpret_cast(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(epd_large); + + const auto ept = + reinterpret_cast(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( + mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + + const auto epd_large = + reinterpret_cast(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(epd_large); + + const auto ept = + reinterpret_cast(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( + mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + + const auto epd_large = + reinterpret_cast(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(epd_large); + + const auto ept = + reinterpret_cast(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( + mm::map_page(eptp.page_frame_number << 12, mm::map_type_t::map_src)); + const auto epdpt_large = + reinterpret_cast(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(epdpt_large); + + const auto epd_large = + reinterpret_cast(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(epd_large); + + const auto ept = + reinterpret_cast(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; +} \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/ept.h b/Voyager/PayLoad (Intel)/ept.h new file mode 100644 index 0000000..b19b192 --- /dev/null +++ b/Voyager/PayLoad (Intel)/ept.h @@ -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); \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/mm.cpp b/Voyager/PayLoad (Intel)/mm.cpp index fd0e729..8ad2ad3 100644 --- a/Voyager/PayLoad (Intel)/mm.cpp +++ b/Voyager/PayLoad (Intel)/mm.cpp @@ -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(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(pt)); - if (!pdpt_phys || !pd_phys || !pt_phys) + const auto shadHookData_phys = + translate(reinterpret_cast(&ShadowHookData)); + + const auto shadow_phys = + translate(reinterpret_cast(&shadow)); + + if (!pdpt_phys || !pd_phys || !pt_phys || !shadHookData_phys || !shadow_phys) return vmxroot_error_t::invalid_host_virtual; // setup mapping page table entries... diff --git a/Voyager/PayLoad (Intel)/mm.h b/Voyager/PayLoad (Intel)/mm.h index 099850c..827f6fe 100644 --- a/Voyager/PayLoad (Intel)/mm.h +++ b/Voyager/PayLoad (Intel)/mm.h @@ -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(SELF_REF_PML4) }; diff --git a/Voyager/PayLoad (Intel)/types.h b/Voyager/PayLoad (Intel)/types.h index c3e7c79..9b3f94b 100644 --- a/Voyager/PayLoad (Intel)/types.h +++ b/Voyager/PayLoad (Intel)/types.h @@ -7,7 +7,11 @@ #include #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; \ No newline at end of file +__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; +}; \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/vmexit.cpp b/Voyager/PayLoad (Intel)/vmexit.cpp index cc7a08d..219a110 100644 --- a/Voyager/PayLoad (Intel)/vmexit.cpp +++ b/Voyager/PayLoad (Intel)/vmexit.cpp @@ -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_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_page) = command_data; } } \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/vmexit.h b/Voyager/PayLoad (Intel)/vmexit.h index 8049ff7..28edac9 100644 --- a/Voyager/PayLoad (Intel)/vmexit.h +++ b/Voyager/PayLoad (Intel)/vmexit.h @@ -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; } \ No newline at end of file diff --git a/Voyager/PayLoad (Intel)/vmexit_handler.cpp b/Voyager/PayLoad (Intel)/vmexit_handler.cpp index b456ccf..97ccd5c 100644 --- a/Voyager/PayLoad (Intel)/vmexit_handler.cpp +++ b/Voyager/PayLoad (Intel)/vmexit_handler.cpp @@ -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( diff --git a/Voyager/PayLoad (Intel)/x64.asm b/Voyager/PayLoad (Intel)/x64.asm new file mode 100644 index 0000000..86ee849 --- /dev/null +++ b/Voyager/PayLoad (Intel)/x64.asm @@ -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 diff --git a/Voyager/libvoyager/libvoyager.cpp b/Voyager/libvoyager/libvoyager.cpp index 31bb227..83c2dff 100644 --- a/Voyager/libvoyager/libvoyager.cpp +++ b/Voyager/libvoyager/libvoyager.cpp @@ -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); } \ No newline at end of file diff --git a/Voyager/libvoyager/libvoyager.hpp b/Voyager/libvoyager/libvoyager.hpp index aa1e7b3..a4b1dc7 100644 --- a/Voyager/libvoyager/libvoyager.hpp +++ b/Voyager/libvoyager/libvoyager.hpp @@ -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 /// 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; /// /// gets the current cores CR3 value (current address space pml4)... /// diff --git a/Voyager/libvoyager/libvoyager.vcxproj b/Voyager/libvoyager/libvoyager.vcxproj index ac1f80d..7e42696 100644 --- a/Voyager/libvoyager/libvoyager.vcxproj +++ b/Voyager/libvoyager/libvoyager.vcxproj @@ -53,6 +53,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreaded Console