Bitdefender Hypervisor Memory Introspection
hook_gpa.c File Reference
#include "hook.h"
#include "hook_gpa.h"
#include "callbacks.h"
#include "introcpu.h"
#include "ptfilter.h"

Go to the source code of this file.

Functions

PHOOK_EPT_ENTRY IntHookGpaGetEptEntry (QWORD GpaPage)
 Get the EPT entry associated with a physical page. More...
 
static INTSTATUS IntHookGpaGetSppEntry (HOOK_EPT_ENTRY *Entry)
 Allocates a SPP entry for the given EPT hook. More...
 
static void IntHookGpaInsertHookInList (LIST_ENTRY *List, HOOK_GPA *Hook)
 Insert the hook in the given list of hooks. More...
 
PHOOK_EPT_ENTRY IntHookGpaGetExistingEptEntry (QWORD GpaPage)
 Get the EPT entry associated with the provided guest physical page. More...
 
INTSTATUS IntHookGpaSetHook (QWORD Gpa, DWORD Length, BYTE Type, PFUNC_EptViolationCallback Callback, void *Context, void *ParentHook, DWORD Flags, HOOK_GPA **Hook)
 Places an EPT hook on the indicated memory range. More...
 
static INTSTATUS IntHookGpaSetNewPageProtection (HOOK_GPA *Hook)
 Update EPT protection for a removed hook. More...
 
static INTSTATUS IntHookGpaRemoveHookInternal (HOOK_GPA *Hook, DWORD Flags)
 Remove a GPA hook. More...
 
INTSTATUS IntHookGpaRemoveHook (HOOK_GPA **Hook, DWORD Flags)
 Remove a GPA hook. More...
 
static INTSTATUS IntHookGpaDeleteHookInternal (HOOK_GPA *Hook, DWORD Flags)
 Permanently delete a GPA hook. More...
 
INTSTATUS IntHookGpaDeleteHook (HOOK_GPA **Hook, DWORD Flags)
 Permanently delete a GPA hook. More...
 
INTSTATUS IntHookGpaCommitHooks (void)
 Commit existing modified hooks. More...
 
INTSTATUS IntHookGpaDisableHook (HOOK_GPA *Hook)
 Disable a GPA hook. More...
 
INTSTATUS IntHookGpaEnableHook (HOOK_GPA *Hook)
 Enable a GPA hook. More...
 
INTSTATUS IntHookGpaIsPageHooked (QWORD Gpa, BYTE *Read, BYTE *Write, BYTE *Execute)
 Get the read, write and execute access for the given guest physical page. More...
 
INTSTATUS IntHookGpaInit (void)
 Initialize the GPA hook system. This function should be called only once, during introspection init. More...
 
void IntHookGpaDump (void)
 Dump the entire contents of the GPA hook system, listing each hook. More...
 
static INTSTATUS IntHookGpaEnableDisableVe (BOOLEAN Enable)
 Enable or disable the VE filtering mechanism. More...
 
static INTSTATUS IntHookGpaEnableDisablePtCache (BOOLEAN Enable)
 Enable or disable the in guest PT filtering mechanism. More...
 
INTSTATUS IntHookGpaEnableVe (void)
 Enable VE filtering. More...
 
INTSTATUS IntHookGpaEnablePtCache (void)
 Enable PT filtering. More...
 
INTSTATUS IntHookGpaDisableVe (void)
 Disable VE filtering. More...
 
INTSTATUS IntHookGpaDisablePtCache (void)
 Disable PT filtering. More...
 
INTSTATUS IntHookGpaGetEPTPageProtection (DWORD EptIndex, QWORD Address, BYTE *Read, BYTE *Write, BYTE *Execute)
 Get the EPT page protection for the indicated guest physical address. More...
 
INTSTATUS IntHookGpaFindConvertible (void)
 Displays all convertible pages. More...
 

Function Documentation

◆ IntHookGpaCommitHooks()

INTSTATUS IntHookGpaCommitHooks ( void  )

Commit existing modified hooks.

This function will iterate the list of removed hooks, and it will actually delete them. Hooks which are flagged with HOOK_FLG_CHAIN_DELETE will not be deleted, as it is expected that someone else will delete them (this happens when a higher-level hook system wants to delete an entire chain of hooks).

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 876 of file hook_gpa.c.

Referenced by IntHookCommitAllHooks().

