Skip to content

Commit

Permalink
asdasd
Browse files Browse the repository at this point in the history
  • Loading branch information
MellowNight2 committed Mar 8, 2022
1 parent f2c18b8 commit 71e356e
Show file tree
Hide file tree
Showing 44 changed files with 195 additions and 116 deletions.
3 changes: 0 additions & 3 deletions AMD-Hypervisor/hypervisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ struct Hypervisor
uintptr_t noexecute_ncr3;
uintptr_t tertiary_cr3;

struct NptHookEntry* first_npt_hook;
struct SplitTlbHook* first_itlb_hook;

PHYSICAL_MEMORY_RANGE phys_mem_range[12];
CoreVmcbData* vcpu_data[32];
int core_count;
Expand Down
6 changes: 4 additions & 2 deletions AMD-Hypervisor/itlb_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ namespace TlbHooks
}
}

void HandlePageFaultTlb(CoreVmcbData* vcpu, GPRegs* guest_regs)
bool HandlePageFaultTlb(CoreVmcbData* vcpu, GPRegs* guest_regs)
{
auto fault_address = (void*)vcpu->guest_vmcb.control_area.ExitInfo2;

Expand All @@ -163,7 +163,7 @@ namespace TlbHooks

InjectException(vcpu, 14, error_code.as_uint32);

return;
return false;
}

/* get back to this RIP once TLB entries have been added */
Expand Down Expand Up @@ -202,5 +202,7 @@ namespace TlbHooks

vcpu->guest_vmcb.save_state_area.Rip = (uintptr_t)hook_entry->read_gadget;
}

return true;
}
};
3 changes: 2 additions & 1 deletion AMD-Hypervisor/itlb_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ namespace TlbHooks

void Init();

