HyperDbg Debugger
Loading...
Searching...
No Matches
EptHook.c File Reference

Implementation of different EPT hidden hooks functions. More...

#include "pch.h"

Functions

_Must_inspect_result_ _Success_ (return==TRUE)
 Check whether the desired PhysicalAddress is already in the g_EptState->HookedPagesList hooks or not.
VOID EptHookReservePreallocatedPoolsForEptHooks (UINT32 Count)
 Reserve pre-allocated pools for EPT hooks.
VOID EptHookAllocateExtraHookingPagesForMemoryMonitorsAndExecEptHooks (UINT32 Count)
 Allocate (reserve) extra pages for storing details of page hooks for memory monitor and regular hidden breakpoit exec EPT hooks.
PVOID ExAllocatePoolWithTagHook (POOL_TYPE PoolType, SIZE_T NumberOfBytes, ULONG Tag)
 Hook function that HooksExAllocatePoolWithTag.
BOOLEAN EptHookPerformPageHook (VIRTUAL_MACHINE_STATE *VCpu, PVOID TargetAddress, CR3_TYPE ProcessCr3)
 The main function that performs EPT page hook with hidden breakpoint.
BOOLEAN EptHookPerformHook (PVOID TargetAddress, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot)
 This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on exception bitmap.
BOOLEAN EptHook (PVOID TargetAddress, UINT32 ProcessId)
 This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on exception bitmap.
BOOLEAN EptHookFromVmxRoot (PVOID TargetAddress)
 This function invokes a direct VMCALL to setup the hook.
BOOLEAN EptHookRestoreSingleHookToOriginalEntry (VIRTUAL_MACHINE_STATE *VCpu, SIZE_T PhysicalAddress, UINT64 OriginalEntry)
 Remove and Invalidate Hook in TLB (Hidden Detours and if counter of hidden breakpoint is zero).
VOID EptHookRestoreAllHooksToOriginalEntry (VIRTUAL_MACHINE_STATE *VCpu)
 Remove and Invalidate Hook in TLB.
VOID EptHookWriteAbsoluteJump (PCHAR TargetBuffer, SIZE_T TargetAddress)
 Write an absolute x64 jump to an arbitrary address to a buffer.
VOID EptHookWriteAbsoluteJump2 (PCHAR TargetBuffer, SIZE_T TargetAddress)
 Write an absolute x64 jump to an arbitrary address to a buffer.
BOOLEAN EptHookInstructionMemory (PEPT_HOOKED_PAGE_DETAIL Hook, CR3_TYPE ProcessCr3, PVOID TargetFunction, PVOID TargetFunctionInSafeMemory, PVOID HookFunction)
 Hook instructions.
BOOLEAN EptHookPerformPageHookMonitorAndInlineHook (VIRTUAL_MACHINE_STATE *VCpu, PVOID HookingDetails, CR3_TYPE ProcessCr3, UINT32 PageHookMask)
 The main function that performs EPT page hook with hidden detours and monitor.
BOOLEAN EptHookPerformMemoryOrInlineHook (VIRTUAL_MACHINE_STATE *VCpu, EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 *EptHook2AddressDetails, EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *MemoryAddressDetails, UINT32 ProcessId, BOOLEAN EptHiddenHook2, BOOLEAN ApplyDirectlyFromVmxRoot)
 This function allocates a buffer in VMX Non Root Mode and then invokes a VMCALL to set the hook.
BOOLEAN EptHookInlineHook (VIRTUAL_MACHINE_STATE *VCpu, PVOID TargetAddress, PVOID HookFunction, UINT32 ProcessId)
 This function applies EPT hook 2 (inline) to the target EPT table.
BOOLEAN EptHookMonitorHook (VIRTUAL_MACHINE_STATE *VCpu, EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *HookingDetails, UINT32 ProcessId)
 This function applies monitor hooks to the target EPT table.
BOOLEAN EptHookInlineHookFromVmxRoot (VIRTUAL_MACHINE_STATE *VCpu, PVOID TargetAddress, PVOID HookFunction)
 This function applies EPT inline to the target EPT table.
BOOLEAN EptHookMonitorFromVmxRoot (VIRTUAL_MACHINE_STATE *VCpu, EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *MemoryAddressDetails)
 This function applies EPT monitor hooks to the target EPT table.
BOOLEAN EptHookHandleHookedPage (VIRTUAL_MACHINE_STATE *VCpu, EPT_HOOKED_PAGE_DETAIL *HookedEntryDetails, VMX_EXIT_QUALIFICATION_EPT_VIOLATION ViolationQualification, SIZE_T PhysicalAddress, EPT_HOOKS_CONTEXT *LastContext, BOOLEAN *IgnoreReadOrWriteOrExec, BOOLEAN *IsExecViolation)
 Handles page hooks (trigger events).
BOOLEAN EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList (UINT64 Address)
 Remove the entry from g_EptHook2sDetourListHead in the case of !epthook2 details.
UINT32 EptHookGetCountOfEpthooks (BOOLEAN IsEptHook2)
 get the length of active EPT hooks (!epthook and !epthook2)
