Bitdefender Hypervisor Memory Introspection
winselfmap.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winselfmap.h"
6 #include "alerts.h"
7 #include "hook.h"
8 
10 
11 
12 __forceinline static void
14  _In_ QWORD ModifiedCr3,
15  _Inout_ WIN_PROCESS_OBJECT *Process,
16  _In_ QWORD NewValue
17  )
28 {
29  if (Process->Cr3 == ModifiedCr3)
30  {
31  Process->SelfMapEntryValue = NewValue;
32  }
33  else
34  {
35  Process->UserSelfMapEntryValue = NewValue;
36  }
37 }
38 
39 
40 static INTSTATUS
42  _In_ QWORD NewValue,
43  _In_ QWORD OldValue,
44  _Inout_ WIN_PROCESS_OBJECT *Process,
45  _In_ QWORD Cr3
46  )
57 {
58  INTSTATUS status;
59  INTRO_ACTION action;
60  INTRO_ACTION_REASON reason;
62 
63  action = introGuestNotAllowed;
64  reason = introReasonNoException;
65 
66  memzero(pTr, sizeof(*pTr));
67 
68  WARNING("[WARNING] Self-mapping entry modified for process '%s' with CR3 %llx (%s), addr %llx, "
69  "from 0x%016llx to 0x%016llx\n", Process->Name, Cr3, Cr3 == Process->Cr3 ? "kernel" : "user",
70  SELF_MAP_ENTRY(Cr3), OldValue, NewValue);
71 
73  {
74  LOG("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (B) ROOTKIT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n");
75  }
76  else
77  {
78  LOG("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ROOTKIT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n");
79 
80  QWORD *pPage = NULL;
81 
82  status = IntPhysMemMap(SELF_MAP_ENTRY(Cr3), sizeof(QWORD), 0, &pPage);
83  if (!INT_SUCCESS(status))
84  {
85  ERROR("[ERROR] IntPhysMemMap failed: 0x%08x\n", status);
86  goto _just_send_alert;
87  }
88 
89  // restore only the US bit in case of modification
90  pPage[0] = NewValue & (~PT_US);
91 
92  IntPhysMemUnmap(&pPage);
93  }
94 
95  // We always update the selfmap with the new value
96  IntWinSelfMapSelfMapUpdate(Cr3, Process, NewValue);
97 
98 _just_send_alert:
100  {
101  pTr->Header.Action = action;
102  pTr->Header.Reason = reason;
103  pTr->Header.MitreID = idRootkit;
104 
106 
107  if (Process->SystemProcess)
108  {
110  }
111 
113 
115 
117 
118  pTr->WriteInfo.NewValue[0] = NewValue;
119  pTr->WriteInfo.OldValue[0] = OldValue;
120  pTr->WriteInfo.Size = sizeof(QWORD);
121 
122  pTr->Originator.Module.Valid = FALSE;
123  pTr->Header.CpuContext.Valid = FALSE;
125 
128 
129  status = IntNotifyIntroEvent(introEventTranslationViolation, pTr, sizeof(*pTr));
130  if (!INT_SUCCESS(status))
131  {
132  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
133  }
134  }
135 
136  return INT_STATUS_SUCCESS;
137 }
138 
139 
140 static INTSTATUS
142  _Inout_ WIN_PROCESS_OBJECT *Process,
143  _In_opt_ const QWORD *CurrentKernelValue,
144  _In_opt_ const QWORD *CurrentUserValue
145  )
165 {
166  QWORD currentKern, currentUser;
167  INTSTATUS status = INT_STATUS_SUCCESS;
168 
169  if (Process->Outswapped)
170  {
172  }
173 
174  if (NULL == CurrentKernelValue)
175  {
176  status = IntPhysicalMemRead(SELF_MAP_ENTRY(Process->Cr3), sizeof(QWORD), &currentKern, NULL);
177  if (!INT_SUCCESS(status))
178  {
179  ERROR("[ERROR] IntPhysicalMemRead failed: 0x%08x\n", status);
180  goto _exit;
181  }
182  }
183  else
184  {
185  currentKern = *CurrentKernelValue;
186  }
187 
188  if (NULL == CurrentUserValue && Process->Cr3 != Process->UserCr3)
189  {
190  status = IntPhysicalMemRead(SELF_MAP_ENTRY(Process->UserCr3), sizeof(QWORD), &currentUser, NULL);
191  if (!INT_SUCCESS(status))
192  {
193  ERROR("[ERROR] IntPhysicalMemRead failed: 0x%08x\n", status);
194  goto _exit;
195  }
196  }
197  else if (Process->Cr3 != Process->UserCr3)
198  {
199  currentUser = *CurrentUserValue;
200  }
201  else
202  {
203  goto _only_kern_check;
204  }
205 
206  // When in beta, we should also verify that our stored value didn't have the U/S bit as on kernel beta detections
207  // we only want to give an alert when this bit was modified vs. what we have stored instead of sending an alert
208  // every time we check, but if KernelBetaDetections was changed on the fly we should also consider a detection
209  // even if our previously stored value had U/S bit activated.
210  if (Process->Cr3 != Process->UserCr3)
211  {
212  if (SELF_MAP_ENTRY_IS_DETECTION(currentUser) &&
213  ((Process->UserSelfMapEntryValue & PT_US) != (currentUser & PT_US) || !gGuest.KernelBetaDetections))
214  {
215  status = IntWinSelfMapHandleCr3SelfMapModification(currentUser, Process->UserSelfMapEntryValue, Process,
216  Process->UserCr3);
217  if (!INT_SUCCESS(status))
218  {
219  ERROR("[ERROR] IntWinSelfMapCr3SelfMapModification failed: 0x%x\n", status);
220  }
221  }
222  else if (Process->UserSelfMapEntryValue != currentUser)
223  {
224  Process->UserSelfMapEntryValue = currentUser;
225  }
226  }
227 
228 _only_kern_check:
229  if (SELF_MAP_ENTRY_IS_DETECTION(currentKern) &&
230  ((Process->SelfMapEntryValue & PT_US) != (currentKern & PT_US) || !gGuest.KernelBetaDetections))
231  {
232  status = IntWinSelfMapHandleCr3SelfMapModification(currentKern,
233  Process->SelfMapEntryValue,
234  Process,
235  Process->Cr3);
236  if (!INT_SUCCESS(status))
237  {
238  ERROR("[ERROR] IntWinSelfMapCr3SelfMapModification failed: 0x%x\n", status);
239  }
240  }
241  else if (Process->SelfMapEntryValue != currentKern)
242  {
243  Process->SelfMapEntryValue = currentKern;
244  }
245 
246 _exit:
247  return status;
248 }
249 
250 
251 static INTSTATUS
253  _Inout_ WIN_PROCESS_OBJECT *Context,
254  _In_ void *Hook,
255  _In_ QWORD Address,
256  _Out_ INTRO_ACTION *Action
257  )
276 {
277  WIN_PROCESS_OBJECT *pProc = Context;
278  INTSTATUS status;
279  EXCEPTION_KM_ORIGINATOR originator = { 0 };
280  EXCEPTION_VICTIM_ZONE victim = { 0 };
281  IG_ARCH_REGS *regs;
282  INTRO_ACTION action;
283  INTRO_ACTION_REASON reason;
284  QWORD gva;
285  QWORD cr3Modified;
286  BOOLEAN isBeta;
287 
288  regs = &gVcpu->Regs;
289  action = introGuestNotAllowed;
290  reason = introReasonNoException;
292 
293  cr3Modified = CLEAN_PHYS_ADDRESS64(pProc->Cr3) == CLEAN_PHYS_ADDRESS64(Address) ? pProc->Cr3 : pProc->UserCr3;
294 
295  if (!gVcpu->PtEmuBuffer.Valid)
296  {
297  action = introGuestAllowed;
298  reason = introReasonAllowed;
299  goto cleanup_and_exit;
300  }
301 
302  // KPTI is enabled and relevant only for non-privileged processes. Processes which are already privileged
303  // (running as system/admin/etc.), do start with both the kernel and user CR3 allocated & initialized, but soon
304  // after the process is created, the user CR3 will be freed. The self-map mechanism will keep the protection on
305  // that user CR3. Eliminate the self-map protection on user CR3 once they are removed; we can figure out that a
306  // user CR3 is deleted when the self-map entry for tit is made invalid (present bit == 0).
307  if (!!(gVcpu->PtEmuBuffer.Old & PT_P) &&
308  !(gVcpu->PtEmuBuffer.New & PT_P))
309  {
310  action = introGuestAllowed;
311  reason = introReasonAllowed;
312 
313  if (Hook == pProc->SelfMapHook)
314  {
315  pProc->SelfMapHook = NULL;
316  }
317  else if (Hook == pProc->UserSelfMapHook)
318  {
319  pProc->UserSelfMapHook = NULL;
320  }
321 
322  status = IntHookGpaRemoveHook((HOOK_GPA **)&Hook, 0);
323  if (!INT_SUCCESS(status))
324  {
325  ERROR("[ERROR] IntHookGpaRemoveHook failed: 0x%08x\n", status);
326  }
327 
328  return INT_STATUS_SUCCESS;
329  }
330 
331  if (gVcpu->PtEmuBuffer.Old == 0 ||
333  {
334  action = introGuestAllowed;
335  reason = introReasonAllowed;
336 
337  IntWinSelfMapSelfMapUpdate(cr3Modified, pProc, gVcpu->PtEmuBuffer.New);
338 
339  goto cleanup_and_exit;
340  }
341 
343 
344  status = IntExceptKernelGetOriginator(&originator, 0);
345  if (!INT_SUCCESS(status))
346  {
347  WARNING("[WARNING] IntExceptKernelGetOriginator failed: 0x%08x\n", status);
348  }
349 
350  gva = SELF_MAP_ENTRY_VA;
351 
352  status = IntExceptGetVictimEpt(Context, Address, gva, introObjectTypeSelfMapEntry, ZONE_WRITE, &victim);
353 
354  if (!INT_SUCCESS(status))
355  {
356  reason = introReasonInternalError;
357  ERROR("[ERROR] Failed getting zone details: 0x%08x\n", status);
358  goto _exit_exceptions;
359  }
360 
361  // overwrite with these values
362  victim.WriteInfo.NewValue[0] = gVcpu->PtEmuBuffer.New;
363  victim.WriteInfo.OldValue[0] = gVcpu->PtEmuBuffer.Old;
364  victim.WriteInfo.AccessSize = sizeof(QWORD);
365 
366  IntExcept(&victim, &originator, exceptionTypeKm, &action, &reason, introEventEptViolation);
367 
368 _exit_exceptions:
370 
372  {
373  EVENT_EPT_VIOLATION *pEpt = &gAlert.Ept;
374 
375  memzero(pEpt, sizeof(*pEpt));
376 
377  WARNING("[WARNING] Self-mapping entry modified for process '%s' with CR3 %llx (%s), "
378  "addr %llx, from 0x%016llx to 0x%016llx from RIP 0x%016llx\n",
379  pProc->Name,
380  cr3Modified,
381  cr3Modified == pProc->Cr3 ? "kernel" : "user",
382  Address,
385  regs->Rip);
386 
387  if (!isBeta)
388  {
389  QWORD *pPage = NULL;
390 
391  status = IntPhysMemMap(Address, sizeof(QWORD), 0, &pPage);
392  if (!INT_SUCCESS(status))
393  {
394  ERROR("[ERROR] IntPhysMemMap failed: 0x%08x\n", status);
395  goto just_send_alert;
396  }
397 
398  gVcpu->PtEmuBuffer.New &= (~PT_US);
399 
400  pPage[0] = gVcpu->PtEmuBuffer.New;
401 
402  IntPhysMemUnmap(&pPage);
403 
404  IntWinSelfMapSelfMapUpdate(cr3Modified, pProc, gVcpu->PtEmuBuffer.New);
405  }
406 
407 just_send_alert:
408  pEpt->Header.Action = action;
409  pEpt->Header.Reason = reason;
410  pEpt->Header.MitreID = idRootkit;
411 
413 
414  IntAlertEptFillFromKmOriginator(&originator, pEpt);
415  IntAlertEptFillFromVictimZone(&victim, pEpt);
416 
418 
419  if (pProc->SystemProcess)
420  {
422  }
423 
425 
426  IntAlertFillCodeBlocks(originator.Original.Rip, regs->Cr3, FALSE, &pEpt->CodeBlocks);
427  IntAlertFillExecContext(regs->Cr3, &pEpt->ExecContext);
428 
430 
431  status = IntNotifyIntroEvent(introEventEptViolation, pEpt, sizeof(*pEpt));
432  if (!INT_SUCCESS(status))
433  {
434  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
435  }
436  }
437 
438 cleanup_and_exit:
439  if (isBeta || action == introGuestAllowed)
440  {
441  IntWinSelfMapSelfMapUpdate(cr3Modified, pProc, gVcpu->PtEmuBuffer.New);
442  }
443 
445 
446  *Action = action;
447 
448  return INT_STATUS_SUCCESS;
449 }
450 
451 
454  void
455  )
471 {
472  LIST_ENTRY *pList = NULL;
473 
475  {
477  }
478 
480  {
482  }
483 
484  if ((introGuestWindows != gGuest.OSType) ||
488  {
490  }
491 
493 
494  pList = gWinProcesses.Flink;
495  while (pList != &gWinProcesses)
496  {
497  WIN_PROCESS_OBJECT *pProcess = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
498  INTSTATUS status;
499 
500  pList = pList->Flink;
501 
502  status = IntWinSelfMapCheckSelfMapEntry(pProcess, NULL, NULL);
503  if (!INT_SUCCESS(status))
504  {
505  ERROR("[ERROR] IntWinCheckSelfMapEntry failed: 0x%08x\n", status);
506  }
507  }
508 
510 
511  return INT_STATUS_SUCCESS;
512 }
513 
514 
515 INTSTATUS
517  void
518  )
530 {
531  PLIST_ENTRY pList = NULL;
532 
534  {
536  }
537 
539  {
541  }
542 
543  if ((introGuestWindows != gGuest.OSType) ||
546  {
548  }
549 
550  pList = gWinProcesses.Flink;
551  while (pList != &gWinProcesses)
552  {
553  WIN_PROCESS_OBJECT *pProcess = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
554  INTSTATUS status;
555 
556  pList = pList->Flink;
557 
558  status = IntWinSelfMapCheckSelfMapEntry(pProcess, NULL, NULL);
559 
560  // no point in protecting the process if it already has a hook on it...
561  if (pProcess->SelfMapHook != NULL && pProcess->UserSelfMapHook != NULL)
562  {
563  continue;
564  }
565 
566  status = IntWinSelfMapProtectSelfMapIndex(pProcess);
567  if (!INT_SUCCESS(status))
568  {
569  ERROR("[ERROR] IntWinProtectSelfMapIndex failed: 0x%08x\n", status);
570  continue;
571  }
572  }
573 
574  return INT_STATUS_SUCCESS;
575 }
576 
577 
578 INTSTATUS
580  _Inout_ WIN_PROCESS_OBJECT *Process
581  )
599 {
600  INTSTATUS status;
601  QWORD currentKern, currentUser;
602 
603  if (NULL == Process)
604  {
606  }
607 
609  {
611  }
612 
614  {
616  }
617 
618  if ((introGuestWindows != gGuest.OSType) ||
621  {
623  }
624 
625  status = IntPhysicalMemRead(SELF_MAP_ENTRY(Process->Cr3), sizeof(QWORD), &currentKern, NULL);
626  if (!INT_SUCCESS(status))
627  {
628  ERROR("[ERROR] IntPhysicalMemRead failed: 0x%08x\n", status);
629  goto _exit;
630  }
631 
632  // assume current self map entry value has U/S bit deactivated, as we should give a detection on integrity checking
633  Process->SelfMapEntryValue = (currentKern & (~PT_US));
634 
635  status = IntPhysicalMemRead(SELF_MAP_ENTRY(Process->UserCr3), sizeof(QWORD), &currentUser, NULL);
636  if (!INT_SUCCESS(status))
637  {
638  ERROR("[ERROR] IntPhysicalMemRead failed: 0x%08x\n", status);
639  goto _exit;
640  }
641 
642  // assume current self map entry value has U/S bit deactivated, as we should give a detection on integrity checking
643  Process->UserSelfMapEntryValue = (currentUser & (~PT_US));
644 
646  {
647  status = IntWinSelfMapCheckSelfMapEntry(Process, &currentKern, &currentUser);
648  }
649 
650 _exit:
651  return status;
652 }
653 
654 
655 INTSTATUS
657  void
658  )
669 {
670  LIST_ENTRY *pList = NULL;
671 
673  {
675  }
676 
678  {
680  }
681 
682  if ((introGuestWindows != gGuest.OSType) ||
685  {
687  }
688 
689  pList = gWinProcesses.Flink;
690  while (pList != &gWinProcesses)
691  {
692  WIN_PROCESS_OBJECT *pProcess = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
693  INTSTATUS status;
694 
695  pList = pList->Flink;
696 
697  status = IntWinSelfMapUnprotectSelfMapIndex(pProcess);
698  if (!INT_SUCCESS(status))
699  {
700  ERROR("[ERROR] IntWinSelfMapUnprotectSelfMapIndex failed: 0x%08x\n", status);
701  continue;
702  }
703  }
704 
705  return INT_STATUS_SUCCESS;
706 }
707 
708 
709 INTSTATUS
711  _Inout_ WIN_PROCESS_OBJECT *Process
712  )
732 {
733 
734  INTSTATUS status = INT_STATUS_SUCCESS;
735  BOOLEAN bShouldProtect = FALSE;
736 
737  if (NULL == Process)
738  {
740  }
741 
742  if ((introGuestWindows != gGuest.OSType) ||
746  {
748  }
749 
750  // Force only integrity mechanism to kick-in: as we have seen, processes might be "swapped-out"
751  // (see MmSwapOutProcess) - when a process is then swapped in (see MmSwapInProcess), it verifies OutSwapped
752  // flag in EPROCESS.Flags, and if it is set, it copies the whole upper entries (>0x800) from the current process
753  // kernel PML4 into the upper entries of the swapped in process PML4, using memmove, case in which some MOVDQA
754  // instructions come on kernel page tables (because this is the only hook we put on kernel page tables on
755  // protected processes). So, until we find a better solution, keep only the integrity check.
756  bShouldProtect = Process->Pid == 4;
757 
758  TRACE("[INFO] Protecting self-mapping entry for process %s, pid %d with CR3: %llx, UserCR3: %llx with %s\n",
759  Process->Name, Process->Pid, Process->Cr3, Process->UserCr3, bShouldProtect ? "EPT" : "INTEGRITY");
760 
761  if (bShouldProtect)
762  {
763  if (Process->SelfMapHook == NULL)
764  {
765  status = IntHookGpaSetHook(SELF_MAP_ENTRY(Process->Cr3),
766  sizeof(QWORD),
769  Process,
770  NULL,
772  (PHOOK_GPA *)&Process->SelfMapHook);
773  if (!INT_SUCCESS(status))
774  {
775  ERROR("[ERROR] IntHookGpaSetHook failed: 0x%08x\n", status);
776  }
777  }
778 
779  // Avoid double hooking
780  if (Process->Cr3 != Process->UserCr3 && Process->UserSelfMapHook == NULL)
781  {
782  status = IntHookGpaSetHook(SELF_MAP_ENTRY(Process->UserCr3),
783  sizeof(QWORD),
786  Process,
787  NULL,
789  (PHOOK_GPA *)&Process->UserSelfMapHook);
790  if (!INT_SUCCESS(status))
791  {
792  ERROR("[ERROR] IntHookGpaSetHook failed: 0x%08x\n", status);
793  }
794  }
795  }
796 
797  return status;
798 }
799 
800 
801 INTSTATUS
803  _Inout_ WIN_PROCESS_OBJECT *Process
804  )
815 {
816  INTSTATUS status = INT_STATUS_SUCCESS;
817 
818  if (Process == NULL)
819  {
821  }
822 
823  TRACE("[INFO] Deactivating self-map index protection for %s (pid %d, cr3: kernel %016llx, user: %016llx)\n",
824  Process->Name, Process->Pid, Process->Cr3, Process->UserCr3);
825 
826  if (Process->SelfMapHook != NULL)
827  {
828  status = IntHookGpaRemoveHook((HOOK_GPA **)&Process->SelfMapHook, 0);
829  if (!INT_SUCCESS(status))
830  {
831  ERROR("[ERROR] IntHookGpaRemoveHook failed: 0x%08x\n", status);
832  }
833  }
834 
835  if (Process->UserSelfMapHook != NULL)
836  {
837  status = IntHookGpaRemoveHook((HOOK_GPA **)&Process->UserSelfMapHook, 0);
838  if (!INT_SUCCESS(status))
839  {
840  ERROR("[ERROR] IntHookGpaRemoveHook failed: 0x%08x\n", status);
841  }
842  }
843 
844  return status;
845 }
Measures kernel mode exceptions checks.
Definition: stats.h:51
#define _In_opt_
Definition: intro_sal.h:16
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
INTRO_CODEBLOCKS CodeBlocks
Code blocks extracted for the alert.
Definition: intro_types.h:1263
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:904
QWORD IntAlertCoreGetFlags(QWORD ProtectionFlag, INTRO_ACTION_REASON Reason)
Returns the flags for an alert.
Definition: alerts.c:366
DWORD Size
The size of the access.
Definition: intro_types.h:982
static INTSTATUS IntWinSelfMapHandleCr3SelfMapWrite(WIN_PROCESS_OBJECT *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
Handles writes done to the self map entry inside a process page tables.
Definition: winselfmap.c:252
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
INTSTATUS IntPhysicalMemRead(QWORD PhysicalAddress, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest physical memory range, but only for a single page.
Definition: introcore.c:721
BOOLEAN IntPolicyCoreForceBetaIfNeeded(QWORD Flag, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the log-only mode is active.
Definition: introcore.c:2803
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
INTSTATUS IntHookGpaRemoveHook(HOOK_GPA **Hook, DWORD Flags)
Remove a GPA hook.
Definition: hook_gpa.c:738
#define CLEAN_PHYS_ADDRESS64(x)
Definition: pgtable.h:119
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
BOOLEAN IntPolicyCoreTakeAction(QWORD Flag, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a core introspection option.
Definition: introcore.c:2693
QWORD NewValue[8]
The written value. Only the first Size bytes are valid.
Definition: intro_types.h:981
#define STATS_EXIT(id)
Definition: stats.h:160
struct _LIST_ENTRY * Flink
Definition: introlists.h:20
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
BOOLEAN ProtectionActivated
Definition: guests.h:297
The action was not allowed because there was no reason to allow it.
Definition: intro_types.h:183
BOOLEAN KernelBetaDetections
True if the kernel protection is in beta (log-only) mode.
Definition: guests.h:303
#define PT_US
Definition: pgtable.h:85
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1542
struct _EVENT_TRANSLATION_VIOLATION::@301 Victim
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:675
INTSTATUS IntWinSelfMapEnableSelfMapEntryProtection(void)
Enables the self map protection mechanism for the entire system.
Definition: winselfmap.c:516
int INTSTATUS
The status data type.
Definition: introstatus.h:24
TIMER_FRIENDLY INTSTATUS IntWinSelfMapValidateSelfMapEntries(void)
Validates the self map entries for every process in the system.
Definition: winselfmap.c:453
LIST_HEAD gWinProcesses
The list of all the processes inside the guest.
Definition: winprocesshp.c:11
QWORD VirtualAddress
The Virtual Address whose translation is being modified.
Definition: intro_types.h:1552
Event structure for illegal paging-structures modifications.
Definition: intro_types.h:1540
void * UserSelfMapHook
The user self mapping memory hook.
Definition: winprocess.h:260
Rootkit.
Definition: intro_types.h:1144
Describes a kernel-mode originator.
Definition: exceptions.h:943
EVENT_TRANSLATION_VIOLATION Translation
Definition: alerts.h:22
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
EVENT_EPT_VIOLATION Ept
Definition: alerts.h:16
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.
Definition: hook_gpa.c:193
#define LOG(fmt,...)
Definition: glue.h:61
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
#define INTRO_OPT_PROT_KM_SELF_MAP_ENTRY
Definition: intro_types.h:438
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1217
BOOLEAN IntPolicyCoreIsOptionBeta(QWORD Flag)
Checks if one of the kernel protection options is in log-only mode.
Definition: introcore.c:2603
#define HOOK_FLG_HIGH_PRIORITY
If flag is set, the callback associated to this hook will have a higher priority than the others...
Definition: hook.h:54
TRANS_VIOLATION_TYPE ViolationType
Definition: intro_types.h:1562
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
#define HOOK_FLG_PAGING_STRUCTURE
If flag is set, the hook is set on paging structures.
Definition: hook.h:49
INTSTATUS IntAlertFillCodeBlocks(QWORD Rip, QWORD Cr3, BOOLEAN Execute, INTRO_CODEBLOCKS *CodeBlocks)
Fills the code blocks pattern for an alert.
Definition: alerts.c:71
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
void IntAlertEptFillFromKmOriginator(const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills kernel mode originator information inside an EPT alert.
Definition: alerts.c:832
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define _Inout_
Definition: intro_sal.h:20
5-level paging
Definition: introcore.h:72
void IntAlertEptFillFromVictimZone(const EXCEPTION_VICTIM_ZONE *Victim, EVENT_EPT_VIOLATION *EptViolation)
Fills the victim information inside an EPT alert.
Definition: alerts.c:868
#define STATS_ENTER(id)
Definition: stats.h:153
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1196
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
QWORD New
The new, to be written, value of the page table entry.
Definition: guests.h:52
#define memzero(a, s)
Definition: introcrt.h:35
#define PT_P
Definition: pgtable.h:83
INTSTATUS IntExceptGetVictimEpt(void *Context, QWORD Gpa, QWORD Gva, INTRO_OBJECT_TYPE Type, DWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
Fills an EXCEPTION_VICTIM_ZONE with relevant information from an EPT violation.
Definition: exceptions.c:742
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
QWORD Current
The currently used options.
Definition: guests.h:236
QWORD Old
The old, original, value of the written page table entry.
Definition: guests.h:51
QWORD UserCr3
Process user PDBR. Includes PCID.
Definition: winprocess.h:99
INTSTATUS IntWinSelfMapProtectSelfMapIndex(WIN_PROCESS_OBJECT *Process)
Protects the self map index of a process by placing an EPT write hook on it.
Definition: winselfmap.c:710
#define TRUE
Definition: intro_types.h:30
INTRO_WRITE_INFO WriteInfo
The original and new address to which VirtualAddress translates.
Definition: intro_types.h:1560
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
Definition: guests.h:293
#define TRACE(fmt,...)
Definition: glue.h:58
#define SELF_MAP_ENTRY(Cr3)
Computes the self map entry physical address based on a given Cr3.
Definition: winselfmap.h:21
INTSTATUS IntWinSelfMapUnprotectSelfMapIndex(WIN_PROCESS_OBJECT *Process)
Removes the EPT protection for the self map entry index of a process.
Definition: winselfmap.c:802
Sent for virtual address translation alerts. See EVENT_TRANSLATION_VIOLATION.
Definition: intro_types.h:94
#define TIMER_FRIENDLY
Definition: introdefs.h:83
#define SELF_MAP_ENTRY_IS_DETECTION(entry)
Decides if a self map entry value is malicious or not.
Definition: winselfmap.h:34
Kernel-mode exception.
Definition: exceptions.h:61
INTRO_EXEC_CONTEXT ExecContext
Information about the instruction that triggered the alert.
Definition: intro_types.h:1309
#define WARNING(fmt,...)
Definition: glue.h:60
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:928
4-level paging
Definition: introcore.h:71
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
static INTSTATUS IntWinSelfMapHandleCr3SelfMapModification(QWORD NewValue, QWORD OldValue, WIN_PROCESS_OBJECT *Process, QWORD Cr3)
Handles self map entry modifications for a process.
Definition: winselfmap.c:41
Describes the modified zone.
Definition: exceptions.h:893
void * SelfMapHook
The self mapping memory hook.
Definition: winprocess.h:259
struct _EXCEPTION_VICTIM_ZONE::@58::@60 WriteInfo
#define __forceinline
Definition: introtypes.h:61
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:965
enum _INTRO_ACTION INTRO_ACTION
Event actions.
QWORD Rip
The RIP from where the call to the exported function came.
Definition: exceptions.h:950
QWORD OldValue[8]
The original value. Only the first Size bytes are valid.
Definition: intro_types.h:980
#define SELF_MAP_ENTRY_VA
Computes the virtual address at which the self map entry is mapped for this guest.
Definition: winselfmap.h:39
INTSTATUS IntWinSelfMapDisableSelfMapEntryProtection(void)
Disables the self map entry protection for all the processes on the system.
Definition: winselfmap.c:656
Measures the self map entry validation.
Definition: stats.h:65
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:374
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:673
Self mapping index in PDBR.
Definition: intro_types.h:254
INTRO_MODULE Module
The module that modified the translation.
Definition: intro_types.h:1546
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:136
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
static void IntWinSelfMapSelfMapUpdate(QWORD ModifiedCr3, WIN_PROCESS_OBJECT *Process, QWORD NewValue)
Updates the self map entry value for a process.
Definition: winselfmap.c:13
struct _EXCEPTION_KM_ORIGINATOR::@64 Original
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
PAGING_MODE Mode
The paging mode used by the guest.
Definition: guests.h:221
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
Definition: glue.c:338
static INTSTATUS IntWinSelfMapCheckSelfMapEntry(WIN_PROCESS_OBJECT *Process, const QWORD *CurrentKernelValue, const QWORD *CurrentUserValue)
Checks the self map entry for a given process.
Definition: winselfmap.c:141
#define INT_STATUS_NOT_INITIALIZED_HINT
Definition: introstatus.h:320
struct _EVENT_TRANSLATION_VIOLATION::@300 Originator
INTSTATUS IntWinSelfMapGetAndCheckSelfMapEntry(WIN_PROCESS_OBJECT *Process)
Sets and validates the self map entry values for a process.
Definition: winselfmap.c:579
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
Holds register state.
Definition: glueiface.h:30
Event structure for EPT violations.
Definition: intro_types.h:1215
BOOLEAN Valid
True if the information in this structure is valid; False it it is not.
Definition: guests.h:53
PTEMU_BUFFER PtEmuBuffer
The page table write emulator buffer.
Definition: guests.h:169
Write-access hook.
Definition: glueiface.h:299
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
Definition: glue.c:396
INTSTATUS IntExceptKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator, DWORD Options)
This function is used to get the information about the kernel-mode originator.
INTSTATUS IntAlertFillExecContext(QWORD Cr3, INTRO_EXEC_CONTEXT *ExecContext)
Fills the current execution context.
Definition: alerts.c:31
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:271
void IntExcept(EXCEPTION_VICTIM_ZONE *Victim, void *Originator, EXCEPTION_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason, INTRO_EVENT_TYPE EventClass)
This function is the entry point for the exception mechanism.
Definition: exceptions.c:3357
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83