void HandlePageFaultTlb(
bool HandlePageFaultTlb(
CoreVmcbData* vcpu,
GPRegs* guest_regs
);


void HandleTlbHookBreakpoint(
CoreVmcbData* vcpu
);
Expand Down
7 changes: 4 additions & 3 deletions AMD-Hypervisor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
#include "logging.h"
#include "disassembly.h"
#include "prepare_vm.h"
#include "vmexit.h"

extern "C" void __stdcall LaunchVm(void* vm_launch_params);
extern "C" int __stdcall svm_vmmcall(VMMCALL_ID vmmcall_id, ...);

extern "C" void __stdcall LaunchVm(
void* vm_launch_params
);

bool VirtualizeAllProcessors()
{
Expand Down
69 changes: 40 additions & 29 deletions AMD-Hypervisor/npt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,91 @@
#include "logging.h"
#include "hypervisor.h"

void HandleNestedPageFault(CoreVmcbData* VpData, GPRegs* GuestContext)
void HandleNestedPageFault(CoreVmcbData* vcpu_data, GPRegs* GuestContext)
{
NestedPageFaultInfo1 exit_info1;
exit_info1.flags = VpData->guest_vmcb.control_area.ExitInfo1;
PHYSICAL_ADDRESS faulting_physical;
faulting_physical.QuadPart = vcpu_data->guest_vmcb.control_area.ExitInfo2;

auto faulting_virtual = MmGetVirtualForPhysical(faulting_physical);

uintptr_t fail_address = VpData->guest_vmcb.control_area.ExitInfo2;
NestedPageFaultInfo1 exit_info1;
exit_info1.as_uint64 = vcpu_data->guest_vmcb.control_area.ExitInfo1;

PHYSICAL_ADDRESS NCr3;
NCr3.QuadPart = VpData->guest_vmcb.control_area.NCr3;
NCr3.QuadPart = vcpu_data->guest_vmcb.control_area.NCr3;

auto GuestRip = VpData->guest_vmcb.save_state_area.Rip;
auto GuestRip = vcpu_data->guest_vmcb.save_state_area.Rip;

if (exit_info1.fields.valid == 0)
{
int num_bytes = VpData->guest_vmcb.control_area.NumOfBytesFetched;
int num_bytes = vcpu_data->guest_vmcb.control_area.NumOfBytesFetched;

auto insn_bytes = VpData->guest_vmcb.control_area.GuestInstructionBytes;
auto insn_bytes = vcpu_data->guest_vmcb.control_area.GuestInstructionBytes;

auto pml4_base = (PML4E_64*)MmGetVirtualForPhysical(NCr3);

auto pte = AssignNPTEntry((PML4E_64*)pml4_base, fail_address, true);
auto pte = AssignNPTEntry((PML4E_64*)pml4_base, faulting_physical.QuadPart, true);

return;
}

if (exit_info1.fields.execute == 1)
{
auto nptHook = NptHooks::FindByHooklessPhysicalPage(fail_address);
auto npt_hook = NptHooks::ForEachHook(
[](NptHooks::NptHook* hook_entry, void* data) -> bool {

if (PAGE_ALIGN(data) == PAGE_ALIGN(hook_entry->hook_address))
{
return true;
}

bool Switch = true;
}, faulting_virtual
);

int length = 16;
bool switch_ncr3 = true;

int insn_len = 16;

/* handle cases where an instruction is split across 2 pages */

if (PAGE_ALIGN(GuestRip + length) != PAGE_ALIGN(GuestRip))
if (PAGE_ALIGN(GuestRip + insn_len) != PAGE_ALIGN(GuestRip))
{
PT_ENTRY_64* N_Pte = Utils::GetPte((void*)
MmGetPhysicalAddress(PAGE_ALIGN(GuestRip)).QuadPart, NCr3.QuadPart);
auto page1 = MmGetPhysicalAddress(PAGE_ALIGN(GuestRip)).QuadPart;
auto page2 = MmGetPhysicalAddress(PAGE_ALIGN(GuestRip + insn_len)).QuadPart;

PT_ENTRY_64* N_Pte2 = Utils::GetPte((void*)
MmGetPhysicalAddress(PAGE_ALIGN(GuestRip + length)).QuadPart, NCr3.QuadPart);
auto npte1 = Utils::GetPte((void*)page1, NCr3.QuadPart);
auto npte2 = Utils::GetPte((void*)page2, NCr3.QuadPart);


N_Pte->ExecuteDisable = 0;
N_Pte2->ExecuteDisable = 0;
npte1->ExecuteDisable = 0;
npte2->ExecuteDisable = 0;

Switch = false;
switch_ncr3 = false;
}

/* clean ncr3 cache */

VpData->guest_vmcb.control_area.VmcbClean &= ~(1ULL << 4);
//VpData->guest_vmcb.control_area.TlbControl = 3;
vcpu_data->guest_vmcb.control_area.VmcbClean &= ~(1ULL << 4);
vcpu_data->guest_vmcb.control_area.TlbControl = 3;

/* switch to hook CR3, with hooks mapped or switch to innocent CR3, without any hooks */
if (Switch)
if (switch_ncr3)
{
if (nptHook)
if (npt_hook)
{
VpData->guest_vmcb.control_area.NCr3 = hypervisor->noexecute_ncr3;
vcpu_data->guest_vmcb.control_area.NCr3 = hypervisor->noexecute_ncr3;
}
else
{
VpData->guest_vmcb.control_area.NCr3 = hypervisor->normal_ncr3;
vcpu_data->guest_vmcb.control_area.NCr3 = hypervisor->normal_ncr3;
}
}
}
}

/* guest physical addresses are 1:1 mapped to host physical
addresses
/* gPTE pfn would be equal to nPTE pfn,
because guest physical addresses are 1:1 mapped to host physical
*/

void* AllocateNewTable(PML4E_64* PageEntry)
{
void* Table = ExAllocatePoolZero(NonPagedPool, PAGE_SIZE, 'ENON');
Expand Down
74 changes: 57 additions & 17 deletions AMD-Hypervisor/npt_hook.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "npt_hook.h"
#include "logging.h"

namespace NptHooks
{
Expand All @@ -18,48 +19,87 @@ namespace NptHooks
auto hook_entry = &first_npt_hook;

/* reserve memory for hooks because we can't allocate memory in VM root */
__debugbreak();

int max_hooks = 20;

for (int i = 0; i < max_hooks; hook_entry = hook_entry->next_hook, ++i)
{
auto hookless_page = ExAllocatePool(NonPagedPool, PAGE_SIZE);
auto hooked_page = ExAllocatePoolZero(NonPagedPool, PAGE_SIZE, 'ENON');

hook_entry->next_hook = (NptHook*)ExAllocatePool(NonPagedPool, sizeof(NptHook));
hook_entry->next_hook->hooked_npte = Utils::GetPte(hookless_page, cr3.AddressOfPageDirectory << PAGE_SHIFT);
hook_entry->next_hook->hooked_npte = Utils::GetPte(hooked_page, cr3.AddressOfPageDirectory << PAGE_SHIFT);
}

hook_count = 0;
}

NptHook* SetNptHook(void* address, uint8_t* patch, size_t patch_len)
NptHook* ForEachHook(bool(HookCallback)(NptHook* hook_entry, void* data), void* callback_data)
{
auto hook_entry = &first_npt_hook;

for (int i = 0; i < hook_count; hook_entry = hook_entry->next_hook, ++i)
{
if (HookCallback(hook_entry, callback_data))
{
return hook_entry;
}
}
return 0;
}

NptHook* SetNptHook(CoreVmcbData* VpData, void* address, uint8_t* patch, size_t patch_len)
{
auto hook_entry = &first_tlb_hook;
auto hook_entry = &first_npt_hook;

for (int i = 0; i < hook_count; hook_entry = hook_entry->next_hook, ++i)
{
}

Utils::LockPages(address, IoReadAccess);
/* get the guest pte and physical address of the hooked page */

auto physical_addr = (void*)MmGetPhysicalAddress(address).QuadPart;
auto guest_pte = Utils::GetPte(address, VpData->guest_vmcb.save_state_area.Cr3);

hook_entry->hookless_npte = Utils::GetPte(physical_addr, hypervisor->normal_ncr3);
hook_entry->hooked_npte = Utils::GetPte(physical_addr, hypervisor->SecondaryNCr3);
auto physical_page = (uintptr_t)(guest_pte->PageFrameNumber << PAGE_SHIFT);

if (guest_pte->LargePage)
{
PHYSICAL_ADDRESS phys_page;
phys_page.QuadPart = (uintptr_t)physical_page;

auto large_page_offset = (uint8_t*)PAGE_ALIGN(address) - MmGetVirtualForPhysical(phys_page);

physical_page += large_page_offset;
}

/* get the nested pte of the guest physical address */

hook_entry->hook_address = address;
hook_entry->hookless_npte = Utils::GetPte((void*)physical_page, hypervisor->normal_ncr3);


/* get the nested pte of the guest physical address in the 2nd NCR3, and map it to our hook page */

auto hooked_npte = Utils::GetPte((void*)physical_page, hypervisor->noexecute_ncr3);

hooked_npte->PageFrameNumber = hook_entry->hooked_npte->PageFrameNumber;
hooked_npte->ExecuteDisable = 0;

auto hooked_copy = Utils::VirtualAddrFromPfn(hooked_npte->PageFrameNumber);

auto hooked_copy = ExAllocatePool(NonPagedPool, PAGE_SIZE);
auto page_offset = (uintptr_t)address & (PAGE_SIZE - 1);


memcpy(hooked_copy, address, PAGE_SIZE);
/* place our hook in the copied page for the 2nd NCR3 */

memcpy(hooked_copy, PAGE_ALIGN(address), PAGE_SIZE);
memcpy((uint8_t*)hooked_copy + page_offset, patch, patch_len);

hook_entry->hooked_npte->ExecuteDisable = 0;
hook_entry->hookless_npte->ExecuteDisable = 1;

/* gPTE pfn would be equal to nPTE pfn,
as guest physical addresses are 1:1 mapped to host physical
*/
hook_entry->hooked_npte->PageFrameNumber = Utils::PfnFromVirtualAddr(hooked_copy);
VpData->guest_vmcb.control_area.TlbControl = 3;

hook_entry->hookless_npte->ExecuteDisable = 1;
hook_count += 1;

return hook_entry;
}
};
5 changes: 4 additions & 1 deletion AMD-Hypervisor/npt_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ namespace NptHooks
struct NptHook
{
struct NptHook* next_hook;
void* hook_address;
PT_ENTRY_64* hookless_npte;
PT_ENTRY_64* hooked_npte;
};

extern int hook_count;
extern NptHook first_npt_hook;

void SetNptHook();
NptHook* SetNptHook(CoreVmcbData* VpData, void* address, uint8_t* patch, size_t patch_len);
NptHook* ForEachHook(bool(HookCallback)(NptHook* hook_entry, void* data), void* callback_data);

void Init();
};
21 changes: 6 additions & 15 deletions AMD-Hypervisor/prepare_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,24 +162,18 @@ void SetupTssIst()
gdtr.base + (selector.Index * 8));