BOOLEAN EptHookUnHookSingleAddressDetoursAndMonitor (PEPT_HOOKED_PAGE_DETAIL HookedEntry, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
 Remove single hook of detours type.
VOID EptHookHandleMonitorTrapFlag (VIRTUAL_MACHINE_STATE *VCpu)
 Handle vm-exits for Monitor Trap Flag to restore previous state.
BOOLEAN EptHookUnHookSingleAddressHiddenBreakpoint (PEPT_HOOKED_PAGE_DETAIL HookedEntry, UINT64 VirtualAddress, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
 Remove single hook of hidden breakpoint type.
BOOLEAN EptHookPerformUnHookSingleAddress (UINT64 VirtualAddress, UINT64 PhysAddress, UINT64 HookingTag, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
 Remove single hook from the hooked pages list and invalidate TLB.
BOOLEAN EptHookUnHookAllByHookingTag (UINT64 HookingTag)
 Remove all hooks from the hooked pages by the given hooking tag.
BOOLEAN EptHookUnHookSingleHookByHookingTagFromVmxRoot (UINT64 HookingTag, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
 Remove single hook from the hooked pages by the given hooking tag.
BOOLEAN EptHookUnHookSingleAddress (UINT64 VirtualAddress, UINT64 PhysAddress, UINT32 ProcessId)
 Remove single hook from the hooked pages list and invalidate TLB.
BOOLEAN EptHookUnHookSingleAddressFromVmxRoot (UINT64 VirtualAddress, UINT64 PhysAddress, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
 Remove single hook from the hooked pages list and invalidate TLB.
VOID EptHookUnHookAll ()
 Remove all hooks from the hooked pages list and invalidate TLB @detailsShould be called from Vmx Non-root.
PVOID EptHook2GeneralDetourEventHandler (PGUEST_REGS Regs, PVOID CalledFrom)
 routines to generally handle breakpoint hit for detour
BOOLEAN EptHookModifyInstructionFetchState (VIRTUAL_MACHINE_STATE *VCpu, PVOID PhysicalAddress, BOOLEAN IsUnset)
 Change PML EPT state for execution (execute) @detail should be called from VMX-root.
BOOLEAN EptHookModifyPageReadState (VIRTUAL_MACHINE_STATE *VCpu, PVOID PhysicalAddress, BOOLEAN IsUnset)
 Change PML EPT state for read @detail should be called from VMX-root.
BOOLEAN EptHookModifyPageWriteState (VIRTUAL_MACHINE_STATE *VCpu, PVOID PhysicalAddress, BOOLEAN IsUnset)
 Change PML EPT state for write @detail should be called from VMX-root.

Detailed Description

Implementation of different EPT hidden hooks functions.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)

All the R/W hooks, Execute hooks and hardware register simulators are implemented here

Version
0.1
Date
2020-04-11

Function Documentation

◆ _Success_()

_Must_inspect_result_ _Success_ ( return = TRUE)

Check whether the desired PhysicalAddress is already in the g_EptState->HookedPagesList hooks or not.

Parameters
PhysicalBaseAddress
Returns
PEPT_HOOKED_PAGE_DETAIL if the address was already hooked, or FALSE
27{
28 LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, CurrEntity)
29 {
30 if (CurrEntity->PhysicalBaseAddress == PhysicalBaseAddress)
31 {
32 return CurrEntity;
33 }
34 }
35
36 return NULL;
37}
#define LIST_FOR_EACH_LINK(_head, _struct_type, _member, _var)
Definition MetaMacros.h:34
struct _EPT_HOOKED_PAGE_DETAIL EPT_HOOKED_PAGE_DETAIL
Structure to save the state of each hooked pages.
EPT_STATE * g_EptState
Save the state and variables related to EPT.
Definition GlobalVariables.h:50
NULL()
Definition test-case-generator.py:530

◆ EptHook()

BOOLEAN EptHook ( PVOID TargetAddress,
UINT32 ProcessId )

This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on exception bitmap.

Hook in VMX non-root Mode (hidden breakpoint).

this command uses hidden breakpoints (0xcc) to hook, THIS FUNCTION SHOULD BE CALLED WHEN THE VMLAUNCH ALREADY EXECUTED, it is because, broadcasting to enable exception bitmap for breakpoint is not clear here, if we want to broadcast to enable exception bitmaps on all cores when vmlaunch is not executed then that's ok but a user might call this function when we didn't configure the vmcs, it's a problem! we can solve it by giving a hint to vmcs configure function to make it ok for future configuration but that sounds stupid, I think it's better to not support this feature. Btw, debugger won't use this function in the above mentioned method, so we won't have any problem with this This function should be called from VMX non-root mode

Parameters
TargetAddressThe address of function or memory address to be hooked
ProcessIdThe process id to translate based on that process's cr3
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on exception bitmap.

Parameters
TargetAddress
ProcessId
Returns
BOOLEAN
621{
622 //
623 // Should be called from vmx non-root
624 //
626 {
627 return FALSE;
628 }
629
630 return EptHookPerformHook(TargetAddress, ProcessId, FALSE);
631}
BOOLEAN EptHookPerformHook(PVOID TargetAddress, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot)
This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on excep...
Definition EptHook.c:548
BOOLEAN VmxGetCurrentExecutionMode()
Check current execution mode (vmx-root and non-root).
Definition Vmx.c:76
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113

◆ EptHook2GeneralDetourEventHandler()

PVOID EptHook2GeneralDetourEventHandler ( PGUEST_REGS Regs,
PVOID CalledFrom )

routines to generally handle breakpoint hit for detour

Parameters
Regs
CalledFrom
Returns
PVOID
2504{
2505 PLIST_ENTRY TempList = 0;
2506 EPT_HOOKS_CONTEXT TempContext = {0};
2507
2508 //
2509 // The RSP register is the at the RCX and we just added (reverse by stack) to it's
2510 // values by the size of the GUEST_REGS
2511 //
2512 Regs->rsp = (UINT64)Regs - sizeof(GUEST_REGS);
2513
2514 //
2515 // test
2516 //
2517
2518 //
2519 // LogInfo("Hidden Hooked function Called with : rcx = 0x%llx , rdx = 0x%llx , r8 = 0x%llx , r9 = 0x%llx",
2520 // Regs->rcx,
2521 // Regs->rdx,
2522 // Regs->r8,
2523 // Regs->r9);
2524 //
2525
2526 //
2527 // Create temporary context
2528 //
2529 TempContext.VirtualAddress = (UINT64)CalledFrom;
2530 TempContext.PhysicalAddress = VirtualAddressToPhysicalAddress(CalledFrom);
2531
2532 //
2533 // Create a temporary VCpu
2534 //
2535 VIRTUAL_MACHINE_STATE * VCpu = &g_GuestState[KeGetCurrentProcessorNumberEx(NULL)];
2536
2537 //
2538 // Set the register for the temporary VCpu
2539 //
2540 VCpu->Regs = Regs;
2541
2542 //
2543 // As the context to event trigger, we send the address of function
2544 // which is current hidden hook is triggered for it
2545 //
2546 DispatchEventHiddenHookExecDetours(VCpu, &TempContext);
2547
2548 //
2549 // Iterate through the list of hooked pages details to find
2550 // and return where want to jump after this functions
2551 //
2552 TempList = &g_EptHook2sDetourListHead;
2553
2554 while (&g_EptHook2sDetourListHead != TempList->Flink)
2555 {
2556 TempList = TempList->Flink;
2557 PHIDDEN_HOOKS_DETOUR_DETAILS CurrentHookedDetails = CONTAINING_RECORD(TempList, HIDDEN_HOOKS_DETOUR_DETAILS, OtherHooksList);
2558
2559 if (CurrentHookedDetails->HookedFunctionAddress == CalledFrom)
2560 {
2561 return CurrentHookedDetails->ReturnAddress;
2562 }
2563 }
2564
2565 //
2566 // If we reach here, means that we didn't find the return address
2567 // that's an error, generally we can't do anything but as the user
2568 // might already cleaned the hook and the structures are removed
2569 // so we just return the original caller address and continue the
2570 // guest normally
2571 //
2572 return CalledFrom;
2573}
VOID DispatchEventHiddenHookExecDetours(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context)
Handling debugger functions related to hidden hook exec detours events.
Definition Dispatch.c:1063
struct _HIDDEN_HOOKS_DETOUR_DETAILS * PHIDDEN_HOOKS_DETOUR_DETAILS
struct _HIDDEN_HOOKS_DETOUR_DETAILS HIDDEN_HOOKS_DETOUR_DETAILS
Details of detours style EPT hooks.
struct _EPT_HOOKS_CONTEXT EPT_HOOKS_CONTEXT
Temporary $context used in some EPT hook commands.
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddress(_In_ PVOID VirtualAddress)
Converts Virtual Address to Physical Address.
Definition Conversion.c:154
struct _VIRTUAL_MACHINE_STATE VIRTUAL_MACHINE_STATE
The status of each core after and before VMX.
VIRTUAL_MACHINE_STATE * g_GuestState
Save the state and variables related to virtualization on each to logical core.
Definition GlobalVariables.h:38
LIST_ENTRY g_EptHook2sDetourListHead
List header of hidden hooks detour.
Definition GlobalVariables.h:56
#define CONTAINING_RECORD(address, type, field)
Definition nt-list.h:36
UINT64 VirtualAddress
Definition DataTypes.h:372
UINT64 PhysicalAddress
Definition DataTypes.h:371
PVOID HookedFunctionAddress
Definition Hooks.h:25
PVOID ReturnAddress
Definition Hooks.h:26
GUEST_REGS * Regs
Definition State.h:326
Definition BasicTypes.h:136
UINT64 rsp
Definition BasicTypes.h:145

◆ EptHookAllocateExtraHookingPagesForMemoryMonitorsAndExecEptHooks()

VOID EptHookAllocateExtraHookingPagesForMemoryMonitorsAndExecEptHooks ( UINT32 Count)

Allocate (reserve) extra pages for storing details of page hooks for memory monitor and regular hidden breakpoit exec EPT hooks.

Parameters
Count
Returns
VOID
111{
112 ULONG ProcessorsCount;
113
114 //
115 // Get number of processors
116 //
117 ProcessorsCount = KeQueryActiveProcessorCount(0);
118
119 //
120 // Request pages to be allocated for converting 2MB to 4KB pages
121 // Each core needs its own splitting page-tables
122 //
124 Count * ProcessorsCount,
126
127 //
128 // Request pages to be allocated for paged hook details
129 //
131 Count,
133}
BOOLEAN PoolManagerCallbackRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
routine callback to request pool allocation
Definition Callback.c:335
struct _VMM_EPT_DYNAMIC_SPLIT VMM_EPT_DYNAMIC_SPLIT
Split 2MB granularity to 4 KB granularity.
unsigned long ULONG
Definition BasicTypes.h:31
@ SPLIT_2MB_PAGING_TO_4KB_PAGE
Definition DataTypes.h:76
@ TRACKING_HOOKED_PAGES
Definition DataTypes.h:74

◆ EptHookFromVmxRoot()

BOOLEAN EptHookFromVmxRoot ( PVOID TargetAddress)

This function invokes a direct VMCALL to setup the hook.

the caller of this function should make sure to 1) broadcast to all cores to intercept breakpoints (#BPs) and after calling this function 2) the caller should broadcast to all cores to invalidate their EPTPs This function should be called from VMX root-mode

Parameters
TargetAddressThe address of function or memory address to be hooked
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error
Parameters
TargetAddress
Returns
BOOLEAN
647{
648 //
649 // Should be called from VMX root-mode
650 //
652 {
653 return FALSE;
654 }
655
656 return EptHookPerformHook(TargetAddress, NULL_ZERO, TRUE);
657}
#define NULL_ZERO
Definition BasicTypes.h:110

◆ EptHookGetCountOfEpthooks()

UINT32 EptHookGetCountOfEpthooks ( BOOLEAN IsEptHook2)

get the length of active EPT hooks (!epthook and !epthook2)

Parameters
IsEptHook2Whether the length should be for !epthook or !epthook2
Returns
UINT32 Count of remained breakpoints
Parameters

return UINT32

1886{
1887 UINT32 Count = 0;
1888
1889 LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, HookedEntry)
1890 {
1891 if (IsEptHook2)
1892 {
1893 if (HookedEntry->IsHiddenBreakpoint == FALSE)
1894 {
1895 Count++;
1896 }
1897 }
1898 else
1899 {
1900 if (HookedEntry->IsHiddenBreakpoint == TRUE)
1901 {
1902 Count++;
1903 }
1904 }
1905 }
1906
1907 return Count;
1908}
unsigned int UINT32
Definition BasicTypes.h:54

◆ EptHookHandleHookedPage()

BOOLEAN EptHookHandleHookedPage ( VIRTUAL_MACHINE_STATE * VCpu,
EPT_HOOKED_PAGE_DETAIL * HookedEntryDetails,
VMX_EXIT_QUALIFICATION_EPT_VIOLATION ViolationQualification,
SIZE_T PhysicalAddress,
EPT_HOOKS_CONTEXT * LastContext,
BOOLEAN * IgnoreReadOrWriteOrExec,
BOOLEAN * IsExecViolation )

Handles page hooks (trigger events).

Handle hooked pages in Vmx-root mode.

Parameters
VCpuThe virtual processor's state
HookedEntryDetailsThe entry that describes the hooked page
ViolationQualificationThe exit qualification of vm-exit
PhysicalAddressThe physical address that cause this vm-exit
LastContextThe last (current) context of the execution
IgnoreReadOrWriteOrExecWhether to ignore the event effects or not
IsExecViolationWhether it's execution violation or not executing the post triggering of the event or not
Returns
BOOLEAN Returns TRUE if the function was hook was handled or returns false if there was an unexpected ept violation

Handles page hooks (trigger events).

Parameters
VCpu
HookedEntryDetails
ViolationQualification
PhysicalAddress
LastContext
IgnoreReadOrWriteOrExec
IsExecViolation
Returns
BOOLEAN
1713{
1714 UINT64 ExactAccessedVirtualAddress;
1715 UINT64 AlignedVirtualAddress;
1716 UINT64 AlignedPhysicalAddress;
1717 BOOLEAN IsTriggeringPostEventAllowed = FALSE;
1718
1719 //
1720 // Get alignment
1721 //
1722 AlignedVirtualAddress = (UINT64)PAGE_ALIGN(HookedEntryDetails->VirtualAddress);
1723 AlignedPhysicalAddress = (UINT64)PAGE_ALIGN(PhysicalAddress);
1724
1725 //
1726 // Let's read the exact address that was accessed
1727 //
1728 ExactAccessedVirtualAddress = AlignedVirtualAddress + PhysicalAddress - AlignedPhysicalAddress;
1729
1730 //
1731 // Set the last context
1732 //
1733 LastContext->HookingTag = HookedEntryDetails->HookingTag;
1734 LastContext->PhysicalAddress = PhysicalAddress;
1735 LastContext->VirtualAddress = ExactAccessedVirtualAddress;
1736
1737 if (!ViolationQualification.EptReadable && ViolationQualification.ReadAccess)
1738 {
1739 //
1740 // LogInfo("Guest RIP : 0x%llx tries to read the page at : 0x%llx", GuestRip, ExactAccessedAddress);
1741 //
1742
1743 //
1744 // Set last violation
1745 //
1746 HookedEntryDetails->LastViolation = EPT_HOOKED_LAST_VIOLATION_READ;
1747
1748 //
1749 // Trigger the event related to Monitor Read and Monitor Read & Write and
1750 // Monitor Read & Execute and Monitor Read & Write & Execute
1751 //
1752 *IgnoreReadOrWriteOrExec = DispatchEventHiddenHookPageReadWriteExecuteReadPreEvent(VCpu, LastContext, &IsTriggeringPostEventAllowed);
1753
1754 //
1755 // It's not an execution violation
1756 //
1757 *IsExecViolation = FALSE;
1758 }
1759 else if (!ViolationQualification.EptWriteable && ViolationQualification.WriteAccess)
1760 {
1761 //
1762 // LogInfo("Guest RIP : 0x%llx tries to write on the page at : 0x%llx", GuestRip, ExactAccessedAddress);
1763 //
1764
1765 //
1766 // Set last violation
1767 //
1768 HookedEntryDetails->LastViolation = EPT_HOOKED_LAST_VIOLATION_WRITE;
1769
1770 //
1771 // Trigger the event related to Monitor Write and Monitor Read & Write and
1772 // Monitor Write & Execute and Monitor Read & Write & Execute
1773 //
1774 *IgnoreReadOrWriteOrExec = DispatchEventHiddenHookPageReadWriteExecuteWritePreEvent(VCpu, LastContext, &IsTriggeringPostEventAllowed);
1775
1776 //
1777 // It's not an execution violation
1778 //
1779 *IsExecViolation = FALSE;
1780 }
1781 else if (!ViolationQualification.EptExecutable && ViolationQualification.ExecuteAccess)
1782 {
1783 //
1784 // LogInfo("Guest RIP : 0x%llx tries to execute the page at : 0x%llx", GuestRip, ExactAccessedAddress);
1785 //
1786
1787 //
1788 // Set last violation
1789 //
1790 HookedEntryDetails->LastViolation = EPT_HOOKED_LAST_VIOLATION_EXEC;
1791
1792 //
1793 // Trigger the event related to Monitor Execute and Monitor Read & Execute and
1794 // Monitor Write & Execute and Monitor Read & Write & Execute
1795 //
1796 *IgnoreReadOrWriteOrExec = DispatchEventHiddenHookPageReadWriteExecuteExecutePreEvent(VCpu, LastContext, &IsTriggeringPostEventAllowed);
1797
1798 //
1799 // It's an execution violation
1800 //
1801 *IsExecViolation = TRUE;
1802 }
1803 else
1804 {
1805 //
1806 // triggering post event is not allowed as it's not valid
1807 //
1808 HookedEntryDetails->IsPostEventTriggerAllowed = FALSE;
1809
1810 //
1811 // there was an unexpected ept violation
1812 //
1813 return FALSE;
1814 }
1815
1816 //
1817 // Set whether the post event trigger is allowed or not
1818 // If only one event short-circuit a special EPT hook the 'post' mode will be ignored for all of the same events
1819 //
1820 if (*IgnoreReadOrWriteOrExec == FALSE)
1821 {
1822 HookedEntryDetails->IsPostEventTriggerAllowed = IsTriggeringPostEventAllowed;
1823 }
1824 else
1825 {
1826 //
1827 // Ignoring read/write/exec will remove the 'post' event
1828 //
1829 HookedEntryDetails->IsPostEventTriggerAllowed = FALSE;
1830 }
1831
1832 //
1833 // Means that restore the Entry to the previous state after current
1834 // instruction executed in the guest
1835 //
1836 return TRUE;
1837}
BOOLEAN DispatchEventHiddenHookPageReadWriteExecuteWritePreEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context, BOOLEAN *IsTriggeringPostEventAllowed)
Handling debugger functions related to read & write & execute, write events (pre).
Definition Dispatch.c:1181
BOOLEAN DispatchEventHiddenHookPageReadWriteExecuteExecutePreEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context, BOOLEAN *IsTriggeringPostEventAllowed)
Handling debugger functions related to read & write & execute, execute events (pre).
Definition Dispatch.c:1275
BOOLEAN DispatchEventHiddenHookPageReadWriteExecuteReadPreEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context, BOOLEAN *IsTriggeringPostEventAllowed)
Handling debugger functions related to read & write & execute, read events (pre).
Definition Dispatch.c:1087
UCHAR BOOLEAN
Definition BasicTypes.h:35
@ EPT_HOOKED_LAST_VIOLATION_READ
Definition State.h:65
@ EPT_HOOKED_LAST_VIOLATION_EXEC
Definition State.h:67
@ EPT_HOOKED_LAST_VIOLATION_WRITE
Definition State.h:66
#define PAGE_ALIGN(Va)
Aligning a page.
Definition common.h:86
UINT64 VirtualAddress
The virtual address from the caller perspective view (cr3).
Definition State.h:191
UINT64 HookingTag
Tag used for notifying the caller.
Definition State.h:218
BOOLEAN IsPostEventTriggerAllowed
This field shows whether the hook should call the post event trigger after restoring the state or not...
Definition State.h:269
EPT_HOOKED_LAST_VIOLATION LastViolation
This field shows the last violation happened to this EPT hook.
Definition State.h:274
UINT64 HookingTag
Definition DataTypes.h:370

◆ EptHookHandleMonitorTrapFlag()

VOID EptHookHandleMonitorTrapFlag ( VIRTUAL_MACHINE_STATE * VCpu)