◆ IntHookGpaDeleteHook()

INTSTATUS IntHookGpaDeleteHook ( HOOK_GPA **  Hook,
DWORD  Flags 
)

Permanently delete a GPA hook.

This function will permanently delete the hook, restoring the original EPT access rights. This function must be called only if IntHookGpaRemoveHook with the HOOK_FLG_CHAIN_DELETE has been called before.

Parameters
[in,out]HookThe hook to be deleted.
[in]FlagsFlags.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 830 of file hook_gpa.c.

Referenced by IntHookGvaDeleteHookInternal(), IntHookPtmDeleteTableHook(), and IntLixVdsoUnprotect().

◆ IntHookGpaDeleteHookInternal()

static INTSTATUS IntHookGpaDeleteHookInternal ( HOOK_GPA Hook,
DWORD  Flags 
)
static

Permanently delete a GPA hook.

Parameters
[in,out]HookThe hook to be deleted.
[in]FlagsFlags.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 788 of file hook_gpa.c.

Referenced by IntHookGpaCommitHooks(), and IntHookGpaDeleteHook().

◆ IntHookGpaDisableHook()

INTSTATUS IntHookGpaDisableHook ( HOOK_GPA Hook)

Disable a GPA hook.

Disables the indicated hook. The hook will not be removed, but the callback will not be called anymore.

Parameters
[in]HookThe hook to be disabled.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 951 of file hook_gpa.c.

◆ IntHookGpaDisablePtCache()

INTSTATUS IntHookGpaDisablePtCache ( void  )

Disable PT filtering.

Definition at line 1442 of file hook_gpa.c.

Referenced by IntPtiDisableFiltering(), and IntPtiEnableFiltering().

◆ IntHookGpaDisableVe()

INTSTATUS IntHookGpaDisableVe ( void  )

Disable VE filtering.

Definition at line 1430 of file hook_gpa.c.

Referenced by IntVeDeployUnloader(), and IntVeRemoveAgent().

◆ IntHookGpaDump()

void IntHookGpaDump ( void  )

Dump the entire contents of the GPA hook system, listing each hook.

Definition at line 1156 of file hook_gpa.c.

Referenced by IntHandleEptViolation().

◆ IntHookGpaEnableDisablePtCache()

static INTSTATUS IntHookGpaEnableDisablePtCache ( BOOLEAN  Enable)
static

Enable or disable the in guest PT filtering mechanism.

When enabling PT filtering, the function will mark all page-tables as being writable inside the EPT. When disabling PT filtering, it will mark all page-table pages non-writable inside EPT.

Parameters
[in]EnableTrue if the PT filtering is to be enabled, false otherwise.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf Enable is true and PT filtering is already enabled, or if Enable is false and PT filtering is already disabled.

Definition at line 1344 of file hook_gpa.c.

Referenced by IntHookGpaDisablePtCache(), and IntHookGpaEnablePtCache().

◆ IntHookGpaEnableDisableVe()

static INTSTATUS IntHookGpaEnableDisableVe ( BOOLEAN  Enable)
static

Enable or disable the VE filtering mechanism.

When enabling VE filtering, the function will mark all page-tables as being convertible inside the EPT. When disabling VE filtering, it will remove the convertible flag from all page-table pages.

Parameters
[in]EnableTrue if the VE filtering is to be enabled, false otherwise.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf Enable is true and VE filtering is already enabled, or if Enable is false and VE filtering is already disabled.

Definition at line 1259 of file hook_gpa.c.

Referenced by IntHookGpaDisableVe(), and IntHookGpaEnableVe().

◆ IntHookGpaEnableHook()

INTSTATUS IntHookGpaEnableHook ( HOOK_GPA Hook)

Enable a GPA hook.

Enables a hook. Once a hook is enabled, the callback will be called again for accesses inside the hooked region. NOTE: When setting a GPA hook, it is enabled by default. This function must be called only if one wishes to re-enable a hook previously disabled using IntHookGpaDisableHook.

Parameters
[in]HookThe GPA hook to be enabled.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 977 of file hook_gpa.c.

◆ IntHookGpaEnablePtCache()

INTSTATUS IntHookGpaEnablePtCache ( void  )

Enable PT filtering.

Definition at line 1418 of file hook_gpa.c.

Referenced by IntPtiEnableFiltering().

◆ IntHookGpaEnableVe()

