11 #ifdef INT_COMPILER_MSVC 13 #pragma warning(disable: 4204) // nonstandard extension used: non-constant aggregate initializer 14 #endif // INT_COMPILER_MSVC 39 if (NULL != pEptEntry)
49 if (NULL == pEptEntry)
82 if (NULL != Entry->Spp)
88 if (NULL == Entry->Spp)
94 Entry->Spp->OldSpp = 0;
98 if (Entry->WriteCount == 0)
100 Entry->Spp->CurSpp = 0x5555555555555555;
106 Entry->Spp->CurSpp = 0;
108 for (
DWORD i = 0; i < 32; i++)
110 Entry->Spp->SppCount[i] += Entry->WriteCount;
142 while (pivot != List)
148 pivot = pivot->
Blink;
152 pivot = pivot->
Flink;
182 if (pEptEntry->
GpaPage == GpaPage)
280 if (NULL == Callback)
285 if ((Gpa &
PAGE_MASK) != ((Gpa + Length - 1) & PAGE_MASK))
303 setr = setc = sets =
FALSE;
306 if (NULL == pGpaHook)
324 if (NULL == eptEntry)
327 goto cleanup_and_exit;
338 ERROR(
"[ERROR] IntHookGpaGetSppEntry failed: 0x%08x\n", status);
339 goto cleanup_and_exit;
343 if (NULL != eptEntry->
Spp)
353 for (i = low; i < high; i++)
357 eptEntry->
Spp->
CurSpp &= ~(1ULL << (2 * i));
369 CRITICAL(
"[ERROR] Read hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
371 goto cleanup_and_exit;
379 CRITICAL(
"[ERROR] Write hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
381 goto cleanup_and_exit;
389 CRITICAL(
"[ERROR] Execute hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
391 goto cleanup_and_exit;
405 CRITICAL(
"[ERROR] Page table hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
407 goto cleanup_and_exit;
416 CRITICAL(
"[ERROR] Convertible hook count exceeds the limit for page 0x%016llx!\n", eptEntry->
GpaPage);
418 goto cleanup_and_exit;
428 ERROR(
"[ERROR] IntPtsInt3CacheRemove failed for 0x%016llx and this sucks\n", Gpa);
450 ERROR(
"[ERROR] IntSetEPTPageProtection failed for GPA 0x%016llx: 0x%08x\n", pGpaHook->
GpaPage, status);
451 goto cleanup_and_exit;
460 ERROR(
"[ERROR] IntSetEPTConvertible failed for GPA 0x%016llx: 0x%08x\n", pGpaHook->
GpaPage, status);
461 goto cleanup_and_exit;
471 ERROR(
"[ERROR] IntSetSPPPageProtection failed: 0x%08x\n", status);
472 goto cleanup_and_exit;
481 goto cleanup_and_exit;
509 if (NULL != pGpaHook)
541 setr = setc = sets =
FALSE;
544 if (NULL == eptEntry)
550 switch (Hook->Header.EptHookType)
595 if (NULL != eptEntry->
Spp)
603 high =
ROUND_UP((
DWORD)(Hook->Offset + Hook->Length), 128) >> 7;
605 for (
DWORD i = low; i < high; i++)
609 eptEntry->
Spp->
CurSpp |= (1ULL << (2 * i));
631 ERROR(
"[ERROR] IntSetEPTPageProtection failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
642 ERROR(
"[ERROR] IntSetEPTPageConvertible failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
652 ERROR(
"[ERROR] IntSetSPPPageProtection failed for GPA 0x%016llx: 0x%08x\n", Hook->GpaPage, status);
725 ERROR(
"[ERROR] Invalid hook type %d for hook %p\n", Hook->Header.EptHookType, Hook);
775 ERROR(
"[ERROR] IntHookGpaRemoveHookInternal failed: 0x%08x\n", status);
809 ERROR(
"[ERROR] IntHookGpaSetNewPageProtection failed: 0x%08x\n", status);
866 ERROR(
"[ERROR] IntHookGpaDeleteHookInternal failed: 0x%08x\n", status);
915 while ((queue =
QueueRemove(hooksQueue)) != hooksQueue)
922 ERROR(
"[ERROR] Invalid hook state: %x (chain delete) for hook at GPA 0x%016llx\n",
929 ERROR(
"[ERROR] Invalid hook state: %x for hook at GPA 0x%016llx\n",
939 ERROR(
"[ERROR] IntHookGpaDeleteHookInternal failed: 0x%08x\n", status);
1044 if (NULL == Execute)
1052 *Read = *Write = *Execute = 1;
1054 for (i = 0; i <
ARRAYSIZE(hooksLists); i++)
1056 LIST_HEAD *hooksList = &hooksLists[i][hid];
1058 list = hooksList->
Flink;
1060 while (list != hooksList)
1132 #endif // INT_COMPILER_MSVC 1134 ERROR(
"[ERROR] IntGetCurrentEptIndex failed: 0x%08x. Will assume untrusted EPT index %d.\n",
1163 DWORD i, j, count, count2;
1166 const char *msg[3] = {
"read",
"write",
"execute" };
1173 for (j = 0; j < 3; j++)
1175 NLOG(
"GPA %s hooks:\n", msg[j]);
1194 list = table[i].
Flink;
1198 while (list != &table[i])
1204 NLOG(
"%04d: %p GPA: 0x%016llx, Offset: %04x, Length: %04x, Type: %d, Flags: %08x, Parent: %p," 1205 "Callback: %p, Context: %p, EPT: %c%c%c\n", count++,
1208 r ?
'R' :
'-', w ?
'W' :
'-', x ?
'X' :
'-');
1215 NLOG(
"===> Load of list %04d: %d\n", i, count2);
1221 for (i = 0; i < 3; i++)
1239 queue = hooksQueue->
Next;
1241 NLOG(
"Removed hooks list for '%s':\n", 0 == i ?
"read" : 1 == i ?
"write" :
"execute");
1243 while (queue != hooksQueue)
1247 NLOG(
"%04d: %p GPA: 0x%016llx, Offset: %04x, Length: %04x, Flags: %08x, Parent: %p," 1248 "Callback: %p, Context: %p\n", count++,
1252 queue = queue->
Next;
1301 TRACE(
"[HOOK] Marking GPA %llx as being %s (%c%c%c)\n", gpa, Enable ?
"conv" :
"non-conv",
1308 CRITICAL(
"[ERROR] Convertible hook count exceeds the limit for page 0x%016llx!\n", p->
GpaPage);
1330 ERROR(
"[ERROR] IntSetEPTPageConvertible failed: 0x%08x\n", status);
1385 TRACE(
"[HOOK] Marking GPA %llx as being %s (%c%c%c)\n", gpa, Enable ?
"PT filtered" :
"EPT hooked",
1392 ERROR(
"[ERROR] IntSetEPTPageProtection failed: 0x%08x\n", status);
1478 ERROR(
"[ERROR] Only the Untrusted EPT is supported!\n");
1491 *Read = *Write = *Execute = 1;
1524 LOG(
"!!!! Page 0x%016llx is convertible!\n", p->
GpaPage);
1528 LOG(
"**** Page 0x%016llx is page table, but it is NOT convertible!\n", p->
GpaPage);
1535 #ifdef INT_COMPILER_MSVC 1536 #pragma warning(pop) 1537 #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