Handle vm-exits for Monitor Trap Flag to restore previous state.

Parameters
VCpuThe virtual processor's state
Returns
VOID
1984{
1985 PVOID TargetPage;
1986 //
1987 // Pointer to the page entry in the page table
1988 //
1990
1991 //
1992 // restore the hooked state
1993 //
1995 TargetPage,
1997 InveptSingleContext);
1998
1999 //
2000 // Check to trigger the post event (for events relating the !monitor command
2001 // and the emulation hardware debug registers)
2002 //
2004 {
2006 {
2007 //
2008 // This is a "read" hook
2009 //
2012 }
2014 {
2015 //
2016 // This is a "write" hook
2017 //
2020 }
2022 {
2023 //
2024 // This is a "execute" hook
2025 //
2028 }
2029 }
2030
2031 //
2032 // Check for user-mode attaching mechanisms and callback
2033 // (we call it here, because this callback might change the EPTP entries and invalidate EPTP)
2034 //
2036}
BOOLEAN VmmCallbackRestoreEptState(UINT32 CoreId)
routine callback to restore EPT state
Definition Callback.c:145
VOID DispatchEventHiddenHookPageReadWriteExecReadPostEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context)
Handling debugger functions related to read & write & execute, read events (post).
Definition Dispatch.c:1368
VOID DispatchEventHiddenHookPageReadWriteExecWritePostEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context)
Handling debugger functions related to read & write & execute, write events (post).
Definition Dispatch.c:1415
VOID DispatchEventHiddenHookPageReadWriteExecExecutePostEvent(VIRTUAL_MACHINE_STATE *VCpu, PVOID Context)
Handling debugger functions related to read & write & execute, execute events (post).
Definition Dispatch.c:1460
PEPT_PML1_ENTRY EptGetPml1Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress)
Get the PML1 entry for this physical address if the page is split.
Definition Ept.c:337
_Use_decl_annotations_ VOID EptSetPML1AndInvalidateTLB(VIRTUAL_MACHINE_STATE *VCpu, PEPT_PML1_ENTRY EntryAddress, EPT_PML1_ENTRY EntryValue, INVEPT_TYPE InvalidationType)
This function set the specific PML1 entry in a spinlock protected area then invalidate the TLB.
Definition Ept.c:1181
void * PVOID
Definition BasicTypes.h:56
EPT_HOOKS_CONTEXT LastContextState
Temporary context for the post event monitors It shows the context of the last address that triggered...
Definition State.h:263
EPT_PML1_ENTRY ChangedEntry
The original page entry. Will be copied back when the hook is remove from the page.
Definition State.h:235
SIZE_T PhysicalBaseAddress
The base address of the page. Used to find this structure in the list of page hooks when a hook is hi...
Definition State.h:203
PVMM_EPT_PAGE_TABLE EptPageTable
Definition State.h:364
PEPT_HOOKED_PAGE_DETAIL MtfEptHookRestorePoint
Definition State.h:353
UINT32 CoreId
Definition State.h:328

◆ EptHookInlineHook()

BOOLEAN EptHookInlineHook ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID TargetAddress,
PVOID HookFunction,
UINT32 ProcessId )

This function applies EPT hook 2 (inline) to the target EPT table.

Hook in VMX non-root mode (hidden detours).

this function should be called from VMX non-root mode

Parameters
VCpuThe virtual processor's state
TargetAddressThe address of function or memory address to be hooked
HookFunctionThe function that will be called when hook triggered
ProcessIdThe process id to translate based on that process's cr3
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

This function applies EPT hook 2 (inline) to the target EPT table.

Parameters
VCpu
TargetAddress
HookFunction
ProcessId
Returns
BOOLEAN
1566{
1567 EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 HookingDetail = {0};
1568
1569 //
1570 // Should be called from vmx non-root
1571 //
1573 {
1574 return FALSE;
1575 }
1576
1577 //
1578 // Set the hooking details
1579 //
1580 HookingDetail.TargetAddress = TargetAddress;
1581 HookingDetail.HookFunction = HookFunction;
1582
1584 &HookingDetail,
1585 NULL,
1586 ProcessId,
1587 TRUE,
1588 FALSE);
1589}
BOOLEAN EptHookPerformMemoryOrInlineHook(VIRTUAL_MACHINE_STATE *VCpu, EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 *EptHook2AddressDetails, EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *MemoryAddressDetails, UINT32 ProcessId, BOOLEAN EptHiddenHook2, BOOLEAN ApplyDirectlyFromVmxRoot)
This function allocates a buffer in VMX Non Root Mode and then invokes a VMCALL to set the hook.
Definition EptHook.c:1390
struct _EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2
Setting details for EPT Hooks (!epthook2).
PVOID HookFunction
Definition DataTypes.h:398
PVOID TargetAddress
Definition DataTypes.h:397

◆ EptHookInlineHookFromVmxRoot()

BOOLEAN EptHookInlineHookFromVmxRoot ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID TargetAddress,
PVOID HookFunction )

This function applies EPT inline to the target EPT table.

Hook in VMX root-mode (hidden detours).

this function should be called from VMX root-mode

Parameters
VCpuThe virtual processor's state
TargetAddressThe address of function or memory address to be hooked
HookFunctionThe function that will be called when hook triggered
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

This function applies EPT inline to the target EPT table.

Parameters
VCpu
TargetAddress
HookFunction
Returns
BOOLEAN
1636{
1637 EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 HookingDetail = {0};
1638
1639 //
1640 // Should be called from vmx root-mode
1641 //
1643 {
1644 return FALSE;
1645 }
1646
1647 //
1648 // Configure the details
1649 //
1650 HookingDetail.TargetAddress = TargetAddress;
1651 HookingDetail.HookFunction = HookFunction;
1652
1654 &HookingDetail,
1655 NULL,
1656 NULL_ZERO,
1657 TRUE,
1658 TRUE);
1659}

◆ EptHookInstructionMemory()

BOOLEAN EptHookInstructionMemory ( PEPT_HOOKED_PAGE_DETAIL Hook,
CR3_TYPE ProcessCr3,
PVOID TargetFunction,
PVOID TargetFunctionInSafeMemory,
PVOID HookFunction )

Hook instructions.

Parameters
HookThe details of hooked pages
ProcessCr3The target Process CR3
TargetFunctionTarget function that needs to be hooked
TargetFunctionInSafeMemoryTarget content in the safe memory (used in Length Disassembler Engine)
HookFunctionThe function that will be called when hook triggered
Returns
BOOLEAN Returns true if the hook was successful or returns false if it was not successful
854{
855 PHIDDEN_HOOKS_DETOUR_DETAILS DetourHookDetails;
856 SIZE_T SizeOfHookedInstructions;
857 SIZE_T OffsetIntoPage;
858 CR3_TYPE Cr3OfCurrentProcess;
859
860 OffsetIntoPage = ADDRMASK_EPT_PML1_OFFSET((SIZE_T)TargetFunction);
861
862 //
863 // Log offset
864 //
865 // LogInfo("OffsetIntoPage: 0x%llx", OffsetIntoPage);
866 //
867
868 if ((OffsetIntoPage + 19) > PAGE_SIZE - 1)
869 {
870 LogError("Err, function extends past a page boundary");
871 return FALSE;
872 }
873
874 //
875 // Determine the number of instructions necessary to overwrite using Length Disassembler Engine
876 // EPTHOOK2 only supports 64-bit kernel (32-bit LDE is not supported)
877 //
878 for (SizeOfHookedInstructions = 0;
879 SizeOfHookedInstructions < 19;
881 (PVOID)((UINT64)TargetFunctionInSafeMemory + SizeOfHookedInstructions),
882 FALSE))
883 {
884 //
885 // Get the full size of instructions necessary to copy
886 //
887 }
888
889 // for (SizeOfHookedInstructions = 0;
890 // SizeOfHookedInstructions < 19;
891 // SizeOfHookedInstructions += ZydisLde(((UINT64)TargetFunctionInSafeMemory + SizeOfHookedInstructions), TRUE))
892 //{
893 // //
894 // // Get the full size of instructions necessary to copy
895 // //
896 // }
897
898 //
899 // For logging purpose
900 //
901 // LogInfo("Number of bytes of instruction mem: %x", SizeOfHookedInstructions);
902
903 //
904 // Build a trampoline
905 //
906
907 //
908 // Allocate some executable memory for the trampoline
909 //
911
912 if (!Hook->Trampoline)
913 {
914 LogError("Err, could not allocate trampoline function buffer");
915 return FALSE;
916 }
917
918 //
919 // Copy the trampoline instructions in
920 //
921
922 // Switch to target process
923 //
924 Cr3OfCurrentProcess = SwitchToProcessMemoryLayoutByCr3(ProcessCr3);
925
926 //
927 // The following line can't be used in user mode addresses
928 // RtlCopyMemory(Hook->Trampoline, TargetFunction, SizeOfHookedInstructions);
929 //
930 MemoryMapperReadMemorySafe((UINT64)TargetFunction, Hook->Trampoline, SizeOfHookedInstructions);
931
932 //
933 // Restore to original process
934 //
935 SwitchToPreviousProcess(Cr3OfCurrentProcess);
936
937 //
938 // Add the absolute jump back to the original function
939 //
940 EptHookWriteAbsoluteJump2(&Hook->Trampoline[SizeOfHookedInstructions], (SIZE_T)TargetFunction + SizeOfHookedInstructions);
941
942 //
943 //
944 //
945 // LogInfo("Trampoline: 0x%llx", Hook->Trampoline);
946 // LogInfo("HookFunction: 0x%llx", HookFunction);
947
948 //
949 // Let the hook function call the original function
950 //
951 // *OrigFunction = Hook->Trampoline;
952 //
953
954 //
955 // Create the structure to return for the debugger, we do it here because it's the first
956 // function that changes the original function and if our structure is no ready after this
957 // function then we probably see BSOD on other cores
958 //
960 DetourHookDetails->HookedFunctionAddress = TargetFunction;
961 DetourHookDetails->ReturnAddress = Hook->Trampoline;
962
963 //
964 // Save the address of DetourHookDetails because we want to
965 // deallocate it when the hook is finished
966 //
967 Hook->AddressOfEptHook2sDetourListEntry = (UINT64)DetourHookDetails;
968
969 //
970 // Insert it to the list of hooked pages
971 //
972 InsertHeadList(&g_EptHook2sDetourListHead, &(DetourHookDetails->OtherHooksList));
973
974 //
975 // Write the absolute jump to our shadow page memory to jump to our hook
976 //
977 EptHookWriteAbsoluteJump(&Hook->FakePageContents[OffsetIntoPage], (SIZE_T)HookFunction);
978
979 return TRUE;
980}
UINT64 PoolManagerCallbackRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size)
routine callback to request pool
Definition Callback.c:358
#define ADDRMASK_EPT_PML1_OFFSET(_VAR_)
Offset into the 1st paging structure (4096 byte).
Definition Ept.h:49
VOID EptHookWriteAbsoluteJump(PCHAR TargetBuffer, SIZE_T TargetAddress)
Write an absolute x64 jump to an arbitrary address to a buffer.
Definition EptHook.c:758
VOID EptHookWriteAbsoluteJump2(PCHAR TargetBuffer, SIZE_T TargetAddress)
Write an absolute x64 jump to an arbitrary address to a buffer.
Definition EptHook.c:807
#define MAX_EXEC_TRAMPOLINE_SIZE
Maximum number of supported execution trampoline.
Definition Hooks.h:95
struct _CR3_TYPE CR3_TYPE
CR3 Structure.
char CHAR
Definition BasicTypes.h:33
@ EXEC_TRAMPOLINE
Definition DataTypes.h:75
@ DETOUR_HOOK_DETAILS
Definition DataTypes.h:77
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
IMPORT_EXPORT_VMM VOID SwitchToPreviousProcess(_In_ CR3_TYPE PreviousProcess)
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafe(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead)
IMPORT_EXPORT_VMM UINT32 DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess(PVOID Address, BOOLEAN Is32Bit)
Disassembler length disassembler engine.
Definition Disassembler.c:297
IMPORT_EXPORT_VMM CR3_TYPE SwitchToProcessMemoryLayoutByCr3(_In_ CR3_TYPE TargetCr3)
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80
UINT64 AddressOfEptHook2sDetourListEntry
The virtual address of it's entry on g_EptHook2sDetourListHead this way we can de-allocate the list w...
Definition State.h:197
CHAR FakePageContents[PAGE_SIZE]
Definition State.h:181
PCHAR Trampoline
The buffer of the trampoline function which is used in the inline hook.
Definition State.h:240
LIST_ENTRY OtherHooksList
Definition Hooks.h:24

◆ EptHookModifyInstructionFetchState()

BOOLEAN EptHookModifyInstructionFetchState ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID PhysicalAddress,
BOOLEAN IsUnset )

Change PML EPT state for execution (execute) @detail should be called from VMX-root.