INTSTATUS IntHookGpaEnableVe ( void  )

Enable VE filtering.

Definition at line 1406 of file hook_gpa.c.

Referenced by IntVeCompleteLoader().

◆ IntHookGpaFindConvertible()

INTSTATUS IntHookGpaFindConvertible ( void  )

Displays all convertible pages.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1499 of file hook_gpa.c.

◆ IntHookGpaGetEptEntry()

PHOOK_EPT_ENTRY IntHookGpaGetEptEntry ( QWORD  GpaPage)

Get the EPT entry associated with a physical page.

This function will search for an existing EPT entry, and return it. If none is found, it will allocate one, insert it in the EPT entry list, and return it.

Parameters
[in]GpaPageGuest physical page whose EPT entry is to be returned. Low 12 bits are ignored.
Returns
The EPT entry associated with the provided guest physical page, or NULL if none is found and a memory alloc fails.

Definition at line 18 of file hook_gpa.c.

Referenced by IntHookGpaSetHook(), and IntHookGpaSetNewPageProtection().

◆ IntHookGpaGetEPTPageProtection()

INTSTATUS IntHookGpaGetEPTPageProtection ( DWORD  EptIndex,
QWORD  Address,
BYTE Read,
BYTE Write,
BYTE Execute 
)

Get the EPT page protection for the indicated guest physical address.

Parameters
[in]EptIndexThe EPT for which the rights are taken. Must be the UntrustedEptIndex.
[in]AddressGuest physical address whose access rights are queried.
[out]ReadWill be 1 if the page is readable, 0 otherwise.
[out]WriteWill be 1 if the page is writable, 0 otherwise.
[out]ExecuteWill be 1 if the page is executable, 0 otherwise.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 1454 of file hook_gpa.c.

Referenced by IntValidateRangeForWrite(), and IntVirtMemSafeWrite().

◆ IntHookGpaGetExistingEptEntry()

PHOOK_EPT_ENTRY IntHookGpaGetExistingEptEntry ( QWORD  GpaPage)

Get the EPT entry associated with the provided guest physical page.

Parameters
[in]GpaPageThe guest physical page for which the EPT entry must be retrieved. Low 12 bits are ignored.
Returns
The EPT entry associated with the provided guest physical page, or NULL if none is found.

Definition at line 161 of file hook_gpa.c.

Referenced by IntHookGpaGetEptEntry(), IntHookGpaGetEPTPageProtection(), and IntValidatePageRightsEx().

◆ IntHookGpaGetSppEntry()

static INTSTATUS IntHookGpaGetSppEntry ( HOOK_EPT_ENTRY Entry)
static

Allocates a SPP entry for the given EPT hook.

Allocates a SPP entry for the provided EPT entry. SPP entries are used to describe 128 bytes granularity hooks on capable Intel CPUs. If no write hooks exist inside the given page, the SPP entry will be initialized to the default value indicating that sub-page writes are allowed. If at least a hook is present on this page, the SPP entry will be initialized assuming that the entire page is hooked. This function must be called whenever placing the first write hook that does not cover the entire page (less than 4K).

Parameters
[in,out]EntryThe EPT entry whose SPP entry is to be allocated.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory allocation function fails.
INT_STATUS_ALREADY_INITIALIZEDIf the SPP entry has already been allocated for this EPT entry.

Definition at line 63 of file hook_gpa.c.

Referenced by IntHookGpaSetHook().

◆ IntHookGpaInit()

INTSTATUS IntHookGpaInit ( void  )

Initialize the GPA hook system. This function should be called only once, during introspection init.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1097 of file hook_gpa.c.

Referenced by IntHookInit().

◆ IntHookGpaInsertHookInList()

static void IntHookGpaInsertHookInList ( LIST_ENTRY List,
HOOK_GPA Hook 
)
static

Insert the hook in the given list of hooks.

Inserts the provided hook inside the given hooks list. This function must be used whenever inserting hooks inside a list, as it takes into account high-priority hooks - hooks that must be called before the regular ones.

Parameters
[in,out]ListThe list where the hook must be inserted.
[in]HookThe hook that must be inserted in the list.

Definition at line 119 of file hook_gpa.c.

Referenced by IntHookGpaSetHook().

◆ IntHookGpaIsPageHooked()

