Replace vmexit_handler.cpp

Voager_EPTHook_Injector
Zero Hu 2 years ago
parent 037a7e8c1b
commit db8bc73132

@ -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>(

Loading…
Cancel
Save