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