INTSTATUS IntHookGpaIsPageHooked ( QWORD  Gpa,
BYTE Read,
BYTE Write,
BYTE Execute 
)

Get the read, write and execute access for the given guest physical page.

Parameters
[in]GpaThe guest physical page for which read, write & execute access is queried.
[out]ReadWill contain, upon successful return, 1 if the page is readable, 0 if it is read-hooked.
[out]WriteWill contain, upon successful return, 1 if the page is writable, 0 if it is write-hooked.
[out]ExecuteWill contain, upon successful return, 1 if the page is executable, 0 if it is execute-hooked.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 1006 of file hook_gpa.c.

Referenced by IntVirtMemSafeWrite().

◆ IntHookGpaRemoveHook()

INTSTATUS IntHookGpaRemoveHook ( HOOK_GPA **  Hook,
DWORD  Flags 
)

Remove a GPA hook.

This function will only flag the current hook for removal. No other action will be taken. The hook will then be removed during the commit phase. Once this function is called, the hook callback will not be called anymore.

Parameters
[in,out]HookThe GPA hook to be removed.
[in]FlagsFlags. If HOOK_FLG_CHAIN_DELETE is set, the function will just mark the hook as being removed; the actual deletion will be done by calling the IntHookGpaDeleteHook.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the hook has already been marked for removal.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 738 of file hook_gpa.c.

Referenced by IntHookGvaDisableHooks(), IntHookGvaRemoveHookInternal(), IntHookPtmAddTable(), IntHookPtmRemoveTableHook(), IntHookRemoveChain(), IntIcFreeInvdEntry(), IntVasHookTables(), IntVasUnHookTables(), IntWinSelfMapHandleCr3SelfMapWrite(), and IntWinSelfMapUnprotectSelfMapIndex().

◆ IntHookGpaRemoveHookInternal()

static INTSTATUS IntHookGpaRemoveHookInternal ( HOOK_GPA Hook,
DWORD  Flags 
)
static

Remove a GPA hook.

This function will only flag the current hook for removal. No other action will be taken. The hook will then be removed during the commit phase. Once this function is called, the hook callback will not be called anymore.

Parameters
[in]HookThe GPA hook to be removed.
[in]FlagsFlags. If HOOK_FLG_CHAIN_DELETE is set, the function will just mark the hook as being removed; the actual deletion will be done by calling the IntHookGpaDeleteHook.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the hook has already been marked for removal.

Definition at line 675 of file hook_gpa.c.

Referenced by IntHookGpaRemoveHook().

◆ IntHookGpaSetHook()

INTSTATUS IntHookGpaSetHook ( QWORD  Gpa,
DWORD  Length,
BYTE  Type,
PFUNC_EptViolationCallback  Callback,
void *  Context,
void *  ParentHook,
DWORD  Flags,
HOOK_GPA **  Hook 
)

Places an EPT hook on the indicated memory range.