Parameters
VCpuThe virtual processor's state
PhysicalAddressTarget physical address
IsUnsetIs unsetting bit or setting bit
Returns
BOOLEAN
2589{
2590 PVOID PmlEntry = NULL;
2591 BOOLEAN IsLargePage = FALSE;
2592
2593 PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage);
2594
2595 if (PmlEntry)
2596 {
2597 if (IsLargePage)
2598 {
2599 if (IsUnset)
2600 {
2601 ((PEPT_PML2_ENTRY)PmlEntry)->ExecuteAccess = FALSE;
2602 }
2603 else
2604 {
2605 ((PEPT_PML2_ENTRY)PmlEntry)->ExecuteAccess = TRUE;
2606 }
2607 }
2608 else
2609 {
2610 if (IsUnset)
2611 {
2612 ((PEPT_PML1_ENTRY)PmlEntry)->ExecuteAccess = FALSE;
2613 }
2614 else
2615 {
2616 ((PEPT_PML1_ENTRY)PmlEntry)->ExecuteAccess = TRUE;
2617 }
2618 }
2619 }
2620 else
2621 {
2622 return FALSE;
2623 }
2624
2625 //
2626 // Invalidate the EPTP (single-context)
2627 //
2628 EptInveptSingleContext(VCpu->EptPointer.AsUInt);
2629
2630 return TRUE;
2631}
PVOID EptGetPml1OrPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress, BOOLEAN *IsLargePage)
Get the PML1 entry for this physical address if the large page is available then large page of Pml2 i...
Definition Ept.c:394
UCHAR EptInveptSingleContext(_In_ UINT64 EptPointer)
Invalidates a single context in ept cache table.
Definition Invept.c:40
EPT_PTE * PEPT_PML1_ENTRY
Definition State.h:23
EPT_PDE_2MB * PEPT_PML2_ENTRY
Definition State.h:21
EPT_POINTER EptPointer
Definition State.h:363

◆ EptHookModifyPageReadState()

BOOLEAN EptHookModifyPageReadState ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID PhysicalAddress,
BOOLEAN IsUnset )

Change PML EPT state for read @detail should be called from VMX-root.

Parameters
VCpuThe virtual processor's state
PhysicalAddressTarget physical address
IsUnsetIs unsetting bit or setting bit
Returns
BOOLEAN
2647{
2648 PVOID PmlEntry = NULL;
2649 BOOLEAN IsLargePage = FALSE;
2650
2651 PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage);
2652
2653 if (PmlEntry)
2654 {
2655 if (IsLargePage)
2656 {
2657 if (IsUnset)
2658 {
2659 ((PEPT_PML2_ENTRY)PmlEntry)->ReadAccess = FALSE;
2660 }
2661 else
2662 {
2663 ((PEPT_PML2_ENTRY)PmlEntry)->ReadAccess = TRUE;
2664 }
2665 }
2666 else
2667 {
2668 if (IsUnset)
2669 {
2670 ((PEPT_PML1_ENTRY)PmlEntry)->ReadAccess = FALSE;
2671 }
2672 else
2673 {
2674 ((PEPT_PML1_ENTRY)PmlEntry)->ReadAccess = TRUE;
2675 }
2676 }
2677 }
2678 else
2679 {
2680 return FALSE;
2681 }
2682
2683 //
2684 // Invalidate the EPTP (single-context)
2685 //
2686 EptInveptSingleContext(VCpu->EptPointer.AsUInt);
2687
2688 return TRUE;
2689}

◆ EptHookModifyPageWriteState()

BOOLEAN EptHookModifyPageWriteState ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID PhysicalAddress,
BOOLEAN IsUnset )

Change PML EPT state for write @detail should be called from VMX-root.

Parameters
VCpuThe virtual processor's state
PhysicalAddressTarget physical address
IsUnsetIs unsetting bit or setting bit
Returns
BOOLEAN
2705{
2706 PVOID PmlEntry = NULL;
2707 BOOLEAN IsLargePage = FALSE;
2708
2709 PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage);
2710
2711 if (PmlEntry)
2712 {
2713 if (IsLargePage)
2714 {
2715 if (IsUnset)
2716 {
2717 ((PEPT_PML2_ENTRY)PmlEntry)->WriteAccess = FALSE;
2718 }
2719 else
2720 {
2721 ((PEPT_PML2_ENTRY)PmlEntry)->WriteAccess = TRUE;
2722 }
2723 }
2724 else
2725 {
2726 if (IsUnset)
2727 {
2728 ((PEPT_PML1_ENTRY)PmlEntry)->WriteAccess = FALSE;
2729 }
2730 else
2731 {
2732 ((PEPT_PML1_ENTRY)PmlEntry)->WriteAccess = TRUE;
2733 }
2734 }
2735 }
2736 else
2737 {
2738 return FALSE;
2739 }
2740
2741 //
2742 // Invalidate the EPTP (single-context)
2743 //
2744 EptInveptSingleContext(VCpu->EptPointer.AsUInt);
2745
2746 return TRUE;
2747}

◆ EptHookMonitorFromVmxRoot()

BOOLEAN EptHookMonitorFromVmxRoot ( VIRTUAL_MACHINE_STATE * VCpu,
EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR * MemoryAddressDetails )

This function applies EPT monitor hooks to the target EPT table.

this function should be called from VMX root-mode

Parameters
VCpuThe virtual processor's state
MemoryAddressDetailsdetails of the target memory
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

this function should be called from VMX root-mode

Parameters
VCpu
MemoryAddressDetails
Returns
BOOLEAN
1673{
1674 //
1675 // Should be called from vmx root-mode
1676 //
1678 {
1679 return FALSE;
1680 }
1681
1683 NULL,
1684 MemoryAddressDetails,
1685 NULL_ZERO,
1686 FALSE,
1687 TRUE);
1688}

◆ EptHookMonitorHook()

BOOLEAN EptHookMonitorHook ( VIRTUAL_MACHINE_STATE * VCpu,
EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR * HookingDetails,
UINT32 ProcessId )

This function applies monitor hooks to the target EPT table.

this function should be called from VMX non-root mode

Parameters
VCpuThe virtual processor's state
HookingDetailsMonitor hooking details
ProcessIdThe process id to translate based on that process's cr3
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

this function should be called from VMX non-root mode

Parameters
VCpu
HookingDetails
ProcessId
Returns
BOOLEAN
1605{
1606 //
1607 // Should be called from vmx non-root
1608 //
1610 {
1611 return FALSE;
1612 }
1613
1615 NULL,
1616 HookingDetails,
1617 ProcessId,
1618 FALSE,
1619 FALSE);
1620}

◆ EptHookPerformHook()

BOOLEAN EptHookPerformHook ( PVOID TargetAddress,
UINT32 ProcessId,
BOOLEAN ApplyDirectlyFromVmxRoot )

This function invokes a VMCALL to set the hook and broadcast the exiting for the breakpoints on exception bitmap.

Parameters
TargetAddressThe address of function or memory address to be hooked
ProcessIdThe process id to translate based on that process's cr3
ApplyDirectlyFromVmxRootshould it be directly applied from VMX-root mode or not
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error
551{
552 if (ApplyDirectlyFromVmxRoot)
553 {
554 DIRECT_VMCALL_PARAMETERS DirectVmcallOptions = {0};
555
556 //
557 // Set VMCALL options
558 //
559 DirectVmcallOptions.OptionalParam1 = (UINT64)TargetAddress;
560 DirectVmcallOptions.OptionalParam2 = LayoutGetCurrentProcessCr3().Flags;
561
562 //
563 // Perform the direct VMCALL
564 //
565 if (DirectVmcallSetHiddenBreakpointHook(KeGetCurrentProcessorNumberEx(NULL), &DirectVmcallOptions) == STATUS_SUCCESS)
566 {
567 LogDebugInfo("Hidden breakpoint hook applied from VMX Root Mode");
568
569 return TRUE;
570 }
571 }
572 else
573 {
574 //
575 // Broadcast to all cores to enable vm-exit for breakpoints (exception bitmaps)
576 //
578
580 (UINT64)TargetAddress,
581 LayoutGetCr3ByProcessId(ProcessId).Flags,
582 (UINT64)NULL64_ZERO) == STATUS_SUCCESS)
583 {
584 LogDebugInfo("Hidden breakpoint hook applied from VMX Root Mode");
585
586 //
587 // Now we have to notify all the core to invalidate their EPT
588 //
590
591 return TRUE;
592 }
593 }
594
595 //
596 // sth went wrong as we're here
597 //
598 return FALSE;
599}
NTSTATUS AsmVmxVmcall(UINT64 VmcallNumber, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3)
Request Vmcall.
#define VMCALL_SET_HIDDEN_CC_BREAKPOINT
VMCALL to put hidden breakpoints (using EPT).
Definition Vmcall.h:124
#define NULL64_ZERO
Definition BasicTypes.h:111
struct _DIRECT_VMCALL_PARAMETERS DIRECT_VMCALL_PARAMETERS
Used for sending direct VMCALLs on the VMX root-mode.
#define LogDebugInfo(format,...)
Log, initialize boot information and debug information.
Definition HyperDbgHyperLogIntrinsics.h:155
IMPORT_EXPORT_VMM VOID BroadcastEnableBreakpointExitingOnExceptionBitmapAllCores()
routines to enable vm-exit for breakpoints (exception bitmap)
Definition Broadcast.c:63
IMPORT_EXPORT_VMM NTSTATUS DirectVmcallSetHiddenBreakpointHook(UINT32 CoreId, DIRECT_VMCALL_PARAMETERS *DirectVmcallOptions)
routines for putting hidden breakpoints (using EPT)
Definition DirectVmcall.c:255
IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCurrentProcessCr3()
Get cr3 of the target running process.
Definition Layout.c:55
IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCr3ByProcessId(UINT32 ProcessId)
Converts pid to kernel cr3.
Definition Layout.c:24
VOID BroadcastNotifyAllToInvalidateEptAllCores()
routines to notify to invalidate their ept on all cores
Definition Broadcast.c:119
UINT64 Flags
Definition BasicTypes.h:239
UINT64 OptionalParam2
Definition DataTypes.h:328
UINT64 OptionalParam1
Definition DataTypes.h:327

◆ EptHookPerformMemoryOrInlineHook()

BOOLEAN EptHookPerformMemoryOrInlineHook ( VIRTUAL_MACHINE_STATE * VCpu,
EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 * EptHook2AddressDetails,
EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR * MemoryAddressDetails,
UINT32 ProcessId,
BOOLEAN EptHiddenHook2,
BOOLEAN ApplyDirectlyFromVmxRoot )

This function allocates a buffer in VMX Non Root Mode and then invokes a VMCALL to set the hook.

this command uses hidden detours, if it calls from VMX root-mode directly, it should also invalidate EPT caches (by the caller)