auto base = (uintptr_t)(
seg_descriptor.base_address_low +
(seg_descriptor.base_address_middle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) +
(seg_descriptor.base_address_high << SEGMENT__BASE_ADDRESS_HIGH_BIT)
seg_descriptor.BaseAddressLow +
(seg_descriptor.BaseAddressMiddle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) +
(seg_descriptor.BaseAddressHigh << SEGMENT__BASE_ADDRESS_HIGH_BIT)
);

if (!seg_descriptor.descriptor_type)
if (!seg_descriptor.DescriptorType)
{
base += ((uint64_t)seg_descriptor.base_address_upper << 32);
base += ((uint64_t)seg_descriptor.BaseAddressUpper << 32);
}

auto tss_base = (TaskStateSegment*)base;

DbgPrint("gdtr.base %p \n", gdtr.base);
DbgPrint("selector.Index %p \n", selector.Index);
DbgPrint("seg_descriptor.baselow %p \n", seg_descriptor.base_address_low);
DbgPrint("seg_descriptor.BaseMiddle %p \n", seg_descriptor.base_address_middle);
DbgPrint("seg_descriptor.BaseHigh %p \n", seg_descriptor.base_address_high);

/* Find free IST entry for page fault */

int idx = 0;
Expand Down Expand Up @@ -259,15 +253,12 @@ void ConfigureProcessor(CoreVmcbData* core_data, CONTEXT* context_record)
InterceptVector2 intercept_vector2;