Establishes a memory hook, using the EPT/NPT, on the provided guest physical address. The provided guest physical address needs not be page aligned, but the memory area for which the hook is placed must not exceed the page boundary. Whenever the indicated access (read, write, execute) takes place inside the hooked range, the provided callback will be called (see PFUNC_EptViolationCallback for more info). Note that the CPU may trigger events for accesses outside the hooked range - these will not cause the callback to be called, but they will induce a significant performance penalty, so care must be taken when placing memory hooks. The minimum granularity of a hook is given by the hardware page size, and it usually is 4K - this means that placing a hook on a range of 4 bytes will still trigger events for the entire page, but the provided callback will be called if and only if at least on byte inside the hooked range is accessed. If a write hook is placed on a CPU & HV which supports sub-page permissions (SPP), the hook granularity is reduced to 128 bytes. Please refer to the Intel docs for more information, and take into consideration that even if a SPP hook is placed on a 128 bytes region, events may still be generated for accesses outside that region. Accepted hook types are:

  • IG_EPT_HOOK_READ - read hook, call the callback on each read access.
  • IG_EPT_HOOK_WRITE - write hook, call the callback on each write access.
  • IG_EPT_HOOK_EXECUTE - execute hook, call the callback on each instruction fetch. NOTE: Placing a read-only hook is not supported by Intel hardware (a page cannot be writable without having read permissions). Therefore, if you wish to establish a read hook on a page, make sure you first set a write hook, in order to avoid an EPT misconfiguration. NOTE: Placing a write hook on a page table (as indicated by HOOK_FLG_PAGING_STRUCTURE, HOOK_FLG_PAE_ROOT, and HOOK_FLG_PT_UM_ROOT flags) may be treated differently than placing a hook on a regular page:
  • If the PT filter is enabled, the page will not actually be hooked in EPT, meaning that it will remain writable; however, accesses will be instrumented directly inside the guest, and relevant modifications will be reported to introspection;
  • If VE and VMFUNC are supported by the CPU and the HV, the page will be marked non-writable inside the EPT, and it will also be marked convertible, meaning that instead of EPT violations, VEs will be generated inside the guest. Inside the guest, a filtering agent exists which analyzes page-table writes, and raises a VMCALL to introspection only if the access is deemed relevant (for example, simply modifying the A/D bits will not lead to a VM exit). Also note that when hooking page-tables against writes, the Intel CPUs will generate an EPT violation on every page walk, if it has to set the A/D bits; Due to performance concerns, these EPT violations are handled directly inside the HV, and they are never sent to introspection; therefore, the callback will never be called for page-walk induced EPT violations. NOTE: Some Intel CPUs do not support execute-only EPT hooks. NOTE: There is a limit on how many hooks of a given type can be placed on a given page - this limit is MAX_HOOK_COUNT - MAX_HOOK_COUNT read, write and execute hooks can be placed on the same page. NOTE: This function will invoke the integrator/HV in order to alter the EPT access rights for the provided guest physical page. However, these requests may be cached and/or TLB shoot-down may take place only when the current VCPU enters back in guest mode. This means that placing a hook does not guarantee that events will take place immediately. If the caller needs this guarantee, it has to pause the VCPUs, set the hook, and then immediately resume the VCPUs, as on each VCPU resume, all EPT access rights are committed immediately. NOTE: The callback will be called whenever an instruction does the indicated access inside the hooked region; however, it may be called in cases where the instruction does not appear to directly access the area - this may happen when implicit memory accesses are made by the CPU to that area; for example, delivering an interrupt or on exception will trigger writes on the stack, in order to save the interrupt frame; if that area of the stack is write-hooked, the callback will be invoked, even if the current instruction does no memory access at all. NOTE: IG_EPT_HOOK_READ, IG_EPT_HOOK_WRITE, IG_EPT_HOOK_EXECUTE cannot be combined. Only one hook type can be set with one call to this function. If one want to place multiple hook types (for example, both a read and a write hook), this function must be called twice - one for the write hook, and once for the read hook.
Parameters
[in]GpaGuest physical address to be hooked.
[in]LengthThe length of the region to be hooked: [Gpa, Gpa + Length - 1].
[in]TypeEPT hook type: IG_EPT_HOOK_READ, IG_EPT_HOOK_WRITE or IG_EPT_HOOK_EXECUTE.
[in]CallbackFunction to be called whenever the indicated access is made inside [Gpa, Gpa + Length - 1].
[in]ContextOptional context that will be passed to the Callback function when an access is made.
[in]ParentHookHooks can be chained, so if an upper-level hook system places a GPA hook, it should use this argument to indicate the higher level hook structure.
[in]FlagsHook flags. Please see HOOK_FLG_* for more info.
[out]HookA pointer to a hook handle. Upon successful return, this will contain the hook handle which can be later used to remove the hook.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_SUPPORTEDIf the hooked area spans outside the given page.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory allocation fails.
INT_STATUS_ARITHMETIC_OVERFLOWIf too many hooks have been placed on the page.

Definition at line 193 of file hook_gpa.c.

Referenced by IntHookGvaEnableHooks(), IntHookPtmAddTable(), IntIcAddInvdForInstruction(), IntLixVdsoDynamicProtectRelocate(), IntVasHookTables(), and IntWinSelfMapProtectSelfMapIndex().

◆ IntHookGpaSetNewPageProtection()

static INTSTATUS IntHookGpaSetNewPageProtection ( HOOK_GPA Hook)
static

Update EPT protection for a removed hook.

Given a GPA hook entry that is being removed, this function will update the EPT access rights according to the hook entry. NOTE: This function will trigger a bug-check if a hook with a 0 reference count is being removed.

Parameters
[in]HookThe GPA hook entry.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory allocation fails.

Definition at line 520 of file hook_gpa.c.

Referenced by IntHookGpaDeleteHookInternal().