Parameters
VCpuThe virtual processor's state
EptHook2AddressDetailsThe address details for inline EPT hooks
MemoryAddressDetailsThe address details for monitor EPT hooks
ProcessIdThe process id to translate based on that process's cr3
EptHiddenHook2epthook2 style hook
ApplyDirectlyFromVmxRootshould it be directly applied from VMX-root mode or not
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error
1396{
1397 UINT32 PageHookMask = 0;
1398 PVOID HookDetailsToVmcall = NULL;
1399
1400 //
1401 // Check for the features to avoid EPT Violation problems
1402 //
1403 if (MemoryAddressDetails != NULL)
1404 {
1405 HookDetailsToVmcall = MemoryAddressDetails;
1406
1407 if (MemoryAddressDetails->SetHookForExec &&
1408 !g_CompatibilityCheck.ExecuteOnlySupport)
1409 {
1410 //
1411 // In the current design of hyperdbg we use execute-only pages
1412 // to implement hidden hooks for exec page, so your processor doesn't
1413 // have this feature and you have to implement it in other ways :(
1414 //
1415 return FALSE;
1416 }
1417
1418 if (!MemoryAddressDetails->SetHookForWrite && MemoryAddressDetails->SetHookForRead)
1419 {
1420 //
1421 // The hidden hook with Write Enable and Read Disabled will cause EPT violation!
1422 // fixed
1423 return FALSE;
1424 }
1425
1426 if (MemoryAddressDetails->SetHookForRead)
1427 {
1428 PageHookMask |= PAGE_ATTRIB_READ;
1429 }
1430 if (MemoryAddressDetails->SetHookForWrite)
1431 {
1432 PageHookMask |= PAGE_ATTRIB_WRITE;
1433 }
1434 if (MemoryAddressDetails->SetHookForExec)
1435 {
1436 PageHookMask |= PAGE_ATTRIB_EXEC;
1437 }
1438 }
1439 else if (EptHook2AddressDetails != NULL)
1440 {
1441 HookDetailsToVmcall = EptHook2AddressDetails;
1442
1443 //
1444 // Initialize the list of ept hook detours if it's not already initialized
1445 //
1447 {
1449
1450 InitializeListHead(&g_EptHook2sDetourListHead);
1451 }
1452
1453 if (EptHiddenHook2)
1454 {
1455 PageHookMask |= PAGE_ATTRIB_EXEC_HIDDEN_HOOK;
1456 }
1457 }
1458 else
1459 {
1460 //
1461 // No details provided
1462 //
1463 return FALSE;
1464 }
1465
1466 //
1467 // Check if mask is valid or not
1468 //
1469 if (PageHookMask == 0)
1470 {
1471 //
1472 // nothing to hook
1473 //
1474 return FALSE;
1475 }
1476
1477 if (ApplyDirectlyFromVmxRoot)
1478 {
1479 DIRECT_VMCALL_PARAMETERS DirectVmcallOptions = {0};
1480 DirectVmcallOptions.OptionalParam1 = (UINT64)HookDetailsToVmcall;
1481 DirectVmcallOptions.OptionalParam2 = PageHookMask;
1482 DirectVmcallOptions.OptionalParam3 = LayoutGetCurrentProcessCr3().Flags; // Process id is ignored while applied directly
1483
1484 if (DirectVmcallPerformVmcall(VCpu->CoreId, VMCALL_CHANGE_PAGE_ATTRIB, &DirectVmcallOptions) == STATUS_SUCCESS)
1485 {
1486 return TRUE;
1487 }
1488 else
1489 {
1490 return FALSE;
1491 }
1492 }
1493 else
1494 {
1496 {
1498 (UINT64)HookDetailsToVmcall,
1499 PageHookMask,
1500 LayoutGetCr3ByProcessId(ProcessId).Flags) == STATUS_SUCCESS)
1501 {
1502 //
1503 // Test log
1504 //
1505 // LogInfo("Hook applied from VMX Root Mode");
1506 //
1507
1509 {
1510 //
1511 // Now we have to notify all the core to invalidate their EPT
1512 //
1514 }
1515 else
1516 {
1517 LogInfo("Err, unable to notify all cores to invalidate their TLB "
1518 "caches as you called hook on vmx-root mode, however, the "
1519 "hook is still works");
1520 }
1521
1522 return TRUE;
1523 }
1524 else
1525 {
1526 return FALSE;
1527 }
1528 }
1529 else
1530 {
1532 HookDetailsToVmcall,
1533 LayoutGetCr3ByProcessId(ProcessId),
1534 PageHookMask) == TRUE)
1535 {
1536 LogWarning("Hook applied (VM has not launched)");
1537 return TRUE;
1538 }
1539 }
1540 }
1541
1542 //
1543 // There was a error, we shouldn't reach here
1544 //
1545 LogWarning("Err, hook was not applied");
1546
1547 return FALSE;
1548}
#define PAGE_ATTRIB_EXEC
Definition Ept.h:24
#define PAGE_ATTRIB_READ
Page attributes for internal use.
Definition Ept.h:22
#define PAGE_ATTRIB_EXEC_HIDDEN_HOOK
Definition Ept.h:25
#define PAGE_ATTRIB_WRITE
Definition Ept.h:23
BOOLEAN EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE *VCpu, PVOID HookingDetails, CR3_TYPE ProcessCr3, UINT32 PageHookMask)
The main function that performs EPT page hook with hidden detours and monitor.
Definition EptHook.c:995
#define VMCALL_CHANGE_PAGE_ATTRIB
VMCALL to Hook Change the attribute bits of the EPT Table.
Definition Vmcall.h:34
BOOLEAN VmxGetCurrentLaunchState()
Check if the VMX is launched or not.
Definition Vmx.c:100
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71
#define LogWarning(format,...)
Log in the case of warning.
Definition HyperDbgHyperLogIntrinsics.h:99
IMPORT_EXPORT_VMM NTSTATUS DirectVmcallPerformVmcall(UINT32 CoreId, UINT64 VmcallNumber, DIRECT_VMCALL_PARAMETERS *DirectVmcallOptions)
routines for performing a direct VMCALL
Definition DirectVmcall.c:45
COMPATIBILITY_CHECKS_STATUS g_CompatibilityCheck
Different attributes and compatibility checks of the current processor.
Definition GlobalVariables.h:26
BOOLEAN g_IsEptHook2sDetourListInitialized
List header of hidden hooks detour.
Definition GlobalVariables.h:62
UINT64 OptionalParam3
Definition DataTypes.h:329
BOOLEAN SetHookForRead
Definition DataTypes.h:383
BOOLEAN SetHookForWrite
Definition DataTypes.h:384
BOOLEAN SetHookForExec
Definition DataTypes.h:385

◆ EptHookPerformPageHook()

BOOLEAN EptHookPerformPageHook ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID TargetAddress,
CR3_TYPE ProcessCr3 )

The main function that performs EPT page hook with hidden breakpoint.

Hook in VMX Root Mode with hidden breakpoints (A pre-allocated buffer should be available).

This function returns false in VMX Non-Root Mode if the VM is already initialized This function have to be called through a VMCALL in VMX Root Mode

Parameters
VCpuThe virtual processor's state
TargetAddressThe address of function or memory address to be hooked
ProcessCr3The process cr3 to translate based on that process's cr3
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

The main function that performs EPT page hook with hidden breakpoint.

Parameters
VCpu
TargetAddress
ProcessCr3
Returns
BOOLEAN
483{
484 SIZE_T PhysicalBaseAddress;
485 PVOID VirtualTarget;
486 EPT_HOOKED_PAGE_DETAIL * HookedEntry = NULL;
487
488 //
489 // Translate the page from a physical address to virtual so we can read its memory.
490 // This function will return NULL if the physical address was not already mapped in
491 // virtual memory.
492 //
493 VirtualTarget = PAGE_ALIGN(TargetAddress);
494
495 //
496 // Here we have to change the CR3, it is because we are in SYSTEM process
497 // and if the target address is not mapped in SYSTEM address space (e.g
498 // user mode address of another process) then the translation is invalid
499 //
500
501 //
502 // Find cr3 of target core
503 //
504 PhysicalBaseAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3(VirtualTarget, ProcessCr3);
505
506 if (!PhysicalBaseAddress)
507 {
509 return FALSE;
510 }
511
512 //
513 // Check if the physical address is bigger than 512 GB
514 //
515 if (PhysicalBaseAddress >= SIZE_512_GB)
516 {
518 return FALSE;
519 }
520
521 //
522 // try to see if we can find the address
523 //
524
525 HookedEntry = EptHookFindByPhysAddress(PhysicalBaseAddress);
526
527 if (HookedEntry != NULL)
528 {
529 return EptHookUpdateHookPage(TargetAddress, HookedEntry);
530 }
531 else
532 {
533 return EptHookCreateHookPage(VCpu, TargetAddress, ProcessCr3);
534 }
535}
VOID VmmCallbackSetLastError(UINT32 LastError)
routine callback to set last error
Definition Callback.c:47
#define SIZE_512_GB
Integer 512GB.
Definition Ept.h:43
#define DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB
error, cannot put EPT hooks on addresses above 512 GB
Definition ErrorCodes.h:564
#define DEBUGGER_ERROR_INVALID_ADDRESS
error, invalid address specified for debugger
Definition ErrorCodes.h:63
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddressByProcessCr3(_In_ PVOID VirtualAddress, _In_ CR3_TYPE TargetCr3)

◆ EptHookPerformPageHookMonitorAndInlineHook()

BOOLEAN EptHookPerformPageHookMonitorAndInlineHook ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID HookingDetails,
CR3_TYPE ProcessCr3,
UINT32 PageHookMask )

The main function that performs EPT page hook with hidden detours and monitor.

Hook in VMX Root Mode with hidden detours and monitor (A pre-allocated buffer should be available).

This function returns false in VMX Non-Root Mode if the VM is already initialized This function have to be called through a VMCALL in VMX Root Mode

Parameters
VCpuThe virtual processor's state
HookingDetailsThe address of function or memory address to be hooked
ProcessCr3The process cr3 to translate based on that process's cr3
PageHookMaskMask hook of the page
Returns
BOOLEAN Returns true if the hook was successful or false if there was an error

The main function that performs EPT page hook with hidden detours and monitor.

