Bitdefender Hypervisor Memory Introspection
hook_gpa.h File Reference
#include "queue.h"

Go to the source code of this file.

Data Structures

struct  _HOOK_GPA
 
struct  _HOOK_SPP_ENTRY
 
struct  _HOOK_EPT_ENTRY
 
struct  _HOOK_GPA_STATE
 

Macros

#define GPA_HOOK_TABLE_SIZE   1024
 Size of the GPA hook hash. More...
 
#define GPA_HOOK_ID(addr)   (((addr) >> 12) & (GPA_HOOK_TABLE_SIZE - 1))
 
#define GPA_EPT_TABLE_SIZE   4096
 Size of the EPT entries hash. More...
 
#define GPA_EPT_ID(addr)   (((addr) >> 12) & (GPA_EPT_TABLE_SIZE - 1))
 
#define GPA_REF_COUNT(epte)
 
#define MAX_HOOK_COUNT   UINT32_MAX
 Total number of hooks supported for each type. More...
 

Typedefs

typedef struct _HOOK_HEADER HOOK_HEADER
 
typedef INTSTATUS(* PFUNC_EptViolationCallback) (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 EPT callback handler. More...
 
typedef struct _HOOK_GPA HOOK_GPA
 
typedef struct _HOOK_GPAPHOOK_GPA
 
typedef struct _HOOK_SPP_ENTRY HOOK_SPP_ENTRY
 
typedef struct _HOOK_SPP_ENTRYPHOOK_SPP_ENTRY
 
typedef struct _HOOK_EPT_ENTRY HOOK_EPT_ENTRY
 
typedef struct _HOOK_EPT_ENTRYPHOOK_EPT_ENTRY
 
typedef struct _HOOK_GPA_STATE HOOK_GPA_STATE
 
typedef struct _HOOK_GPA_STATEPHOOK_GPA_STATE
 

Functions

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...
 
INTSTATUS IntHookGpaRemoveHook (HOOK_GPA **Hook, DWORD Flags)
 Remove a GPA hook. More...
 
INTSTATUS IntHookGpaDeleteHook (HOOK_GPA **Hook, DWORD Flags)
 Permanently delete a GPA hook. More...
 
INTSTATUS IntHookGpaDisableHook (HOOK_GPA *Hook)
 Disable a GPA hook. More...
 
INTSTATUS IntHookGpaEnableHook (HOOK_GPA *Hook)
 Enable a GPA hook. More...
 
INTSTATUS IntHookGpaCommitHooks (void)
 Commit existing modified hooks. 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 IntHookGpaEnableVe (void)
 Enable VE filtering. More...
 
INTSTATUS IntHookGpaDisableVe (void)
 Disable VE filtering. 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...
 
INTSTATUS IntHookGpaEnablePtCache (void)
 Enable PT 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...
 

Macro Definition Documentation

◆ GPA_EPT_ID

#define GPA_EPT_ID (   addr)    (((addr) >> 12) & (GPA_EPT_TABLE_SIZE - 1))

Definition at line 91 of file hook_gpa.h.

Referenced by IntHookGpaGetEptEntry(), and IntHookGpaGetExistingEptEntry().

◆ GPA_EPT_TABLE_SIZE

#define GPA_EPT_TABLE_SIZE   4096

Size of the EPT entries hash.

Definition at line 90 of file hook_gpa.h.

Referenced by IntHookGpaEnableDisablePtCache(), IntHookGpaEnableDisableVe(), IntHookGpaFindConvertible(), and IntHookGpaInit().

◆ GPA_HOOK_ID

#define GPA_HOOK_ID (   addr)    (((addr) >> 12) & (GPA_HOOK_TABLE_SIZE - 1))

Definition at line 88 of file hook_gpa.h.

Referenced by IntHandleMemAccess(), IntHookGpaIsPageHooked(), and IntHookGpaSetHook().

◆ GPA_HOOK_TABLE_SIZE

#define GPA_HOOK_TABLE_SIZE   1024

Size of the GPA hook hash.

Definition at line 87 of file hook_gpa.h.

Referenced by IntDbgCheckHooks(), IntHookGpaDump(), IntHookGpaInit(), and IntVeInit().

◆ GPA_REF_COUNT

#define GPA_REF_COUNT (   epte)
Value:
(((QWORD)((epte)->ReadCount) + \
(QWORD)((epte)->WriteCount) + \
((QWORD)(epte)->ExecuteCount) + \
((QWORD)(epte)->PtCount)))
unsigned long long QWORD
Definition: intro_types.h:53

Definition at line 93 of file hook_gpa.h.

Referenced by IntHookGpaSetNewPageProtection().

◆ MAX_HOOK_COUNT

#define MAX_HOOK_COUNT   UINT32_MAX

Total number of hooks supported for each type.

Definition at line 98 of file hook_gpa.h.

Referenced by IntHookGpaEnableDisableVe(), and IntHookGpaSetHook().

Typedef Documentation

◆ HOOK_EPT_ENTRY

Introcore shadow EPT structure. Each guest physical page that is hooked by Introcore will have such an entry associated.

◆ HOOK_GPA

typedef struct _HOOK_GPA HOOK_GPA

Describes one guest physical address hook, for a given access type.

◆ HOOK_GPA_STATE

Global GPA hooks state.

◆ HOOK_HEADER

typedef struct _HOOK_HEADER HOOK_HEADER

Definition at line 10 of file hook_gpa.h.

◆ HOOK_SPP_ENTRY

Describes one sub-page permissions hook entry. Such entries are allocated only for write hooks that span less than a page (4K) in size.

◆ PFUNC_EptViolationCallback

typedef INTSTATUS(* PFUNC_EptViolationCallback) (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)

EPT callback handler.

Such a callback is called whenever an access is made to a hooked memory region. The callback must set the Action argument to the desired action upon return. In order to allow an access, set it to introGuestAllowed. In order to block an attempt, set it to introGuestNotAllowed. In order to retry the instruction, set it to introGuestRetry. Note that if multiple callbacks exist for the same region, each one will return its own action. In this case, actions have a predetermined priority: the least priority is introGuestAllowed, while the highest priority is introGuestRetry. This means that if two callbacks return different actions, the numerically higher action (as given by the enum values) will be considered.

Parameters
[in]ContextUser-supplied context (may contain anything, including NULL).
[in]HookThe hook handle (points to the GPA hook structure).
[in]AddressThe accessed guest physical address.
[out]ActionUpon return, it must contain the action Introcore and the HV must take for the access. Please refer to INTRO_ACTION member fields for more info.

Definition at line 30 of file hook_gpa.h.

◆ PHOOK_EPT_ENTRY

typedef struct _HOOK_EPT_ENTRY * PHOOK_EPT_ENTRY

◆ PHOOK_GPA

typedef struct _HOOK_GPA * PHOOK_GPA

◆ PHOOK_GPA_STATE

typedef struct _HOOK_GPA_STATE * PHOOK_GPA_STATE

◆ PHOOK_SPP_ENTRY

typedef struct _HOOK_SPP_ENTRY * PHOOK_SPP_ENTRY

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().

◆ 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().

◆ 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.

◆ 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().

◆ 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().

◆ 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().

◆ 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().