Bitdefender Hypervisor Memory Introspection
wintoken.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "wintoken.h"
6 #include "winprocess.h"
7 #include "winprocesshp.h"
8 #include "decoder.h"
9 #include "hook.h"
10 #include "drivers.h"
11 #include "alerts.h"
12 #include "winpool.h"
13 #include "gpacache.h"
14 
49 
50 
52 
53 
54 static INTSTATUS
56  _In_opt_ void *Context,
57  _In_ void *Hook,
58  _In_ QWORD Address,
59  _Out_ INTRO_ACTION *Action
60  );
61 
62 
63 static void
65  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
67  _In_ INTRO_ACTION Action,
69  )
78 {
80  INTSTATUS status;
81 
82  memzero(pEpt, sizeof(*pEpt));
83 
84  pEpt->Header.Action = Action;
85  pEpt->Header.Reason = Reason;
87 
89 
90  IntAlertEptFillFromKmOriginator(Originator, pEpt);
91  IntAlertEptFillFromVictimZone(Victim, pEpt);
92 
94 
95  if (Victim->Object.WinProc->SystemProcess)
96  {
98  }
99 
100  IntAlertFillWinProcessByCr3(Victim->Object.WinProc->Cr3, &pEpt->Header.CurrentProcess);
101 
102  IntAlertFillCodeBlocks(Originator->Original.Rip, gVcpu->Regs.Cr3, FALSE, &pEpt->CodeBlocks);
104 
106 
107  status = IntNotifyIntroEvent(introEventEptViolation, pEpt, sizeof(*pEpt));
108  if (!INT_SUCCESS(status))
109  {
110  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
111  }
112 }
113 
114 
115 static void
117  _In_ EXCEPTION_VICTIM_ZONE *Victim,
118  _In_ INTRO_ACTION Action,
120  )
128 {
129  INTSTATUS status;
130  EVENT_INTEGRITY_VIOLATION *pIntViol;
131 
132  pIntViol = &gAlert.Integrity;
133  memzero(pIntViol, sizeof(*pIntViol));
134 
136 
137  // Force de-activation of ALERT_FLAG_NOT_RING0. We're always in ring0.
138  pIntViol->Header.Flags &= ~ALERT_FLAG_NOT_RING0;
139 
140  pIntViol->Header.Flags |= ALERT_FLAG_ASYNC;
141 
142  pIntViol->Header.Action = Action;
143  pIntViol->Header.Reason = Reason;
144  pIntViol->Header.MitreID = idAccessToken;
145 
146  pIntViol->Victim.Type = Victim->Object.Type;
147 
148  memcpy(pIntViol->Victim.Name, VICTIM_TOKEN_PRIVILEGES, sizeof(VICTIM_TOKEN_PRIVILEGES));
149 
150  IntAlertFillWinProcess(Victim->Object.Process, &pIntViol->Originator.Process);
151  IntAlertFillWinProcess(Victim->Object.Process, &pIntViol->Victim.Process);
152  IntAlertFillWinProcess(Victim->Object.Process, &pIntViol->Header.CurrentProcess);
153 
154  IntAlertFillWriteInfo(Victim, &pIntViol->WriteInfo);
155 
157 
158  // We can't know from what CPU the write was, but we know where the integrity check failed
159  pIntViol->Header.CpuContext.Valid = FALSE;
160 
161  IntAlertFillVersionInfo(&pIntViol->Header);
162 
163  status = IntNotifyIntroEvent(introEventIntegrityViolation, pIntViol, sizeof(*pIntViol));
164  if (!INT_SUCCESS(status))
165  {
166  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
167  }
168 }
169 
170 static BOOLEAN
172  _In_ WIN_PROCESS_OBJECT *Process,
173  _In_ QWORD NewTokenPtr
174  )
194 {
195  void *pPage = NULL;
196  INTSTATUS status;
197  const POOL_HEADER *ph;
198  DWORD blockSize, desiredBlockSize;
199  BOOLEAN ret;
200 
201  // By default protect everything through EPT if we have SPP.
202  if (gGuest.SupportSPP)
203  {
204  return TRUE;
205  }
206 
207  // If the process was static detected there's virtually no chance that the token was allocated
208  // through our hook. Bail out the following checks since they would most likely not pass on static
209  // detected processes.
210  if (Process->StaticDetected)
211  {
212  return FALSE;
213  }
214 
215  // The process is not static detected, now verify that the token is really allocated through our hook handler
216  // and the allocation has been forced to PAGE_SIZE for performance improvement. If the block size is not 0xff
217  // (meaning that the allocation + sizeof(pool_header) = 1 page), it means that the allocation was not forced
218  // and we should not protect through EPT this token, as it would most probably induce a high performance impact.
219  // We have previously observed this behavior on the "registry" process, where the token assigned to that process
220  // is allocated at boot time, long before we initialize our hooks.
221  status = IntVirtMemMap(NewTokenPtr & PAGE_MASK, PAGE_SIZE, gGuest.Mm.SystemCr3, 0, &pPage);
222  if (!INT_SUCCESS(status))
223  {
224  ERROR("[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n", NewTokenPtr, status);
225  return FALSE;
226  }
227 
228  ph = IntWinPoolGetPoolHeaderInPage(pPage, NewTokenPtr & PAGE_OFFSET, WIN_POOL_TAG_TOKE);
229  if (NULL == ph)
230  {
231  // Try with WIN_POOL_TAG_TOKE2, as on windows 7, the most significant bit is set if the allocation is
232  // considered "Protected".
233  ph = IntWinPoolGetPoolHeaderInPage(pPage, NewTokenPtr & PAGE_OFFSET, WIN_POOL_TAG_TOKE2);
234  if (NULL == ph)
235  {
236  ERROR("[ERROR] IntWinPoolGetPoolHeaderInPage did not found a valid pool header!\n");
237  ret = FALSE;
238  goto _exit;
239  }
240  }
241 
242  blockSize = gGuest.Guest64 ? ph->Header64.BlockSize : ph->Header32.BlockSize;
243  desiredBlockSize = gGuest.Guest64 ? 0xFF : 0x1FF;
244 
245  if (blockSize != desiredBlockSize)
246  {
247  // This means that the token didn't go through our allocation hook. That's a pity, but we'll detect it through
248  // integrity if anything goes wrong, or if the token changes to one of the tokens which were forced
249  // to page size.
250  ret = FALSE;
251  goto _exit;
252  }
253 
254  ret = TRUE;
255 
256 _exit:
257  if (NULL != pPage)
258  {
259  IntVirtMemUnmap(&pPage);
260  }
261 
262  return ret;
263 }
264 
265 
266 static INTSTATUS
268  _In_ WIN_PROCESS_OBJECT *Process,
269  _In_ QWORD NewTokenPtr
270  )
281 {
282  INTSTATUS status;
283 
284  if (NULL != Process->TokenHook)
285  {
286  status = IntHookGvaRemoveHook((HOOK_GVA **)&Process->TokenHook, 0);
287  if (!INT_SUCCESS(status))
288  {
289  ERROR("[ERROR] IntHookGvaRemoveHook failed: 0x%08x\n", status);
290  return status;
291  }
292  }
293 
294  if (IntWinTokenPrivsShouldHook(Process, NewTokenPtr))
295  {
297  NewTokenPtr & PAGE_MASK,
298  PAGE_SIZE,
301  Process,
302  NULL,
303  0,
304  (HOOK_GVA **)&Process->TokenHook);
305  if (!INT_SUCCESS(status))
306  {
307  ERROR("[ERROR] IntHookGvaSetHook failed: 0x%08x\n", status);
308  return status;
309  }
310  }
311  else
312  {
313  TRACE("[INFO] Token at 0x%016llx is not allocated through our hook - we'll protect it only with integrity!\n",
314  NewTokenPtr);
315  }
316 
317  return INT_STATUS_SUCCESS;
318 }
319 
320 
321 static INTSTATUS
323  _In_opt_ void *Context,
324  _In_ void *Hook,
325  _In_ QWORD Address,
326  _Out_ INTRO_ACTION *Action
327  )
340 {
341  WIN_PROCESS_OBJECT *pProc = Context;
342  QWORD newTokenPtr = 0;
343  INTSTATUS status;
344  INTRO_ACTION_REASON reason;
345  EXCEPTION_KM_ORIGINATOR originator = { 0 };
346  EXCEPTION_VICTIM_ZONE victim = { 0 };
347  BOOLEAN exitAfterInformation = FALSE;
348  DWORD privsOffsetInPage, writeOffset;
349 
351 
352  *Action = introGuestAllowed;
353 
354  if (NULL == pProc)
355  {
356  return INT_STATUS_NOT_FOUND;
357  }
358 
359  status = IntKernVirtMemFetchWordSize(pProc->EprocessAddress + WIN_KM_FIELD(Process, Token), &newTokenPtr);
360  if (!INT_SUCCESS(status))
361  {
362  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
363  return status;
364  }
365 
366  newTokenPtr = EX_FAST_REF_TO_PTR(gGuest.Guest64, newTokenPtr);
367 
368  if (newTokenPtr != pProc->OriginalTokenPtr)
369  {
370  IntWinTokenProtectPrivsInternal(pProc, newTokenPtr);
371 
372  // Check integrity if token changed.
374 
375  *Action = introGuestAllowed;
376  return INT_STATUS_SUCCESS;
377  }
378 
379  privsOffsetInPage = (pProc->OriginalTokenPtr & PAGE_OFFSET) + WIN_KM_FIELD(Token, Privs);
380  writeOffset = Address & PAGE_OFFSET;
381 
382  // The write [woff, woff + access_size) was outside the ranges [privoff, privoff + 3 * sizeof(QWORD)),
383  // basically the interval [a, b) cannot intersect with [x, y) if either b <= x or a >= y. Since we already verified
384  // if the token has changed, and the write is not over the Privileges field, we will just return in this case.
385  if (writeOffset + gVcpu->AccessSize <= privsOffsetInPage || writeOffset >= privsOffsetInPage + 3 * sizeof(QWORD))
386  {
387  *Action = introGuestAllowed;
388  return INT_STATUS_SUCCESS;
389  }
390 
393 
394  *Action = introGuestNotAllowed;
395  reason = introReasonUnknown;
396 
397  status = IntExceptKernelGetOriginator(&originator, 0);
398  if (status == INT_STATUS_EXCEPTION_BLOCK)
399  {
400  reason = introReasonNoException;
401  exitAfterInformation = TRUE;
402  }
403  else if (!INT_SUCCESS(status))
404  {
405  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
406  reason = introReasonInternalError;
407  exitAfterInformation = TRUE;
408  }
409 
410  status = IntExceptGetVictimEpt(Context,
411  Address,
412  IntHookGetGlaFromGpaHook(Hook, Address),
414  ZONE_WRITE,
415  &victim);
416  if (!INT_SUCCESS(status))
417  {
418  reason = introReasonInternalError;
419  ERROR("[ERROR] Failed getting zone details: 0x%08x\n", status);
420  goto _exit_exceptions;
421  }
422 
423  if (exitAfterInformation)
424  {
425  IntExceptKernelLogInformation(&victim, &originator, *Action, reason);
426  }
427  else
428  {
429  IntExcept(&victim, &originator, exceptionTypeKm, Action, &reason, introEventEptViolation);
430  }
431 
432 _exit_exceptions:
434 
436  {
437  IntWinTokenPrivsSendEptAlert(&originator, &victim, *Action, reason);
438  }
439 
441 
443 
444  return INT_STATUS_SUCCESS;
445 }
446 
447 
448 static INTSTATUS
450  _In_ WIN_PROCESS_OBJECT *Process,
451  _Out_ QWORD *OldValue,
452  _Out_ QWORD *NewValue
453  )
469 {
470  INTSTATUS status;
471  VA_TRANSLATION tr = { 0 };
472  QWORD newValue = 0, oldValue = 0;
473 
474  status = IntTranslateVirtualAddressEx(Process->EprocessAddress + WIN_KM_FIELD(Process, Token),
477  &tr);
478  if (!INT_SUCCESS(status))
479  {
480  ERROR("[ERROR] IntTranslateVirtualAddressEx failed: 0x%08x\n", status);
481  return status;
482  }
483 
484  if (0 == (tr.Flags & PT_P))
485  {
487  }
488 
489  // Read the token.
491  if (!INT_SUCCESS(status))
492  {
493  ERROR("[ERROR] IntGpaCacheFetchAndAdd failed: 0x%08x\n", status);
494  return status;
495  }
496 
497  // Ignore ref count.
498  newValue = EX_FAST_REF_TO_PTR(gGuest.Guest64, newValue);
499  oldValue = EX_FAST_REF_TO_PTR(gGuest.Guest64, Process->OriginalTokenPtr);
500 
501  *OldValue = oldValue;
502  *NewValue = newValue;
503 
504  return INT_STATUS_SUCCESS;
505 }
506 
507 
508 _Success_(return == TRUE)
509 BOOLEAN
511  _In_ WIN_PROCESS_OBJECT *Process,
512  _In_ BOOLEAN Check,
513  _Out_opt_ WIN_PROCESS_OBJECT **FromProcess,
514  _Out_opt_ QWORD *OldValue,
515  _Out_opt_ QWORD *NewValue
516  )
531 {
532  INTSTATUS status = INT_STATUS_SUCCESS;
533  QWORD newValue = 0, oldValue = 0;
534  WIN_PROCESS_OBJECT *pProc = Process;
535 
536  status = IntWinTokenFetchTokenAddress(pProc, &oldValue, &newValue);
537  if (!INT_SUCCESS(status))
538  {
539  ERROR("[ERROR] IntWinTokenFetchTokenAddress failed: 0x%08x\n", status);
540  return FALSE;
541  }
542 
543  pProc->OriginalTokenPtr = newValue;
544 
545  // the pointer should never change
546  if (Check || ((newValue != oldValue) && (0 != newValue)))
547  {
548  WIN_PROCESS_OBJECT* pProc2 = NULL;
549  LIST_ENTRY* list;
550  BOOLEAN bFound;
551 
552  // Check if the new token belongs to another process; if it doesn't, we can bail out, it is most likely
553  // a legitimate action.
554  bFound = FALSE;
555  list = gWinProcesses.Flink;
556  while (list != &gWinProcesses)
557  {
558  pProc2 = CONTAINING_RECORD(list, WIN_PROCESS_OBJECT, Link);
559 
560  list = list->Flink;
561 
562  // Ignore the current process, as it will obviously have this token already.
563  if (pProc2 == pProc)
564  {
565  continue;
566  }
567 
568  if (EX_FAST_REF_TO_PTR(gGuest.Guest64, pProc2->OriginalTokenPtr) == newValue)
569  {
570  bFound = TRUE;
571  break;
572  }
573  }
574 
575  if (!bFound || (NULL == pProc2))
576  {
577  goto _bail_out;
578  }
579 
580  if (NULL != NewValue)
581  {
582  *NewValue = newValue;
583  }
584 
585  if (NULL != OldValue)
586  {
587  *OldValue = oldValue;
588  }
589 
590  if (NULL != FromProcess)
591  {
592  *FromProcess = pProc2;
593  }
594 
595  return TRUE;
596  }
597 
598 _bail_out:
599  return FALSE;
600 }
601 
602 
603 INTSTATUS
605  _In_ WIN_PROCESS_OBJECT *Process
606 )
614 {
615  QWORD newValue;
616  QWORD oldValue;
617  WIN_PROCESS_OBJECT *pProc;
618  WIN_PROCESS_OBJECT *pProc2;
619 
620  if (NULL == Process)
621  {
623  }
624 
625  pProc = Process;
626 
627  if (IntWinTokenPtrIsStolen(pProc, FALSE, &pProc2, &oldValue, &newValue))
628  {
629  EVENT_INTEGRITY_VIOLATION* pIntViolation;
630  INTSTATUS status;
631 
632  IntPauseVcpus();
633 
634  LOG("[INTEGRITY VIOLATION] Token pointer was modified (%llx -> %llx): "
635  "process %llx (%d / %s), token stolen from process %llx (%d / %s)\n",
636  oldValue, newValue, pProc->EprocessAddress, pProc->Pid,
637  pProc->Name, pProc2->EprocessAddress, pProc2->Pid, pProc2->Name);
639  {
640  LOG("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (B) MALWARE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n");
641  }
642  else
643  {
644  LOG("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MALWARE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n");
645  }
646 
647  // We can't change the pointer back to the original value because that would result in a bug check
648  // almost all the time so save the new value in order to avoid alert spamming and to catch future changes.
649 
650  pIntViolation = &gAlert.Integrity;
651  memzero(pIntViolation, sizeof(*pIntViolation));
652 
653  pIntViolation->Header.Action = introGuestAllowed;
654  pIntViolation->Header.Reason = introReasonNoException;
655  pIntViolation->Header.MitreID = idAccessToken;
656 
657  pIntViolation->Header.CpuContext.Valid = FALSE;
658 
659  IntAlertFillWinProcess(pProc, &pIntViolation->Header.CurrentProcess);
660  IntAlertFillWinProcess(pProc, &pIntViolation->Originator.Process);
661  IntAlertFillWinProcess(pProc2, &pIntViolation->Victim.Process);
662 
664  {
665  pIntViolation->Header.Flags |= ALERT_FLAG_BETA;
666  }
667  pIntViolation->Header.Flags |= ALERT_FLAG_ASYNC;
668 
669  pIntViolation->Victim.Type = introObjectTypeTokenPtr;
670  memcpy(pIntViolation->Victim.Name, VICTIM_PROCESS_TOKEN, sizeof(VICTIM_PROCESS_TOKEN));
671 
672  pIntViolation->Size = gGuest.WordSize;
673  pIntViolation->BaseAddress = pProc2->EprocessAddress + WIN_KM_FIELD(Process, Token);
674  pIntViolation->VirtualAddress = pProc->EprocessAddress + WIN_KM_FIELD(Process, Token);
675 
676  pIntViolation->WriteInfo.Size = gGuest.WordSize;
677  pIntViolation->WriteInfo.OldValue[0] = oldValue;
678  pIntViolation->WriteInfo.NewValue[0] = newValue;
679 
680  IntAlertFillVersionInfo(&pIntViolation->Header);
681 
682  status = IntNotifyIntroEvent(introEventIntegrityViolation, pIntViolation, sizeof(*pIntViolation));
683  if (!INT_SUCCESS(status))
684  {
685  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
686  }
687 
688  IntResumeVcpus();
689  }
690 
691  return INT_STATUS_SUCCESS;
692 }
693 
694 
695 INTSTATUS
697  _In_ WIN_PROCESS_OBJECT *Process,
698  _In_ QWORD TokenPtr,
699  _Out_ BOOLEAN *PresentIncreased,
700  _Out_ BOOLEAN *EnabledIncreased,
701  _Out_opt_ QWORD *Present,
702  _Out_opt_ QWORD *Enabled
703  )
733 {
734  INTSTATUS status;
735  QWORD privs[2];
736  QWORD present, enabled;
737 
738  if (NULL == Process)
739  {
741  }
742 
743  if (NULL == PresentIncreased)
744  {
746  }
747 
748  if (NULL == EnabledIncreased)
749  {
751  }
752 
753  *PresentIncreased = FALSE;
754  *EnabledIncreased = FALSE;
755 
756  // Always check the new token, as the old token may have been used for something else in the meantime.
757  status = IntVirtMemRead(TokenPtr + WIN_KM_FIELD(Token, Privs), 2 * sizeof(QWORD), gGuest.Mm.SystemCr3, privs, NULL);
758  if (!INT_SUCCESS(status))
759  {
760  // The token is probably not present in memory, nothing we can do for now...
761  return status;
762  }
763 
764  present = privs[0];
765  enabled = privs[1];
766 
767  // We might have not fetched the enabled/present beforehand, so don't bother checking.
768  if (Process->OriginalEnabledPrivs == 0 && Process->OriginalPresentPrivs == 0)
769  {
770  goto _skip_checks;
771  }
772 
773  // Check if there is any bit which is set in present and not set in original present.
774  if ((present & (~Process->OriginalPresentPrivs)) != 0)
775  {
776  *PresentIncreased = TRUE;
777  }
778 
779  // All bits in enabled must also be set in present, if any bit is not set in present => it shouldn't
780  // have that privilege
781  if (enabled != Process->OriginalEnabledPrivs && (enabled & present) != enabled)
782  {
783  // Windows 7 is a hidden gem and, when a privilege is disabled, it disables it from present and
784  // just after that from enabled. This may lead to a race condition, where we find a bit in Enabled
785  // which is not set in Present. We will check, only for windows 7 if there is (only) a bit which
786  // can give a detection in this case, and skip the detection if this happens.
787  if (gGuest.OSVersion >= 7600 && gGuest.OSVersion <= 7602)
788  {
789  QWORD diffbits = enabled & (~(enabled & present));
790 
791  if (diffbits != 0 && (diffbits & (diffbits - 1)) == 0)
792  {
793  WARNING("[WARNING] Special case on Windows 7, difference 1 bit! 0x%016llx 0x%016llx\n",
794  enabled, present);
795  goto _skip_checks;
796  }
797  }
798 
799  *EnabledIncreased = TRUE;
800  }
801 
802 _skip_checks:
803  if (NULL != Present)
804  {
805  *Present = present;
806  }
807 
808  if (NULL != Enabled)
809  {
810  *Enabled = enabled;
811  }
812 
813  return INT_STATUS_SUCCESS;
814 }
815 
816 
817 INTSTATUS
819  _In_ WIN_PROCESS_OBJECT *Process
820  )
829 {
830  INTSTATUS status;
831  QWORD present, enabled;
832  QWORD oldValue = 0, newValue = 0;
833  BOOLEAN presentIncreased = FALSE, enabledIncreased = FALSE;
834  EXCEPTION_KM_ORIGINATOR originator = { 0 };
835  EXCEPTION_VICTIM_ZONE victim = { 0 };
836  INTRO_ACTION action;
837  INTRO_ACTION_REASON reason;
838 
839  if (NULL == Process)
840  {
842  }
843 
844  status = IntWinTokenFetchTokenAddress(Process, &oldValue, &newValue);
845  if (!INT_SUCCESS(status))
846  {
847  ERROR("[ERROR] IntWinTokenFetchTokenAddress failed: 0x%08x!\n", status);
848  return status;
849  }
850 
851  if (oldValue != newValue)
852  {
853  IntWinTokenProtectPrivsInternal(Process, newValue);
854  }
855 
856  status = IntWinTokenCheckCurrentPrivileges(Process,
857  newValue,
858  &presentIncreased,
859  &enabledIncreased,
860  &present,
861  &enabled);
862  if (!INT_SUCCESS(status))
863  {
864  return status;
865  }
866 
867  if (Process->SkipPrivsNextCheck)
868  {
869  goto _skip_checks;
870  }
871 
872  if (presentIncreased || enabledIncreased)
873  {
874  // The originator is only dummy. Complete just the elements so that we can go through exceptions.
875  originator.Original.NameHash = INITIAL_CRC_VALUE;
876  originator.Return.NameHash = INITIAL_CRC_VALUE;
877 
878  // Since we don't have an INTEGRITY_REGION associated, we'll complete the victim in-place.
879  victim.Object.Process = Process;
880  victim.Object.NameHash = Process->NameHash;
882  victim.ZoneFlags |= ZONE_WRITE | ZONE_INTEGRITY;
884 
885  victim.WriteInfo.OldValue[0] = Process->OriginalPresentPrivs;
886  victim.WriteInfo.OldValue[1] = Process->OriginalEnabledPrivs;
887 
888  victim.WriteInfo.NewValue[0] = present;
889  victim.WriteInfo.NewValue[1] = enabled;
890 
891  victim.WriteInfo.AccessSize = 2 * sizeof(QWORD);
892 
893  IntExcept(&victim, &originator, exceptionTypeKm, &action, &reason, introEventIntegrityViolation);
894 
896  {
897  // Mark action as allowed, since we didn't really block anything.
899 
900  if (presentIncreased)
901  {
902  WARNING("[WARNING] Present privileges are higher than the original ones: "
903  "0x%016llx vs 0x%016llx in process %s:%d\n",
904  present,
905  Process->OriginalPresentPrivs,
906  Process->Name,
907  Process->Pid);
908  }
909  if (enabledIncreased)
910  {
911  WARNING("[WARNING] Enabled privileges are higher than the present ones: "
912  "0x%016llx vs 0x%016llx in process %s:%d\n",
913  enabled,
914  present,
915  Process->Name,
916  Process->Pid);
917  }
918  }
919 
920  // Theoretically, we can overwrite the privileges with the old ones if not allowed, but note that we are
921  // around ~1 sec after the LPE took place, so the exploit could have run enough to do damage
922  // with the gained privileges, so there's not much to do about it...
923 
924  // Note that we should also consider on DPI from now on as a detection every process creation, since
925  // on DPI we will see only the changed values, as we update them below.
926  Process->PrivsChangeDetected = TRUE;
927  }
928 
929 _skip_checks:
930  // Save them so we don't give an alert for the same stuff once every second.
931  Process->OriginalPresentPrivs = present;
932  Process->OriginalEnabledPrivs = enabled;
933 
934  // On the next tick, give a detection if something else changed.
935  Process->SkipPrivsNextCheck = FALSE;
936 
937  return status;
938 }
939 
940 
943  void
944  )
952 {
953  LIST_ENTRY *pList = NULL;
954 
956  {
958  }
959 
961  {
963  }
964 
965  if ((introGuestWindows != gGuest.OSType) ||
967  {
969  }
970 
971  pList = gWinProcesses.Flink;
972  while (pList != &gWinProcesses)
973  {
974  WIN_PROCESS_OBJECT* pProcess = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
975  INTSTATUS status;
976 
977  pList = pList->Flink;
978 
979  // Note: the order is important here, we should do the token stolen integrity checks
980  // always the last one, since afterwards we won't have anymore the old token, as the
981  // check will also overwrite the OriginalTokenPtr field.
983  {
984  status = IntWinTokenPrivsCheckIntegrityOnProcess(pProcess);
985  if (!INT_SUCCESS(status) &&
987  {
988  ERROR("[ERROR] IntWinTokenPtrCheckIntegrityOnProcess failed: 0x%08x\n", status);
989  }
990  }
991 
993  {
994  status = IntWinTokenPtrCheckIntegrityOnProcess(pProcess);
995  if (!INT_SUCCESS(status) &&
997  {
998  ERROR("[ERROR] IntWinTokenPtrCheckIntegrityOnProcess failed: 0x%08x\n", status);
999  }
1000  }
1001  }
1002 
1003  return INT_STATUS_SUCCESS;
1004 }
1005 
1006 
1007 INTSTATUS
1009  _Inout_ WIN_PROCESS_OBJECT *Process
1010  )
1021 {
1022  QWORD privs[2];
1023  INTSTATUS status;
1024 
1025  if (NULL == Process)
1026  {
1028  }
1029 
1030  if (NULL != Process->TokenHook)
1031  {
1033  }
1034 
1035  status = IntVirtMemRead(Process->OriginalTokenPtr + WIN_KM_FIELD(Token, Privs),
1036  2 * sizeof(QWORD),
1038  privs,
1039  NULL);
1040  if (!INT_SUCCESS(status))
1041  {
1042  // If the page is not present, just skip checks on next integrity and skip ept hooking,
1043  // as we can't properly decide whether to hook the token or not.
1045  {
1046  Process->SkipPrivsNextCheck = TRUE;
1047  return INT_STATUS_SUCCESS;
1048  }
1049 
1050  ERROR("[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
1051  return status;
1052  }
1053 
1054  // Save them even if the flag was not given, so that, if the flag is suddenly activated and we check integrity,
1055  // we won't have any bad surprises.
1056  Process->OriginalPresentPrivs = privs[0];
1057  Process->OriginalEnabledPrivs = privs[1];
1058 
1060  {
1062  }
1063 
1064  return IntWinTokenProtectPrivsInternal(Process, Process->OriginalTokenPtr);
1065 }
1066 
1067 
1068 INTSTATUS
1070  _In_ WIN_PROCESS_OBJECT *Process
1071  )
1072 {
1073  INTSTATUS status = INT_STATUS_SUCCESS;
1074 
1075  if (NULL == Process)
1076  {
1078  }
1079 
1080  if (NULL != Process->TokenHook)
1081  {
1082  status = IntHookGvaRemoveHook((HOOK_GVA **)&Process->TokenHook, 0);
1083  if (!INT_SUCCESS(status))
1084  {
1085  ERROR("[ERROR] IntHookGvaRemoveHook failed: 0x%08x\n", status);
1086  }
1087  }
1088 
1089  return status;
1090 }
1091 
1092 
1093 INTSTATUS
1095  void
1096  )
1103 {
1104  LIST_ENTRY *list;
1105  INTSTATUS status;
1106 
1108  {
1110  }
1111 
1112  list = gWinProcesses.Flink;
1113 
1114  while (list != &gWinProcesses)
1115  {
1117 
1118  list = list->Flink;
1119 
1120  status = IntWinTokenPrivsProtectOnProcess(pProc);
1121  if (!INT_SUCCESS(status))
1122  {
1123  WARNING("[WARNING] IntWinTokenPrivsProtectOnProcess failed for %s:%d: 0x%08x\n",
1124  pProc->Name,
1125  pProc->Pid,
1126  status);
1127  }
1128  }
1129 
1130  return INT_STATUS_SUCCESS;
1131 }
1132 
1133 
1134 INTSTATUS
1136  void
1137  )
1144 {
1145  LIST_ENTRY *list;
1146  INTSTATUS status = INT_STATUS_SUCCESS;
1147 
1149  {
1151  }
1152 
1153  list = gWinProcesses.Flink;
1154 
1155  while (list != &gWinProcesses)
1156  {
1158 
1159  list = list->Flink;
1160 
1161  if (NULL != pProc->TokenHook)
1162  {
1163  IntHookGvaRemoveHook((HOOK_GVA **)&pProc->TokenHook, 0);
1164  }
1165  }
1166 
1167  return status;
1168 }
Measures kernel mode exceptions checks.
Definition: stats.h:51
#define _In_opt_
Definition: intro_sal.h:16
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
Definition: introstatus.h:438
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
Definition: introcore.h:107
struct _EXCEPTION_KM_ORIGINATOR::@63 Original
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:1145
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
#define WIN_POOL_TAG_TOKE2
Definition: winpool.h:18
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
Exposes the types, constants and functions used to handle Windows processes events (creation...
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
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:896
#define VICTIM_PROCESS_TOKEN
Printable name used for introObjectTypeTokenPtr objects.
Definition: intro_types.h:685
#define EX_FAST_REF_TO_PTR(is64, p)
Converts a _EX_FAST_REF value to a pointer.
Definition: wddefs.h:100
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
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
QWORD ZoneFlags
The flags of the modified zone.
Definition: exceptions.h:852
static INTSTATUS IntWinTokenFetchTokenAddress(WIN_PROCESS_OBJECT *Process, QWORD *OldValue, QWORD *NewValue)
Fetches the token pointer from inside the EPROCESS and returns the old token pointer and the new toke...
Definition: wintoken.c:449
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:1088
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:207
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
const POOL_HEADER * IntWinPoolGetPoolHeaderInPage(const void *Page, DWORD StartOffset, DWORD Tag)
Search for a pool header with given tag in a buffer.
Definition: winpool.c:160
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:895
#define STATS_EXIT(id)
Definition: stats.h:148
static BOOLEAN IntWinTokenPrivsShouldHook(WIN_PROCESS_OBJECT *Process, QWORD NewTokenPtr)
Decides if the given token address should be hooked through EPT or not.
Definition: wintoken.c:171
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
Event structure for integrity violations on monitored structures.
Definition: intro_types.h:1450
POOL_HEADER32 Header32
Definition: wddefs.h:462
struct _LIST_ENTRY * Flink
Definition: introlists.h:20
#define _Success_(expr)
Definition: intro_sal.h:47
struct _EXCEPTION_VICTIM_ZONE::@57::@59 WriteInfo
#define INTRO_OPT_PROT_KM_TOKEN_PTR
Enable process token protection (Windows only).
Definition: intro_types.h:400
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
INTRO_OBJECT_TYPE Type
Definition: intro_types.h:1462
BOOLEAN ProtectionActivated
Definition: guests.h:293
#define PAGE_OFFSET
Definition: pgtable.h:32
BOOLEAN KernelBetaDetections
True if the kernel protection is in beta (log-only) mode.
Definition: guests.h:299
QWORD IntHookGetGlaFromGpaHook(HOOK_GPA const *Hook, QWORD Address)
Gets the GLA from a GPA hook.
Definition: hook.c:279
DWORD BlockSize
Definition: wddefs.h:440
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
static INTSTATUS IntWinTokenPrivsHandleWrite(void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
EPT callback triggered when a write occurs over the Privileges bitfields in a nt!_TOKEN structure pro...
Definition: wintoken.c:322
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:637
Token writes.
Definition: stats.h:94
INTSTATUS IntKernVirtMemFetchWordSize(QWORD GuestVirtualAddress, void *Data)
Reads a guest pointer from the guest kernel memory.
Definition: introcore.c:847
int INTSTATUS
The status data type.
Definition: introstatus.h:24
DWORD OSVersion
Os version.
Definition: guests.h:277
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
TIMER_FRIENDLY INTSTATUS IntWinTokenCheckIntegrity(void)
This function checks the integrity of the security token for all the processes inside gWinProcesses...
Definition: wintoken.c:942
Describes a kernel-mode originator.
Definition: exceptions.h:897
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:274
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
#define LOG(fmt,...)
Definition: glue.h:61
LIST_HEAD gWinProcesses
The list of all the processes inside the guest.
Definition: winprocesshp.c:11
INTSTATUS IntHookGvaSetHook(QWORD Cr3, QWORD Gva, DWORD Length, BYTE Type, void *Callback, void *Context, void *ParentHook, DWORD Flags, HOOK_GVA **GvaHook)
Set a read, write, execute or swap hook on a guest virtual address.
Definition: hook_gva.c:345
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
DWORD AccessSize
The size of the memory access. Valid only for EPT exits.
Definition: guests.h:103
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1106
#define ZONE_INTEGRITY
Used for integrity zone.
Definition: exceptions.h:702
Access Token Manipulation.
Definition: intro_types.h:1042
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1084
INTSTATUS IntWinTokenPtrCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the security token of a given process has been stone from another process...
Definition: wintoken.c:604
EXCEPTION_VICTIM_OBJECT Object
The modified object.
Definition: exceptions.h:849
INTSTATUS IntAlertFillCodeBlocks(QWORD Rip, QWORD Cr3, BOOLEAN Execute, INTRO_CODEBLOCKS *CodeBlocks)
Fills the code blocks pattern for an alert.
Definition: alerts.c:71
Token privileges.
Definition: intro_types.h:263
#define ALERT_FLAG_BETA
If set, the alert is a BETA alert. No action was taken.
Definition: intro_types.h:633
static void IntWinTokenPrivsSendIntegrityAlert(EXCEPTION_VICTIM_ZONE *Victim, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an EVENT_INTEGRITY_VIOLATION when checks over the token privileges have failed.
Definition: wintoken.c:116
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
BOOLEAN SupportSPP
Set to True if support for SPP was detected.
Definition: guests.h:353
#define _Inout_
Definition: intro_sal.h:20
INTSTATUS IntWinTokenPrivsUnprotectOnProcess(WIN_PROCESS_OBJECT *Process)
Definition: wintoken.c:1069
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
#define _Out_opt_
Definition: intro_sal.h:30
void IntAlertFillWriteInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_WRITE_INFO *WriteInfo)
Fills the write information for an alert.
Definition: alerts.c:521
#define WIN_POOL_TAG_TOKE
Definition: winpool.h:17
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
#define INT_STATUS_EXCEPTION_BLOCK
Definition: introstatus.h:421
DWORD Size
The size of the modified memory area.
Definition: intro_types.h:1483
void IntAlertEptFillFromVictimZone(const EXCEPTION_VICTIM_ZONE *Victim, EVENT_EPT_VIOLATION *EptViolation)
Fills the victim information inside an EPT alert.
Definition: alerts.c:868
POOL_HEADER64 Header64
Definition: wddefs.h:463
The modified object is inside an integrity hook.
Definition: exceptions.h:713
#define STATS_ENTER(id)
Definition: stats.h:141
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1085
uint8_t * PBYTE
Definition: intro_types.h:47
DWORD BlockSize
Definition: wddefs.h:411
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
#define memzero(a, s)
Definition: introcrt.h:35
#define PT_P
Definition: pgtable.h:83
INTSTATUS IntGpaCacheFetchAndAdd(PGPA_CACHE Cache, QWORD Gpa, DWORD Size, PBYTE Buffer)
Fetch data from a cached entry, or add it to the cache, of not already present.
Definition: gpacache.c:508
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:286
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:106
QWORD Current
The currently used options.
Definition: guests.h:232
struct _EVENT_INTEGRITY_VIOLATION::@295 Victim
void * GpaCache
The currently used GPA cache.
Definition: guests.h:399
QWORD VirtualAddress
The guest virtual address which was modified.
Definition: intro_types.h:1481
#define TRUE
Definition: intro_types.h:30
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1452
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
Definition: guests.h:289
#define TRACE(fmt,...)
Definition: glue.h:58
DWORD NameHash
The hash of the modified object.
Definition: exceptions.h:808
#define TIMER_FRIENDLY
Definition: introdefs.h:83
void IntExceptKernelLogInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a kernel-mode violation and dumps the code-blocks.
Kernel-mode exception.
Definition: exceptions.h:62
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:363
INTRO_OBJECT_TYPE Type
The type of the modified object.
Definition: exceptions.h:806
ZONE_TYPE ZoneType
The type of the modified zone.
Definition: exceptions.h:851
INTSTATUS IntTranslateVirtualAddressEx(QWORD Gva, QWORD Cr3, DWORD Flags, VA_TRANSLATION *Translation)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1863
INTRO_EXEC_CONTEXT ExecContext
Information about the instruction that triggered the alert.
Definition: intro_types.h:1191
void * TokenHook
Hook object for the ept hook over nt!_TOKEN Privileges field.
Definition: winprocess.h:302
INTSTATUS IntWinTokenPrivsProtectOnProcess(WIN_PROCESS_OBJECT *Process)
Updates the stored original Privileges bitfields (Present and Enabled) and hooks through EPT the Priv...
Definition: wintoken.c:1008
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:98
INTSTATUS IntHookGvaRemoveHook(HOOK_GVA **Hook, DWORD Flags)
Remove a GVA hook.
Definition: hook_gva.c:507
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:636
#define PAGE_SIZE
Definition: common.h:53
Describes the modified zone.
Definition: exceptions.h:847
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
#define TRFLG_PG_MODE
Obtains the translation mode flag for the currently used paging mode.
Definition: introcore.h:92
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:726
WCHAR Name[ALERT_PATH_MAX_LEN]
NULL-terminated string with a human readable description of the modified object.
Definition: intro_types.h:1464
uint32_t DWORD
Definition: intro_types.h:49
QWORD OriginalTokenPtr
Original Token pointer inside EPROCESS (should never change).
Definition: winprocess.h:241
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:879
enum _INTRO_ACTION INTRO_ACTION
Event actions.
QWORD OldValue[8]
The original value. Only the first Size bytes are valid.
Definition: intro_types.h:894
INTRO_WRITE_INFO WriteInfo
The original and the new value.
Definition: intro_types.h:1477
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
Definition: introcore.c:2134
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:370
BOOLEAN IntWinTokenPtrIsStolen(WIN_PROCESS_OBJECT *Process, BOOLEAN Check, WIN_PROCESS_OBJECT **FromProcess, QWORD *OldValue, QWORD *NewValue)
This function checks if the security token of a given process has been stone from another process...
Definition: wintoken.c:510
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:88
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:635
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
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
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
Definition: introcore.c:627
static void IntWinTokenPrivsSendEptAlert(EXCEPTION_KM_ORIGINATOR *Originator, EXCEPTION_VICTIM_ZONE *Victim, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an EVENT_EPT_VIOLATION for a token privileges violation.
Definition: wintoken.c:64
INTSTATUS IntWinTokenUnprotectPrivs(void)
Unprotects all the currently protected tokens belonging to processes against privileges manipulation...
Definition: wintoken.c:1135
void * Process
The internal structure of the modified process.
Definition: exceptions.h:835
EVENT_INTEGRITY_VIOLATION Integrity
Definition: alerts.h:23
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1083
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
Definition: introstatus.h:434
QWORD BaseAddress
The guest virtual address at which the monitored integrity region starts.
Definition: intro_types.h:1479
struct _EVENT_INTEGRITY_VIOLATION::@294 Originator
#define INT_STATUS_NOT_INITIALIZED_HINT
Definition: introstatus.h:320
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
INTRO_PROCESS Process
The module to which the current code return to.
Definition: intro_types.h:1457
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1086
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
#define INTRO_OPT_PROT_KM_TOKEN_PRIVS
Enable protection over Token Privileges bitmaps.
Definition: intro_types.h:489
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
Sent for integrity violation alerts. See EVENT_INTEGRITY_VIOLATION.
Definition: intro_types.h:92
Event structure for EPT violations.
Definition: intro_types.h:1104
INTSTATUS IntWinTokenCheckCurrentPrivileges(WIN_PROCESS_OBJECT *Process, QWORD TokenPtr, BOOLEAN *PresentIncreased, BOOLEAN *EnabledIncreased, QWORD *Present, QWORD *Enabled)
Verifies the current token if the current Privileges.Present and Privileges.Enabled fields were not a...
Definition: wintoken.c:696
INTSTATUS IntWinTokenPrivsCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the privileges bitfields for the given process have been changed in a malicio...
Definition: wintoken.c:818
struct _EXCEPTION_KM_ORIGINATOR::@62 Return
static INTSTATUS IntWinTokenProtectPrivsInternal(WIN_PROCESS_OBJECT *Process, QWORD NewTokenPtr)
If needed, this function will establish an EPT hook on the given token pointer for privileges protect...
Definition: wintoken.c:267
Access Token pointer.
Definition: intro_types.h:247
Write-access hook.
Definition: glueiface.h:299
#define PAGE_MASK
Definition: pgtable.h:35
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:698
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:267
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:3317
DWORD NameHash
The namehash of the originator return driver.
Definition: exceptions.h:901
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:81
#define VICTIM_TOKEN_PRIVILEGES
Printable name used for introObjectTypeTokenPrivs objects.
Definition: intro_types.h:687
INTSTATUS IntWinTokenProtectPrivs(void)
Protects all the currently unprotected tokens belonging to processes against privileges manipulation...
Definition: wintoken.c:1094
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68