Parameters
VCpu
HookingDetails
ProcessCr3
PageHookMask
Returns
BOOLEAN
999{
1000 ULONG ProcessorsCount;
1001 EPT_PML1_ENTRY ChangedEntry;
1002 SIZE_T PhysicalBaseAddress;
1003 PVOID AlignedTargetVaOrPa;
1004 PVOID TargetAddress;
1005 PVOID HookFunction;
1006 UINT64 TargetAddressInSafeMemory;
1007 PEPT_PML1_ENTRY TargetPage;
1008 PEPT_HOOKED_PAGE_DETAIL HookedPage;
1009 CR3_TYPE Cr3OfCurrentProcess;
1010 PLIST_ENTRY TempList = 0;
1011 PEPT_HOOKED_PAGE_DETAIL HookedEntry = NULL;
1012 BOOLEAN UnsetExecute = FALSE;
1013 BOOLEAN UnsetRead = FALSE;
1014 BOOLEAN UnsetWrite = FALSE;
1015 BOOLEAN EptHiddenHook = FALSE;
1016
1017 UnsetRead = (PageHookMask & PAGE_ATTRIB_READ) ? TRUE : FALSE;
1018 UnsetWrite = (PageHookMask & PAGE_ATTRIB_WRITE) ? TRUE : FALSE;
1019 UnsetExecute = (PageHookMask & PAGE_ATTRIB_EXEC) ? TRUE : FALSE;
1020 EptHiddenHook = (PageHookMask & PAGE_ATTRIB_EXEC_HIDDEN_HOOK) ? TRUE : FALSE;
1021
1022 //
1023 // Get number of processors
1024 //
1025 ProcessorsCount = KeQueryActiveProcessorCount(0);
1026
1027 //
1028 // Translate the page from a physical address to virtual so we can read its memory.
1029 // This function will return NULL if the physical address was not already mapped in
1030 // virtual memory.
1031 //
1032 if (EptHiddenHook)
1033 {
1034 TargetAddress = ((EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 *)HookingDetails)->TargetAddress;
1035 }
1036 else
1037 {
1038 TargetAddress = (PVOID)((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress;
1039 }
1040
1041 AlignedTargetVaOrPa = PAGE_ALIGN(TargetAddress);
1042
1043 //
1044 // Here we have to change the CR3, it is because we are in SYSTEM process
1045 // and if the target address is not mapped in SYSTEM address space (e.g
1046 // user mode address of another process) then the translation is invalid
1047 //
1048
1049 if (!EptHiddenHook &&
1051 {
1052 //
1053 // The address itself is a physical address, no need for conversion
1054 //
1055 PhysicalBaseAddress = (SIZE_T)AlignedTargetVaOrPa;
1056 }
1057 else
1058 {
1059 //
1060 // based on the CR3 of target core
1061 //
1062 PhysicalBaseAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3(AlignedTargetVaOrPa, ProcessCr3);
1063 }
1064
1065 //
1066 // Check if the physical address is valid
1067 //
1068 if (!PhysicalBaseAddress)
1069 {
1071 return FALSE;
1072 }
1073
1074 //
1075 // Check if the physical address is bigger than 512 GB
1076 //
1077 if (PhysicalBaseAddress >= SIZE_512_GB)
1078 {
1080 return FALSE;
1081 }
1082
1083 //
1084 // try to see if we can find the address
1085 //
1086 TempList = &g_EptState->HookedPagesList;
1087
1088 while (&g_EptState->HookedPagesList != TempList->Flink)
1089 {
1090 TempList = TempList->Flink;
1091 HookedEntry = CONTAINING_RECORD(TempList, EPT_HOOKED_PAGE_DETAIL, PageHookList);
1092
1093 if (HookedEntry->PhysicalBaseAddress == PhysicalBaseAddress)
1094 {
1095 //
1096 // Means that we find the address and !epthook2 doesn't support
1097 // multiple breakpoints in on page
1098 //
1100 return FALSE;
1101 }
1102 }
1103
1104 //
1105 // Save the detail of hooked page to keep track of it
1106 //
1108
1109 if (!HookedPage)
1110 {
1112 return FALSE;
1113 }
1114
1115 //
1116 // Save the virtual address
1117 //
1118 HookedPage->VirtualAddress = (UINT64)TargetAddress;
1119
1120 //
1121 // Save the physical address
1122 //
1123 HookedPage->PhysicalBaseAddress = PhysicalBaseAddress;
1124
1125 //
1126 // If it's a monitor hook, then we need to hold the address of the start
1127 // physical address as well as the end physical address, plus tagging information
1128 //
1129 if (!EptHiddenHook)
1130 {
1131 //
1132 // Save the target tag
1133 //
1134 HookedPage->HookingTag = ((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->Tag;
1135
1136 //
1137 // Save the start of the target physical address
1138 //
1140 {
1141 //
1142 // Physical address
1143 //
1144 HookedPage->StartOfTargetPhysicalAddress = (SIZE_T)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress);
1145 }
1146 else
1147 {
1148 //
1149 // Virtual address
1150 //
1152 (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress),
1153 ProcessCr3);
1154 }
1155
1156 if (!HookedPage->StartOfTargetPhysicalAddress)
1157 {
1158 PoolManagerCallbackFreePool((UINT64)HookedPage);
1159
1161 return FALSE;
1162 }
1163
1164 //
1165 // Save the end of the target physical address
1166 //
1168 {
1169 //
1170 // Physical address
1171 //
1172 HookedPage->EndOfTargetPhysicalAddress = (SIZE_T)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->EndAddress);
1173 }
1174 else
1175 {
1176 //
1177 // Virtual address
1178 //
1180 (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->EndAddress),
1181 ProcessCr3);
1182 }
1183
1184 if (!HookedPage->EndOfTargetPhysicalAddress)
1185 {
1186 PoolManagerCallbackFreePool((UINT64)HookedPage);
1187
1189 return FALSE;
1190 }
1191 }
1192
1193 //
1194 // Fake page content physical address
1195 //
1197
1198 if (EptHiddenHook)
1199 {
1200 //
1201 // Show that entry has hidden hooks for execution
1202 //
1203 HookedPage->IsExecutionHook = TRUE;
1204
1205 //
1206 // Switch to target process
1207 //
1208 Cr3OfCurrentProcess = SwitchToProcessMemoryLayoutByCr3(ProcessCr3);
1209
1210 //
1211 // Copy the content to the fake page
1212 // The following line can't be used in user mode addresses
1213 // RtlCopyBytes(&HookedPage->FakePageContents, VirtualTarget, PAGE_SIZE);
1214 //
1215 MemoryMapperReadMemorySafe((UINT64)AlignedTargetVaOrPa, &HookedPage->FakePageContents, PAGE_SIZE);
1216
1217 //
1218 // Restore to original process
1219 //
1220 SwitchToPreviousProcess(Cr3OfCurrentProcess);
1221
1222 //
1223 // Compute new offset of target offset into a safe bufferr
1224 // It will be used to compute the length of the detours
1225 // address because we might have a user mode code
1226 //
1227 TargetAddressInSafeMemory = EptHookCalcBreakpointOffset(TargetAddress, HookedPage);
1228
1229 //
1230 // Make sure if handler function is valid or if it's default
1231 // then we set it to the default handler
1232 //
1233 if (((EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 *)HookingDetails)->HookFunction == NULL)
1234 {
1235 HookFunction = (PVOID)AsmGeneralDetourHook;
1236 }
1237 else
1238 {
1239 HookFunction = ((EPT_HOOKS_ADDRESS_DETAILS_FOR_EPTHOOK2 *)HookingDetails)->HookFunction;
1240 }
1241
1242 //
1243 // Create Hook
1244 //
1245 if (!EptHookInstructionMemory(HookedPage, ProcessCr3, TargetAddress, (PVOID)TargetAddressInSafeMemory, HookFunction))
1246 {
1247 PoolManagerCallbackFreePool((UINT64)HookedPage);
1248
1250 return FALSE;
1251 }
1252 }
1253
1254 for (SIZE_T i = 0; i < ProcessorsCount; i++)
1255 {
1256 //
1257 // We need to split the large page to 4KB page using pre-allocated pools
1258 //
1259 if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TRUE, PhysicalBaseAddress))
1260 {
1261 PoolManagerCallbackFreePool((UINT64)HookedPage);
1262
1263 //
1264 // Here also other previous pools should be specified, but we forget it for now
1265 //
1266 LogDebugInfo("Err, could not split page for the address : 0x%llx", PhysicalBaseAddress);
1268 return FALSE;
1269 }
1270
1271 //
1272 // Pointer to the page entry in the page table
1273 //
1274 TargetPage = EptGetPml1Entry(g_GuestState[i].EptPageTable, PhysicalBaseAddress);
1275
1276 //
1277 // Ensure the target is valid
1278 //
1279 if (!TargetPage)
1280 {
1281 PoolManagerCallbackFreePool((UINT64)HookedPage);
1282
1283 //
1284 // Here also other previous pools should be specified, but we forget it for now
1285 //
1286
1288 return FALSE;
1289 }
1290
1291 //
1292 // Save the original entry (only one of the page tables as the base original entry
1293 // is enough)
1294 //
1295 HookedPage->OriginalEntry = *TargetPage;
1296
1297 //
1298 // Save the original permissions of the page
1299 //
1300 ChangedEntry = *TargetPage;
1301
1302 //
1303 // Execution is treated differently
1304 //
1305 if (UnsetRead)
1306 ChangedEntry.ReadAccess = 0;
1307 else
1308 ChangedEntry.ReadAccess = 1;
1309
1310 if (UnsetWrite)
1311 ChangedEntry.WriteAccess = 0;
1312 else
1313 ChangedEntry.WriteAccess = 1;
1314
1315 if (UnsetExecute)
1316 ChangedEntry.ExecuteAccess = 0;
1317 else
1318 ChangedEntry.ExecuteAccess = 1;
1319
1320 //
1321 // If it's Execution hook then we have to set extra fields
1322 //
1323 if (EptHiddenHook)
1324 {
1325 //
1326 // In execution hook, we have to make sure to unset read, write because
1327 // an EPT violation should occur for these cases and we can swap the original page
1328 //
1329 ChangedEntry.ReadAccess = 0;
1330 ChangedEntry.WriteAccess = 0;
1331 ChangedEntry.ExecuteAccess = 1;
1332
1333 //
1334 // Also set the current pfn to fake page
1335 //
1336 ChangedEntry.PageFrameNumber = HookedPage->PhysicalBaseAddressOfFakePageContents;
1337 }
1338
1339 //
1340 // Only for the first time execution of the loop, we save these details,
1341 // it is because after this condition, the hook is applied and by applying
1342 // the hook, we have to make sure that the address is saved g_EptState->HookedPagesList
1343 // because the hook might be simultaneously triggered from other cores
1344 //
1345 if (i == 0)
1346 {
1347 //
1348 // Save the modified entry
1349 //
1350 HookedPage->ChangedEntry = ChangedEntry;
1351
1352 //
1353 // Add it to the list
1354 //
1355 InsertHeadList(&g_EptState->HookedPagesList, &(HookedPage->PageHookList));
1356 }
1357
1358 //
1359 // Apply the hook to EPT
1360 //
1361 TargetPage->AsUInt = ChangedEntry.AsUInt;
1362
1363 //
1364 // If it's the current core then we invalidate the EPT
1365 //
1366 if (VCpu->CoreId == i && g_GuestState[i].HasLaunched)
1367 {
1368 EptInveptSingleContext(VCpu->EptPointer.AsUInt);
1369 }
1370 }
1371
1372 return TRUE;
1373}
BOOLEAN PoolManagerCallbackFreePool(UINT64 AddressToFree)
routine callback to free pool
Definition Callback.c:378
BOOLEAN EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, BOOLEAN UsePreAllocatedBuffer, SIZE_T PhysicalAddress)
Convert large pages to 4KB pages.
Definition Ept.c:481
BOOLEAN EptHookInstructionMemory(PEPT_HOOKED_PAGE_DETAIL Hook, CR3_TYPE ProcessCr3, PVOID TargetFunction, PVOID TargetFunctionInSafeMemory, PVOID HookFunction)
Hook instructions.
Definition EptHook.c:849
VOID AsmGeneralDetourHook(VOID)
Detour hook handler.
@ DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS
Definition DataTypes.h:361
struct _EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR
Setting details for EPT Hooks (!monitor).
#define DEBUGGER_ERROR_EPT_FAILED_TO_GET_PML1_ENTRY_OF_TARGET_ADDRESS
error, failed to get PML1 entry of the target address
Definition ErrorCodes.h:264
#define DEBUGGER_ERROR_PRE_ALLOCATED_BUFFER_IS_EMPTY
error, there is no pre-allocated buffer
Definition ErrorCodes.h:251
#define DEBUGGER_ERROR_EPT_MULTIPLE_HOOKS_IN_A_SINGLE_PAGE
error, multiple EPT Hooks or Monitors are applied on a single page
Definition ErrorCodes.h:270
#define DEBUGGER_ERROR_COULD_NOT_BUILD_THE_EPT_HOOK
error, could not build the EPT Hook
Definition ErrorCodes.h:276
#define DEBUGGER_ERROR_EPT_COULD_NOT_SPLIT_THE_LARGE_PAGE_TO_4KB_PAGES
error, in the EPT handler, it could not split the 2MB pages to 512 entries of 4 KB pages
Definition ErrorCodes.h:258
struct _EPT_HOOKED_PAGE_DETAIL * PEPT_HOOKED_PAGE_DETAIL
EPT_PTE EPT_PML1_ENTRY
Definition State.h:23
SIZE_T PhysicalBaseAddressOfFakePageContents
The base address of the page with fake contents. Used to swap page with fake contents when a hook is ...
Definition State.h:224
BOOLEAN IsExecutionHook
This field shows whether the hook contains a hidden hook for execution or not.
Definition State.h:245
LIST_ENTRY PageHookList
Linked list entries for each page hook.
Definition State.h:186
SIZE_T EndOfTargetPhysicalAddress
End address of the target physical address.
Definition State.h:213
SIZE_T StartOfTargetPhysicalAddress
Start address of the target physical address.
Definition State.h:208
EPT_PML1_ENTRY OriginalEntry
The original page entry. Will be copied back when the hook is removed from the page.
Definition State.h:230

◆ EptHookPerformUnHookSingleAddress()

BOOLEAN EptHookPerformUnHookSingleAddress ( UINT64 VirtualAddress,
UINT64 PhysAddress,
UINT64 HookingTag,
UINT32 ProcessId,
BOOLEAN ApplyDirectlyFromVmxRoot,
EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails )

Remove single hook from the hooked pages list and invalidate TLB.