intercept_vector2.intercept_pf = 1;
intercept_vector2.intercept_bp = 1;
// intercept_vector2.intercept_bp = 1;

core_data->guest_vmcb.control_area.InterceptException = intercept_vector2.as_int32;

core_data->guest_vmcb.control_area.GuestAsid = 1;

VpData->guest_vmcb.control_area.NCr3 = hypervisor->normal_ncr3;
VpData->guest_vmcb.control_area.NpEnable = (1UL << 0);

core_data->guest_vmcb.save_state_area.Cr0 = __readcr0();
core_data->guest_vmcb.save_state_area.Cr2 = __readcr2();
core_data->guest_vmcb.save_state_area.Cr3 = __readcr3();
Expand Down
2 changes: 2 additions & 0 deletions AMD-Hypervisor/runsdvui.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd /d "C:\Users\lolxd\source\repos\AMD-Hypervisor\AMD-Hypervisor" &msbuild "AMD-Hypervisor.vcxproj" /t:sdvViewer /p:configuration="Release" /p:platform="x64" /p:SolutionDir="C:\Users\lolxd\source\repos\AMD-Hypervisor"
exit %errorlevel%
Empty file.
4 changes: 2 additions & 2 deletions AMD-Hypervisor/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ namespace Utils
{
page_table_callback((PT_ENTRY_64*)pde);
}

if ((pde->Present == FALSE) || (pde->LargePage != FALSE))
if ((pde->Present == FALSE) || pde->LargePage == TRUE)
{
return (PT_ENTRY_64*)pde;
}
Expand Down
5 changes: 3 additions & 2 deletions AMD-Hypervisor/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ namespace Utils
with this virtual address
*/
PT_ENTRY_64* GetPte(
void* virtual_addr,
uintptr_t pml4_base_pa,
void* virtual_address,
uintptr_t pml4_base_pa,
int (*page_table_callback)(PT_ENTRY_64*) = NULL
);


PT_ENTRY_64* GetPte(
void* virtual_address,
uintptr_t pml4_base_pa,
Expand Down
Loading

1 comment on commit 71e356e

@MellowNight2
Copy link
Collaborator Author

@MellowNight2 MellowNight2 commented on 71e356e Mar 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the commit which contains code for getting the small page from a large page using the guest CR3.

When I am working with nested page tables in the vmexit handler, I have to make sure that I am using the correct CR3 context for guest physical address translations. Instead of using MmGetPhysicalAddress which uses the VM root CR3 (usually 0x1AD000), I have to use GetPte with the guest CR3 value to get the physical address of the small page inside of a large page. If I want to read/write from this physical address, I will have to set the PFN of a page mapping window to the physical address of the small page.

I can look at minivisor, pagewalkr, or physmem-scanner, to quickly set up code for mapping physical pages.

Please sign in to comment.