11 #ifdef INT_COMPILER_MSVC 13 #pragma warning(disable: 4204) // nonstandard extension used: non-constant aggregate initializer 14 #endif // INT_COMPILER_MSVC 37 if (NULL != pEptEntry)
47 if (NULL == pEptEntry)
80 if (NULL != Entry->Spp)
86 if (NULL == Entry->Spp)
92 Entry->Spp->OldSpp = 0;
96 if (Entry->WriteCount == 0)
98 Entry->Spp->CurSpp = 0x5555555555555555;
104 Entry->Spp->CurSpp = 0;
106 for (
DWORD i = 0; i < 32; i++)
108 Entry->Spp->SppCount[i] += Entry->WriteCount;
140 while (pivot != List)
146 pivot = pivot->
Blink;
150 pivot = pivot->
Flink;
178 if (pEptEntry->
GpaPage == GpaPage)
276 if (NULL == Callback)
281 if ((Gpa &
PAGE_MASK) != ((Gpa + Length - 1) & PAGE_MASK))
299 setr = setc = sets =
FALSE;
302 if (NULL == pGpaHook)
320 if (NULL == eptEntry)
323 goto cleanup_and_exit;
334 ERROR(
"[ERROR] IntHookGpaGetSppEntry failed: 0x%08x\n", status);
335 goto cleanup_and_exit;
339 if (NULL != eptEntry->
Spp)
349 for (i = low; i < high; i++)
353 eptEntry->
Spp->
CurSpp &= ~(1ULL << (2 * i));
365 CRITICAL(
"[ERROR] Read hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
367 goto cleanup_and_exit;
375 CRITICAL(
"[ERROR] Write hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
377 goto cleanup_and_exit;
385 CRITICAL(
"[ERROR] Execute hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
387 goto cleanup_and_exit;
401 CRITICAL(
"[ERROR] Page table hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
403 goto cleanup_and_exit;
412 CRITICAL(
"[ERROR] Convertible hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
414 goto cleanup_and_exit;
424 ERROR(
"[ERROR] IntPtsInt3CacheRemove failed for 0x%016llx and this sucks\n", Gpa);
446 ERROR(
"[ERROR] IntSetEPTPageProtection failed for GPA 0x%016llx: 0x%08x\n", pGpaHook->
GpaPage, status);
447 goto cleanup_and_exit;
456 ERROR(
"[ERROR] IntSetEPTConvertible failed for GPA 0x%016llx: 0x%08x\n", pGpaHook->
GpaPage, status);
457 goto cleanup_and_exit;
467 ERROR(
"[ERROR] IntSetSPPPageProtection failed: 0x%08x\n", status);
468 goto cleanup_and_exit;
477 goto cleanup_and_exit;
505 if (NULL != pGpaHook)
537 setr = setc = sets =
FALSE;
540 if (NULL == eptEntry)
546 switch (Hook->Header.EptHookType)
591 if (NULL != eptEntry->
Spp)
599 high =
ROUND_UP((
DWORD)(Hook->Offset + Hook->Length), 128) >> 7;
601 for (
DWORD i = low; i < high; i++)
605 eptEntry->
Spp->
CurSpp |= (1ULL << (2 * i));
627 ERROR(
"[ERROR] IntSetEPTPageProtection failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
638 ERROR(
"[ERROR] IntSetEPTPageConvertible failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
648 ERROR(
"[ERROR] IntSetSPPPageProtection failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
721 ERROR(
"[ERROR] Invalid hook type %d for hook %p\n", Hook->Header.EptHookType, Hook);
771 ERROR(
"[ERROR] IntHookGpaRemoveHookInternal failed: 0x%08x\n", status);
805 ERROR(
"[ERROR] IntHookGpaSetNewPageProtection failed: 0x%08x\n", status);
862 ERROR(
"[ERROR] IntHookGpaDeleteHookInternal failed: 0x%08x\n", status);
911 while ((queue =
QueueRemove(hooksQueue)) != hooksQueue)
918 ERROR(
"[ERROR] Invalid hook state: %x (chain delete) for hook at GPA 0x%016llx\n",
925 ERROR(
"[ERROR] Invalid hook state: %x for hook at GPA 0x%016llx\n",
935 ERROR(
"[ERROR] IntHookGpaDeleteHookInternal failed: 0x%08x\n", status);
1040 if (NULL == Execute)
1048 *Read = *Write = *Execute = 1;
1050 for (i = 0; i <
ARRAYSIZE(hooksLists); i++)
1052 LIST_HEAD *hooksList = &hooksLists[i][hid];
1054 list = hooksList->
Flink;
1056 while (list != hooksList)
1128 #endif // INT_COMPILER_MSVC 1130 ERROR(
"[ERROR] IntGetCurrentEptIndex failed: 0x%08x. Will assume untrusted EPT index %d.\n",
1159 DWORD i, j, count, count2;
1162 const char *msg[3] = {
"read",
"write",
"execute" };
1169 for (j = 0; j < 3; j++)
1171 NLOG(
"GPA %s hooks:\n", msg[j]);
1190 list = table[i].
Flink;
1194 while (list != &table[i])
1200 NLOG(
"%04d: %p GPA: 0x%016llx, Offset: %04x, Length: %04x, Type: %d, Flags: %08x, Parent: %p," 1201 "Callback: %p, Context: %p, EPT: %c%c%c\n", count++,
1204 r ?
'R' :
'-', w ?
'W' :
'-', x ?
'X' :
'-');
1211 NLOG(
"===> Load of list %04d: %d\n", i, count2);
1217 for (i = 0; i < 3; i++)
1235 queue = hooksQueue->
Next;
1237 NLOG(
"Removed hooks list for '%s':\n", 0 == i ?
"read" : 1 == i ?
"write" :
"execute");
1239 while (queue != hooksQueue)
1243 NLOG(
"%04d: %p GPA: 0x%016llx, Offset: %04x, Length: %04x, Flags: %08x, Parent: %p," 1244 "Callback: %p, Context: %p\n", count++,
1248 queue = queue->
Next;
1297 TRACE(
"[HOOK] Marking GPA %llx as being %s (%c%c%c)\n", gpa, Enable ?
"conv" :
"non-conv",
1304 CRITICAL(
"[ERROR] Convertible hook count exceeds the limit for page 0x%016llx!\n", p->
GpaPage);
1326 ERROR(
"[ERROR] IntSetEPTPageConvertible failed: 0x%08x\n", status);
1381 TRACE(
"[HOOK] Marking GPA %llx as being %s (%c%c%c)\n", gpa, Enable ?
"PT filtered" :
"EPT hooked",
1388 ERROR(
"[ERROR] IntSetEPTPageProtection failed: 0x%08x\n", status);
1474 ERROR(
"[ERROR] Only the Untrusted EPT is supported!\n");
1487 *Read = *Write = *Execute = 1;
1520 LOG(
"!!!! Page 0x%016llx is convertible!\n", p->
GpaPage);
1524 LOG(
"**** Page 0x%016llx is page table, but it is NOT convertible!\n", p->
GpaPage);
1531 #ifdef INT_COMPILER_MSVC 1532 #pragma warning(pop) 1533 #endif // INT_COMPILER_MSVC
HOOK_SPP_ENTRY * Spp
SPP entry. Allocated only for write hooks that are less than a page in size.
#define CONTAINING_RECORD(List, Type, Member)
#define ROUND_UP(what, to)
#define MAX_HOOK_COUNT
Total number of hooks supported for each type.
#define GPA_REF_COUNT(epte)
#define GPA_HOOK_TABLE_SIZE
Size of the GPA hook hash.
HOOK_HEADER Header
Hook header.
DWORD ReadCount
Number of read EPT hooks.
QUEUE_HEAD RemovedHooksExecute
List of removed execute hooks.
BOOLEAN Dirty
Set whenever hooks are added or removed.
void * Context
User-defined data that will be supplied to the callback.
INTSTATUS IntHookGpaEnablePtCache(void)
Enable PT filtering.
INTSTATUS IntGetEPTPageConvertible(DWORD EptIndex, QWORD Address, BOOLEAN *Convertible)
LIST_HEAD GpaHooksWrite[GPA_HOOK_TABLE_SIZE]
Hash table of write hooks.
#define GPA_HOOK_ID(addr)
#define INT_STATUS_SUCCESS
INTSTATUS IntPtiCacheRemove(QWORD Gpa)
Remove a guest physical page from the PT filter cache.
#define IntEnterDebugger()
struct _LIST_ENTRY * Flink
void QueueInsert(QUEUE_HEAD *QueueHead, QUEUE_ENTRY *Element)
#define INT_SUCCESS(Status)
#define HOOK_FLG_DISABLED
If flag is set, the hook is disabled, therefore ignored on EPT violations.
DWORD WriteCount
Number of write EPT hooks.
BYTE EptHookType
The type of the hook in EPT (see IG_EPT_HOOK_TYPE)
#define INT_STATUS_NOT_NEEDED_HINT
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
static INTSTATUS IntHookGpaDeleteHookInternal(HOOK_GPA *Hook, DWORD Flags)
Permanently delete a GPA hook.
void QueueInitialize(QUEUE_HEAD *QueueHead)
HOOK_STATE * gHooks
Global hooks state.
INTSTATUS IntHookGpaRemoveHook(HOOK_GPA **Hook, DWORD Flags)
Remove a GPA hook.
INTSTATUS IntHookGpaEnableVe(void)
Enable VE filtering.
INTSTATUS IntHookGpaCommitHooks(void)
Commit existing modified hooks.
#define HOOK_FLG_HIGH_PRIORITY
If flag is set, the callback associated to this hook will have a higher priority than the others...
INTSTATUS IntSetEPTPageProtection(DWORD EptIndex, QWORD Gpa, BYTE Read, BYTE Write, BYTE Execute)
BYTE HookType
The type of the hook structure (see _HOOK_TYPE)
static INTSTATUS IntEnableEptNotifications(void)
static INTSTATUS IntHookGpaEnableDisablePtCache(BOOLEAN Enable)
Enable or disable the in guest PT filtering mechanism.
QUEUE_HEAD RemovedHooksWrite
List of removed write hooks.
INTSTATUS IntHookGpaIsPageHooked(QWORD Gpa, BYTE *Read, BYTE *Write, BYTE *Execute)
Get the read, write and execute access for the given guest physical page.
LIST_HEAD GpaHooksRead[GPA_HOOK_TABLE_SIZE]
Hash table of read hooks.
static INTSTATUS IntDisableEptNotifications(void)
BOOLEAN SupportSPP
Set to True if support for SPP was detected.
#define HOOK_FLG_GLOBAL_MASK
Global flags must be defined here and must be handled by each hooks layer (even if it ignores them...
DWORD SppCount[32]
Number of write hooks placed on each 128 bytes region within the page.
#define INT_STATUS_ALREADY_INITIALIZED
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
INTSTATUS IntHookGpaDisableHook(HOOK_GPA *Hook)
Disable a GPA hook.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
static INTSTATUS IntHookGpaRemoveHookInternal(HOOK_GPA *Hook, DWORD Flags)
Remove a GPA hook.
PHOOK_EPT_ENTRY IntHookGpaGetEptEntry(QWORD GpaPage)
Get the EPT entry associated with a physical page.
void * ParentHook
The parent hook. For a GPA hook, for example, a GVA hook or a PagedHook will be the parent hook...
#define HOOK_FLG_CHAIN_DELETE
If flag is set, then we won't remove the hook on commit phase; we'll let the parent hook handle the d...
WORD Offset
The offset within the page where the hook starts. 0-4095 valid.
QWORD GpaPage
The page where the hook is set.
#define INT_STATUS_INVALID_PARAMETER_4
QWORD CurSpp
Current SPP permissions.
#define INVALID_EPTP_INDEX
#define HpFreeAndNullWithTag(Add, Tag)
QWORD GpaPage
Guest physical page address.
static void InsertAfterList(LIST_ENTRY *Pivot, LIST_ENTRY *Item)
INTSTATUS IntHookGpaGetEPTPageProtection(DWORD EptIndex, QWORD Address, BYTE *Read, BYTE *Write, BYTE *Execute)
Get the EPT page protection for the indicated guest physical address.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
QUEUE_HEAD RemovedHooksRead
List of removed read hooks.
#define INT_STATUS_ALREADY_INITIALIZED_HINT
#define ROUND_DOWN(what, to)
HOOK_GPA_STATE GpaHooks
GPA hooks state.
LIST_HEAD EptEntries[GPA_EPT_TABLE_SIZE]
Hash table containing the EPT entries elements (HOOK_EPT_ENTRY).
static void InitializeListHead(LIST_ENTRY *ListHead)
static INTSTATUS IntHookGpaSetNewPageProtection(HOOK_GPA *Hook)
Update EPT protection for a removed hook.
#define UNREFERENCED_PARAMETER(P)
PHOOK_EPT_ENTRY IntHookGpaGetExistingEptEntry(QWORD GpaPage)
Get the EPT entry associated with the provided guest physical page.
INT64 HooksCount
Total number of hooks set.
static void IntHookGpaInsertHookInList(LIST_ENTRY *List, HOOK_GPA *Hook)
Insert the hook in the given list of hooks.
INTSTATUS IntHookGpaDisableVe(void)
Disable VE filtering.
void IntHookGpaDump(void)
Dump the entire contents of the GPA hook system, listing each hook.
DWORD ProtectedEptIndex
The EPTP index of the trusted EPT.
BOOLEAN SppEnabled
True if SPP support is present and enabled.
DWORD PtCount
Number of PT hooks.
WORD Length
The length, in bytes, of the hook. 1-4096 valid.
INTSTATUS IntGetEPTPageProtection(DWORD EptIndex, QWORD Gpa, BYTE *Read, BYTE *Write, BYTE *Execute)
#define IntDbgEnterDebugger()
LIST_ENTRY Link
List entry element.
#define INT_STATUS_ARITHMETIC_OVERFLOW
INTSTATUS IntHookGpaDisablePtCache(void)
Disable PT filtering.
INTSTATUS(* PFUNC_EptViolationCallback)(void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
EPT callback handler.
static INTSTATUS IntHookGpaGetSppEntry(HOOK_EPT_ENTRY *Entry)
Allocates a SPP entry for the given EPT hook.
GUEST_STATE gGuest
The current guest state.
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.
BOOLEAN VeEnabled
True if VE filtering is enabled.
LIST_HEAD GpaHooksExecute[GPA_HOOK_TABLE_SIZE]
Hash table of execute hooks.
INTSTATUS IntHookGpaInit(void)
Initialize the GPA hook system. This function should be called only once, during introspection init...
BOOLEAN PtCacheEnabled
True if the PT cache is active inside the guest.
#define GPA_EPT_TABLE_SIZE
Size of the EPT entries hash.
INTSTATUS IntHookGpaDeleteHook(HOOK_GPA **Hook, DWORD Flags)
Permanently delete a GPA hook.
DWORD ExecuteCount
Number of execute EPT hooks.
INTSTATUS IntHookGpaEnableHook(HOOK_GPA *Hook)
Enable a GPA hook.
PFUNC_EptViolationCallback Callback
The callback for this hook.
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
struct _LIST_ENTRY * Blink
static INTSTATUS IntHookGpaEnableDisableVe(BOOLEAN Enable)
Enable or disable the VE filtering mechanism.
INTSTATUS IntHookGpaFindConvertible(void)
Displays all convertible pages.
QUEUE_ENTRY * QueueRemove(QUEUE_HEAD *QueueHead)
#define CRITICAL(fmt,...)
INTSTATUS IntGetCurrentEptIndex(DWORD CpuNumber, DWORD *EptpIndex)
Get the EPTP index of the currently loaded EPT.
DWORD Flags
Generic flags. Check out EPT Hook flags.
BOOLEAN HooksRemoved
True if hooks were removed, and we must do the cleanup..
#define HOOK_PAGE_TABLE_FLAGS
Any of these flags set indicates that we are dealing with a page table page.
BOOLEAN GlueIsSppApiAvailable(void)
Checks if the SPP APIs in GLUE_IFACE are implemented.
DWORD UntrustedEptIndex
The EPTP index of the untrusted EPT.
#define INT_STATUS_INVALID_PARAMETER_2
INTSTATUS IntSetEPTPageConvertible(DWORD EptIndex, QWORD Address, BOOLEAN Convertible)
INTSTATUS IntSetSPPPageProtection(QWORD Gpa, QWORD Spp)
#define HOOK_FLG_REMOVE
If flag is set, the hook has been removed, and waits the next commit to be actually deleted...
#define INT_STATUS_INSUFFICIENT_RESOURCES
#define INT_STATUS_INVALID_PARAMETER_3