Parameters
VirtualAddressVirtual address to unhook
PhysAddressPhysical address to unhook (optional)
HookingTagHooking tag (optional)
ProcessIdThe process id of target process (in unhooking for some hooks only physical address is availables)
ApplyDirectlyFromVmxRootshould it be directly applied from VMX-root mode or not
TargetUnhookingDetailsTarget data for the caller to restore EPT entry and invalidate EPT caches. Only when applied in VMX-root mode directly
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false
2235{
2236 SIZE_T PhysicalAddress = NULL64_ZERO;
2237
2238 //
2239 // Once applied directly from VMX-root mode, the process id should be the same process Id
2240 // on current process
2241 //
2242 if (ApplyDirectlyFromVmxRoot || ProcessId == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES || ProcessId == 0)
2243 {
2244 ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
2245 }
2246
2247 //
2248 // Check if the physical address is available or not
2249 //
2250 if (PhysAddress != NULL64_ZERO)
2251 {
2252 PhysicalAddress = (SIZE_T)PAGE_ALIGN(PhysAddress);
2253 }
2254 else if (HookingTag == NULL64_ZERO)
2255 {
2256 if (ApplyDirectlyFromVmxRoot)
2257 {
2258 PhysicalAddress = (SIZE_T)(PAGE_ALIGN(VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)VirtualAddress)));
2259 }
2260 else
2261 {
2262 PhysicalAddress = (SIZE_T)(PAGE_ALIGN(VirtualAddressToPhysicalAddressByProcessId((PVOID)VirtualAddress,
2263 ProcessId)));
2264 }
2265 }
2266
2267 LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, CurrEntity)
2268 {
2269 //
2270 // Check if it's a hidden breakpoint or hidden detours
2271 //
2272 if (CurrEntity->IsHiddenBreakpoint)
2273 {
2274 //
2275 // It's a hidden breakpoint
2276 //
2277 for (SIZE_T i = 0; i < CurrEntity->CountOfBreakpoints; i++)
2278 {
2279 if (CurrEntity->BreakpointAddresses[i] == VirtualAddress)
2280 {
2282 VirtualAddress,
2283 ApplyDirectlyFromVmxRoot,
2284 TargetUnhookingDetails);
2285 }
2286 }
2287 }
2288 else
2289 {
2290 //
2291 // It's either a hidden detours or a monitor (read/write/execute) entry
2292 //
2293 if ((HookingTag != NULL64_ZERO && CurrEntity->HookingTag == HookingTag) || CurrEntity->PhysicalBaseAddress == PhysicalAddress)
2294 {
2296 ApplyDirectlyFromVmxRoot,
2297 TargetUnhookingDetails);
2298 }
2299 }
2300 }
2301
2302 //
2303 // Nothing found, probably the hooking detail is not found
2304 //
2305 return FALSE;
2306}
BOOLEAN EptHookUnHookSingleAddressDetoursAndMonitor(PEPT_HOOKED_PAGE_DETAIL HookedEntry, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
Remove single hook of detours type.
Definition EptHook.c:1922
BOOLEAN EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL HookedEntry, UINT64 VirtualAddress, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
Remove single hook of hidden breakpoint type.
Definition EptHook.c:2051
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
#define DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES
Apply the event to all the processes.
Definition Constants.h:745
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddressOnTargetProcess(_In_ PVOID VirtualAddress)
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddressByProcessId(_In_ PVOID VirtualAddress, _In_ UINT32 ProcessId)

◆ EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList()

BOOLEAN EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList ( UINT64 Address)

Remove the entry from g_EptHook2sDetourListHead in the case of !epthook2 details.

Remove an entry from g_EptHook2sDetourListHead.

Parameters
AddressAddress to remove
Returns
BOOLEAN TRUE if successfully removed and false if not found

Remove the entry from g_EptHook2sDetourListHead in the case of !epthook2 details.

Parameters
Address
Returns
BOOLEAN
1847{
1848 //
1849 // Iterate through the list of hooked pages details to find
1850 // the entry in the list
1851 //
1852 LIST_FOR_EACH_LINK(g_EptHook2sDetourListHead, HIDDEN_HOOKS_DETOUR_DETAILS, OtherHooksList, CurrentHookedDetails)
1853 {
1854 if (CurrentHookedDetails->HookedFunctionAddress == (PVOID)Address)
1855 {
1856 //
1857 // We found the address, we should remove it and add it for
1858 // future deallocation
1859 //
1860 RemoveEntryList(&CurrentHookedDetails->OtherHooksList);
1861
1862 //
1863 // Free the pool in next ioctl
1864 //
1865 if (!PoolManagerCallbackFreePool((UINT64)CurrentHookedDetails))
1866 {
1867 LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
1868 }
1869 return TRUE;
1870 }
1871 }
1872 //
1873 // No entry found !
1874 //
1875 return FALSE;
1876}

◆ EptHookReservePreallocatedPoolsForEptHooks()

VOID EptHookReservePreallocatedPoolsForEptHooks ( UINT32 Count)

Reserve pre-allocated pools for EPT hooks.

Allocate pre-allocated pools for EPT hooks.

Parameters
Countnumber of hooks
Returns
VOID

Reserve pre-allocated pools for EPT hooks.

Parameters
Countnumber of hooks
Returns
VOID
71{
72 ULONG ProcessorsCount;
73
74 //
75 // Get number of processors
76 //
77 ProcessorsCount = KeQueryActiveProcessorCount(0);
78
79 //
80 // Request pages to be allocated for converting 2MB to 4KB pages
81 // Each core needs its own splitting page-tables
82 //
84
85 //
86 // Request pages to be allocated for paged hook details
87 //
89
90 //
91 // Request pages to be allocated for Trampoline of Executable hooked pages
92 //
94
95 //
96 // Request pages to be allocated for detour hooked pages details
97 //
99}

◆ EptHookRestoreAllHooksToOriginalEntry()

VOID EptHookRestoreAllHooksToOriginalEntry ( VIRTUAL_MACHINE_STATE * VCpu)

Remove and Invalidate Hook in TLB.

Remove all hooks from the hooked pages lists (Should be called in vmx-root).

Warning
This function won't remove entries from LIST_ENTRY, just invalidate the paging, use EptHookUnHookAll instead
Parameters
VCpuThe virtual processor's state
Returns
VOID

Remove and Invalidate Hook in TLB.

Parameters
VCpu
Returns
VOID
720{
721 PEPT_PML1_ENTRY TargetPage;
722
723 //
724 // Should be called from vmx-root, for calling from vmx non-root use the corresponding VMCALL
725 //
727 {
728 return;
729 }
730
731 LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, HookedEntry)
732 {
733 //
734 // Pointer to the page entry in the page table
735 //
736 TargetPage = EptGetPml1Entry(VCpu->EptPageTable, HookedEntry->PhysicalBaseAddress);
737
738 //
739 // Apply the hook to EPT
740 //
741 TargetPage->AsUInt = HookedEntry->OriginalEntry.AsUInt;
742 }
743
744 //
745 // Invalidate EPT Cache
746 //
748}

◆ EptHookRestoreSingleHookToOriginalEntry()

BOOLEAN EptHookRestoreSingleHookToOriginalEntry ( VIRTUAL_MACHINE_STATE * VCpu,
SIZE_T PhysicalAddress,
UINT64 OriginalEntry )

Remove and Invalidate Hook in TLB (Hidden Detours and if counter of hidden breakpoint is zero).

Remove a special hook from the hooked pages lists.

Warning
This function won't remove entries from LIST_ENTRY, just invalidate the paging, use EptHookUnHookSingleAddress instead
Parameters
VCpuThe virtual processor's state
PhysicalAddress
OriginalEntry
Returns
BOOLEAN Return false if there was an error or returns true if it was successful

Remove and Invalidate Hook in TLB (Hidden Detours and if counter of hidden breakpoint is zero).

Parameters
VCpu
PhysicalAddress
OriginalEntry
Returns
BOOLEAN
674{
675 PEPT_PML1_ENTRY TargetPage;
676
677 //
678 // Should be called from vmx-root, for calling from vmx non-root use the corresponding VMCALL
679 //
681 {
682 return FALSE;
683 }
684 //
685 // Pointer to the page entry in the page table
686 //
687 TargetPage = EptGetPml1Entry(VCpu->EptPageTable, PhysicalAddress);
688
689 if (TargetPage != NULL)
690 {
691 //
692 // Apply the hook to EPT
693 //
694 TargetPage->AsUInt = OriginalEntry;
695
696 //
697 // Invalidate EPT Cache
698 //
700
701 return TRUE;
702 }
703
704 //
705 // The PML1 entry not found
706 //
707 return FALSE;
708}

◆ EptHookUnHookAll()

VOID EptHookUnHookAll ( )

Remove all hooks from the hooked pages list and invalidate TLB @detailsShould be called from Vmx Non-root.

Remove all hooks from the hooked pages lists.

Returns
VOID

Remove all hooks from the hooked pages list and invalidate TLB @detailsShould be called from Vmx Non-root.

Returns
VOID
2452{
2453 //
2454 // Should be called from vmx non-root
2455 //
2457 {
2458 return;
2459 }
2460
2461 //
2462 // Remove it in all the cores
2463 //
2465
2466 //
2467 // In the case of unhooking all pages, we remove the hooked
2468 // from EPT table in vmx-root and at last, we need to deallocate
2469 // it from the buffers
2470 //
2471
2472 LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, CurrEntity)
2473 {
2474 //
2475 // Now that we removed this hidden detours hook, it is
2476 // time to remove it from g_EptHook2sDetourListHead
2477 // if the hook is detours
2478 //
2479 if (!CurrEntity->IsHiddenBreakpoint)
2480 {
2481 EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList(CurrEntity->VirtualAddress);
2482 }
2483
2484 //
2485 // As we are in vmx-root here, we add the hooked entry to the list
2486 // of pools that will be deallocated on next IOCTL
2487 //
2488 if (!PoolManagerCallbackFreePool((UINT64)CurrEntity))
2489 {
2490 LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
2491 }
2492 }
2493}
BOOLEAN EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList(UINT64 Address)
Remove the entry from g_EptHook2sDetourListHead in the case of !epthook2 details.
Definition EptHook.c:1846
VOID DpcRoutineRemoveHookAndInvalidateAllEntriesOnAllCores(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
The broadcast function which removes all the hooks and invalidate TLB.
Definition DpcRoutines.c:1417

◆ EptHookUnHookAllByHookingTag()

BOOLEAN EptHookUnHookAllByHookingTag ( UINT64 HookingTag)

Remove all hooks from the hooked pages by the given hooking tag.

Should be called from Vmx Non-root

Parameters
HookingTagThe hooking tag to unhook
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false
2317{
2318 EPT_SINGLE_HOOK_UNHOOKING_DETAILS TargetUnhookingDetails; // not used
2319 BOOLEAN AtLeastOneUnhooked = FALSE;
2320 BOOLEAN UnhookingResult = FALSE;
2321
2322 //
2323 // Should be called from vmx non-root
2324 //
2326 {
2327 return FALSE;
2328 }
2329
2330KeepUnhooking:
2332 NULL_ZERO,
2333 HookingTag,
2334 NULL_ZERO,
2335 FALSE,
2336 &TargetUnhookingDetails);
2337
2338 if (UnhookingResult)
2339 {
2340 AtLeastOneUnhooked = TRUE;
2341
2342 //
2343 // Keep unhooking until there is no more hooking details
2344 //
2345 goto KeepUnhooking;
2346 }
2347
2348 return AtLeastOneUnhooked;
2349}
BOOLEAN EptHookPerformUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, UINT64 HookingTag, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS *TargetUnhookingDetails)
Remove single hook from the hooked pages list and invalidate TLB.
Definition EptHook.c:2229
struct _EPT_SINGLE_HOOK_UNHOOKING_DETAILS EPT_SINGLE_HOOK_UNHOOKING_DETAILS
Details of unhooking single EPT hooks.

◆ EptHookUnHookSingleAddress()

BOOLEAN EptHookUnHookSingleAddress ( UINT64 VirtualAddress,
UINT64 PhysAddress,
UINT32 ProcessId )

Remove single hook from the hooked pages list and invalidate TLB.

Remove single hook from the hooked pages list and invalidate TLB From VMX non-root mode.

Should be called from VMX non-root

Parameters
VirtualAddressVirtual address to unhook
PhysAddressPhysical address to unhook (optional)
ProcessIdThe process id of target process

in unhooking for some hooks only physical address is availables

Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false

Remove single hook from the hooked pages list and invalidate TLB.

Parameters
VirtualAddress
PhysAddress
ProcessId
Returns
BOOLEAN
2393{
2394 EPT_SINGLE_HOOK_UNHOOKING_DETAILS TargetUnhookingDetails; // not used
2395
2396 //
2397 // Should be called from VMX non-root
2398 //
2400 {
2401 return FALSE;
2402 }
2403
2404 return EptHookPerformUnHookSingleAddress(VirtualAddress,
2405 PhysAddress,
2406 NULL_ZERO,
2407 ProcessId,
2408 FALSE,
2409 &TargetUnhookingDetails);
2410}

◆ EptHookUnHookSingleAddressDetoursAndMonitor()

BOOLEAN EptHookUnHookSingleAddressDetoursAndMonitor ( PEPT_HOOKED_PAGE_DETAIL HookedEntry,
BOOLEAN ApplyDirectlyFromVmxRoot,
EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails )

Remove single hook of detours type.

Parameters
HookedEntryentry detail of hooked address
ApplyDirectlyFromVmxRootshould it be directly applied from VMX-root mode or not
TargetUnhookingDetailsTarget data for the caller to restore EPT entry and invalidate EPT caches. Only when applied in VMX-root mode directly
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false
1925{
1926 //
1927 // Set the unhooking details
1928 //
1929 TargetUnhookingDetails->PhysicalAddress = HookedEntry->PhysicalBaseAddress;
1930 TargetUnhookingDetails->OriginalEntry = HookedEntry->OriginalEntry.AsUInt;
1931
1932 //
1933 // If applied directly from VMX-root mode, it's the responsibility of the
1934 // caller to remove the hook and invalidate EPT caches for the target physical address
1935 //
1936 if (ApplyDirectlyFromVmxRoot)
1937 {
1938 TargetUnhookingDetails->CallerNeedsToRestoreEntryAndInvalidateEpt = TRUE;
1939 }
1940 else
1941 {
1942 //
1943 // Remove it in all the cores
1944 //
1945 TargetUnhookingDetails->CallerNeedsToRestoreEntryAndInvalidateEpt = FALSE;
1946 KeGenericCallDpc(DpcRoutineRemoveHookAndInvalidateSingleEntryOnAllCores, TargetUnhookingDetails);
1947 }
1948
1949 //
1950 // Now that we removed this hidden detours hook, it is
1951 // time to remove it from g_EptHook2sDetourListHead
1952 //
1953 if (HookedEntry->IsExecutionHook)
1954 {
1956 }
1957
1958 //
1959 // remove the entry from the list
1960 //
1961 RemoveEntryList(&HookedEntry->PageHookList);
1962
1963 //
1964 // we add the hooked entry to the list
1965 // of pools that will be deallocated on next IOCTL
1966 //
1967 if (!PoolManagerCallbackFreePool((UINT64)HookedEntry))
1968 {
1969 LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
1970 return FALSE;
1971 }
1972
1973 return TRUE;
1974}
VOID DpcRoutineRemoveHookAndInvalidateSingleEntryOnAllCores(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
The broadcast function which removes the single hook and invalidate TLB.
Definition DpcRoutines.c:1443
BOOLEAN CallerNeedsToRestoreEntryAndInvalidateEpt
Definition DataTypes.h:408
SIZE_T PhysicalAddress
Definition DataTypes.h:410
UINT64 OriginalEntry
Definition DataTypes.h:411

◆ EptHookUnHookSingleAddressFromVmxRoot()

BOOLEAN EptHookUnHookSingleAddressFromVmxRoot ( UINT64 VirtualAddress,
UINT64 PhysAddress,
EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails )

Remove single hook from the hooked pages list and invalidate TLB.

Remove single hook from the hooked pages list and invalidate TLB From VMX root-mode.

Should be called from VMX root-mode

Parameters
VirtualAddressVirtual address to unhook
PhysAddressPhysical address to unhook (optional)
TargetUnhookingDetailsTarget data for the caller to restore EPT entry and invalidate EPT caches. Only when applied in VMX-root mode directly
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false

Remove single hook from the hooked pages list and invalidate TLB.

Parameters
VirtualAddress
PhysAddress
TargetUnhookingDetails
Returns
BOOLEAN
2427{
2428 //
2429 // Should be called from VMX root-mode
2430 //
2432 {
2433 return FALSE;
2434 }
2435
2436 return EptHookPerformUnHookSingleAddress(VirtualAddress,
2437 PhysAddress,
2439 NULL_ZERO,
2440 TRUE,
2441 TargetUnhookingDetails);
2442}

◆ EptHookUnHookSingleAddressHiddenBreakpoint()

BOOLEAN EptHookUnHookSingleAddressHiddenBreakpoint ( PEPT_HOOKED_PAGE_DETAIL HookedEntry,
UINT64 VirtualAddress,
BOOLEAN ApplyDirectlyFromVmxRoot,
EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails )

Remove single hook of hidden breakpoint type.

Parameters
HookedEntryentry detail of hooked address
VirtualAddressvirtual address to unhook
ApplyDirectlyFromVmxRootshould it be directly applied from VMX-root mode or not
TargetUnhookingDetailsTarget data for the caller to restore EPT entry and invalidate EPT caches. Only when applied in VMX-root mode directly
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false
2055{
2056 UINT64 TargetAddressInFakePageContent;
2057 UINT32 CountOfEntriesWithSameAddr = 0;
2058
2059 //
2060 // By default, the caller doesn't need to remove #BPs interceptions if directly
2061 // applied from VMX-root mode
2062 //
2063 TargetUnhookingDetails->RemoveBreakpointInterception = FALSE;
2064
2065 //
2066 // It's a hidden breakpoint (we have to search through an array of addresses)
2067 // We count it from top to down because if there are two ept hooks at the
2068 // same address, then the last one has an invalid PreviousByte and this
2069 // is the HookedEntry that should be remove (not the first one as it has the
2070 // correct PreviousByte)
2071 //
2072 for (SIZE_T i = 0; i < HookedEntry->CountOfBreakpoints; i++)
2073 {
2074 if (HookedEntry->BreakpointAddresses[i] == VirtualAddress)
2075 {
2076 //
2077 // Check if it's a single breakpoint
2078 //
2079 if (HookedEntry->CountOfBreakpoints == 1)
2080 {
2081 //
2082 // Set the unhooking details
2083 //
2084 TargetUnhookingDetails->PhysicalAddress = HookedEntry->PhysicalBaseAddress;
2085 TargetUnhookingDetails->OriginalEntry = HookedEntry->OriginalEntry.AsUInt;
2086
2087 //
2088 // If applied directly from VMX-root mode, it's the responsibility of the
2089 // caller to remove the hook and invalidate EPT caches for the target physical address
2090 //
2091 if (ApplyDirectlyFromVmxRoot)
2092 {
2093 //
2094 // The caller is responsible for restoring EPT entry and invalidate caches
2095 //
2096 TargetUnhookingDetails->CallerNeedsToRestoreEntryAndInvalidateEpt = TRUE;
2097 }
2098 else
2099 {
2100 //
2101 // Remove the hook entirely on all cores
2102 //
2103 TargetUnhookingDetails->CallerNeedsToRestoreEntryAndInvalidateEpt = FALSE;
2104 KeGenericCallDpc(DpcRoutineRemoveHookAndInvalidateSingleEntryOnAllCores, TargetUnhookingDetails);
2105 }
2106
2107 //
2108 // remove the entry from the list
2109 //
2110 RemoveEntryList(&HookedEntry->PageHookList);
2111
2112 //
2113 // we add the hooked entry to the list
2114 // of pools that will be deallocated on next IOCTL
2115 //
2116 if (!PoolManagerCallbackFreePool((UINT64)HookedEntry))
2117 {
2118 LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
2119 }
2120
2121 //
2122 // Check if there is any other breakpoints, if no then we have to disable
2123 // exception bitmaps on vm-exits for breakpoint, for this purpose, we have
2124 // to visit all the entries to see if there is any entries
2125 //
2127 {
2128 //
2129 // If applied directly from VMX-root mode, it's the responsibility of the
2130 // caller to broadcast to disable breakpoint exceptions on all cores
2131 //
2132 if (ApplyDirectlyFromVmxRoot)
2133 {
2134 //
2135 // Set whether it was the last hook (and the caller if applied from VMX-root needed
2136 // to broadcast to disable #BPs interception on exception bitmaps or not)
2137 //
2138 TargetUnhookingDetails->RemoveBreakpointInterception = TRUE;
2139 }
2140 else
2141 {
2142 //
2143 // Did not find any entry, let's disable the breakpoints vm-exits
2144 // on exception bitmaps
2145 //
2146 TargetUnhookingDetails->RemoveBreakpointInterception = FALSE;
2148 }
2149 }
2150
2151 return TRUE;
2152 }
2153 else
2154 {
2155 //
2156 // Set 0xcc to its previous value
2157 //
2158 TargetAddressInFakePageContent = EptHookCalcBreakpointOffset((PVOID)VirtualAddress, HookedEntry);
2159
2160 //
2161 // We'll check if there is another hooked address with the same virtual address
2162 // in the array, then we'll ignore setting the previous bit as previous bit might
2163 // be modified for the previous command
2164 //
2165 for (SIZE_T j = 0; j < HookedEntry->CountOfBreakpoints; j++)
2166 {
2167 if (HookedEntry->BreakpointAddresses[j] == VirtualAddress)
2168 {
2169 CountOfEntriesWithSameAddr++;
2170 }
2171 }
2172
2173 if (CountOfEntriesWithSameAddr == 1)
2174 {
2175 //
2176 // Set the previous value
2177 //
2178 *(BYTE *)TargetAddressInFakePageContent = HookedEntry->PreviousBytesOnBreakpointAddresses[i];
2179 }
2180
2181 //
2182 // Remove just that special entry
2183 // BTW, No need to remove it, it will be replaced automatically
2184 //
2185 HookedEntry->BreakpointAddresses[i] = NULL64_ZERO;
2186 HookedEntry->PreviousBytesOnBreakpointAddresses[i] = 0x0;
2187
2188 //
2189 // all addresses to a lower array index (because one entry is
2190 // missing and might) be in the middle of the array
2191 //
2192 for (SIZE_T j = i /* IndexToRemove */; j < HookedEntry->CountOfBreakpoints - 1; j++)
2193 {
2194 HookedEntry->BreakpointAddresses[j] = HookedEntry->BreakpointAddresses[j + 1];
2195 HookedEntry->PreviousBytesOnBreakpointAddresses[j] = HookedEntry->PreviousBytesOnBreakpointAddresses[j + 1];
2196 }
2197
2198 //
2199 // Decrease the count of breakpoints
2200 //
2201 HookedEntry->CountOfBreakpoints = HookedEntry->CountOfBreakpoints - 1;
2202
2203 return TRUE;
2204 }
2205 }
2206 }
2207
2208 //
2209 // If we reach here, sth went wrong
2210 //
2211 return FALSE;
2212}
UINT32 EptHookGetCountOfEpthooks(BOOLEAN IsEptHook2)
get the length of active EPT hooks (!epthook and !epthook2)
Definition EptHook.c:1885
unsigned char BYTE
Definition BasicTypes.h:40
IMPORT_EXPORT_VMM VOID BroadcastDisableBreakpointExitingOnExceptionBitmapAllCores()
routines to disable vm-exit for breakpoints (exception bitmap)
Definition Broadcast.c:77
UINT64 BreakpointAddresses[MaximumHiddenBreakpointsOnPage]
Address of hooked pages (multiple breakpoints on a single page) this is only used in hidden breakpoin...
Definition State.h:280
UINT64 CountOfBreakpoints
Count of breakpoints (multiple breakpoints on a single page) this is only used in hidden breakpoints ...
Definition State.h:292
BOOLEAN RemoveBreakpointInterception
Definition DataTypes.h:409

◆ EptHookUnHookSingleHookByHookingTagFromVmxRoot()

BOOLEAN EptHookUnHookSingleHookByHookingTagFromVmxRoot ( UINT64 HookingTag,
EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails )

Remove single hook from the hooked pages by the given hooking tag.

Should be called from Vmx root-mode

Parameters
HookingTagThe hooking tag to unhook
Returns
BOOLEAN If unhook was successful it returns true or if it was not successful returns false
2361{
2362 //
2363 // Should be called from VMX root-mode
2364 //
2366 {
2367 return FALSE;
2368 }
2369
2372 HookingTag,
2373 NULL_ZERO,
2374 TRUE,
2375 TargetUnhookingDetails);
2376}

◆ EptHookWriteAbsoluteJump()

VOID EptHookWriteAbsoluteJump ( PCHAR TargetBuffer,
SIZE_T TargetAddress )

Write an absolute x64 jump to an arbitrary address to a buffer.

Parameters
TargetBuffer
TargetAddress
Returns
VOID
759{
760 //
761 // call $ + 5 ; A 64-bit call instruction is still 5 bytes wide!
762 //
763
764 TargetBuffer[0] = 0xe8;
765 TargetBuffer[1] = 0x00;
766 TargetBuffer[2] = 0x00;
767 TargetBuffer[3] = 0x00;
768 TargetBuffer[4] = 0x00;
769
770 //
771 // push Lower 4-byte TargetAddress
772 //
773 TargetBuffer[5] = 0x68;
774
775 //
776 // Lower 4-byte TargetAddress
777 //
778 *((PUINT32)&TargetBuffer[6]) = (UINT32)TargetAddress;
779
780 //
781 // mov [rsp+4],High 4-byte TargetAddress
782 //
783 TargetBuffer[10] = 0xC7;
784 TargetBuffer[11] = 0x44;
785 TargetBuffer[12] = 0x24;
786 TargetBuffer[13] = 0x04;
787
788 //
789 // High 4-byte TargetAddress
790 //
791 *((PUINT32)&TargetBuffer[14]) = (UINT32)(TargetAddress >> 32);
792
793 //
794 // ret
795 //
796 TargetBuffer[18] = 0xC3;
797}
unsigned int * PUINT32
Definition BasicTypes.h:54

◆ EptHookWriteAbsoluteJump2()

VOID EptHookWriteAbsoluteJump2 ( PCHAR TargetBuffer,
SIZE_T TargetAddress )

Write an absolute x64 jump to an arbitrary address to a buffer.

Parameters
TargetBuffer
TargetAddress
Returns
VOID
808{
809 //
810 // push Lower 4-byte TargetAddress
811 //
812 TargetBuffer[0] = 0x68;
813
814 //
815 // Lower 4-byte TargetAddress
816 //
817 *((PUINT32)&TargetBuffer[1]) = (UINT32)TargetAddress;
818
819 //
820 // mov [rsp+4],High 4-byte TargetAddress
821 //
822 TargetBuffer[5] = 0xC7;
823 TargetBuffer[6] = 0x44;
824 TargetBuffer[7] = 0x24;
825 TargetBuffer[8] = 0x04;
826
827 //
828 // High 4-byte TargetAddress
829 //
830 *((PUINT32)&TargetBuffer[9]) = (UINT32)(TargetAddress >> 32);
831
832 //
833 // ret
834 //
835 TargetBuffer[13] = 0xC3;
836}

◆ ExAllocatePoolWithTagHook()

PVOID ExAllocatePoolWithTagHook ( POOL_TYPE PoolType,
SIZE_T NumberOfBytes,
ULONG Tag )

Hook function that HooksExAllocatePoolWithTag.

Parameters
PoolType
NumberOfBytes
Tag
Returns
PVOID
460{
461 LogInfo("ExAllocatePoolWithTag Called with : Tag = 0x%x, Number Of Bytes = 0x%x, Pool Type = 0x%x ",
462 Tag,
464 PoolType);
465
466 return ExAllocatePoolWithTagOrig(PoolType, NumberOfBytes, Tag);
467}
POOL_TYPE PoolType
Definition Hooks.h:87
POOL_TYPE SIZE_T NumberOfBytes
Definition Hooks.h:88
POOL_TYPE SIZE_T ULONG Tag
Definition Hooks.h:89