Bitdefender Hypervisor Memory Introspection
windpi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "windpi.h"
6 #include "alerts.h"
7 #include "winprocesshp.h"
8 #include "winselfmap.h"
9 #include "winstack.h"
10 #include "winthread.h"
11 #include "wintoken.h"
12 #include "shellcode.h"
13 #include "winsecdesc.h"
14 
24 
25 
47 typedef INTSTATUS
49  _In_ WIN_PROCESS_OBJECT *Child,
50  _In_ WIN_PROCESS_OBJECT *RealParent,
51  _Out_ WIN_PROCESS_OBJECT **Originator,
52  _Out_ WIN_PROCESS_OBJECT **Victim,
54  );
55 
56 
58 static MITRE_ID
61  )
69 {
70  // In theory, we could have multiple DPI flags set (Stolen
71  // Token + Debug Flag - for example). In this case we are
72  // going to pick the most dangerous type of attack.
73 
75  {
76  return idAccessToken;
77  }
78 
80  {
81  return idAccessToken;
82  }
83 
85  {
86  return idExploitClientExec;
87  }
88 
90  {
91  return idTrustedDevUtil;
92  }
93 
95  {
96  return idExploitClientExec;
97  }
98 
100  {
101  return idExploitClientExec;
102  }
103 
104  if (INT_PC_VIOLATION_DPI_SEC_DESC & Flags)
105  {
106  return idAccessToken;
107  }
108 
109  if (INT_PC_VIOLATION_DPI_ACL_EDIT & Flags)
110  {
111  return idAccessToken;
112  }
113 
114  LOG("[ERROR] We do not have any known DPI flag set -> Flags:0x%x\n", Flags);
115  return 0;
116 }
117 
118 
119 static INTSTATUS
121  _In_ WIN_PROCESS_OBJECT *VictimProc,
122  _In_ WIN_PROCESS_OBJECT *OriginatorProc,
123  _In_ INTRO_ACTION Action,
124  _In_ INTRO_ACTION_REASON Reason,
126  )
138 {
139  INTSTATUS status;
141  DPI_EXTRA_INFO *extraInfo;
142 
143  pEvent = &gAlert.ProcessCreation;
144  memzero(pEvent, sizeof(*pEvent));
145 
146  pEvent->Header.Action = Action;
147  pEvent->Header.Reason = Reason;
148  pEvent->Header.MitreID = idExecApi;
149 
150  pEvent->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_PREVENT_CHILD_CREATION, VictimProc, Reason, 0);
151 
153 
155  &pEvent->Header.CurrentProcess);
156 
158 
159  IntAlertFillWinProcess(VictimProc, &pEvent->Victim);
160  IntAlertFillWinProcess(OriginatorProc, &pEvent->Originator);
161 
162  pEvent->PcType = PcType;
163  if (pEvent->PcType)
164  {
165  pEvent->Header.MitreID = IntWinDpiGetDpiMitreId(pEvent->PcType);
166  }
167 
168  if (pEvent->PcType == INT_PC_VIOLATION_DPI_DEBUG_FLAG ||
171  {
172  extraInfo = &VictimProc->DpiExtraInfo;
173  }
174  else
175  {
176  extraInfo = &OriginatorProc->DpiExtraInfo;
177  }
178 
179  IntAlertFillDpiExtraInfo(extraInfo, pEvent->PcType, VictimProc, &pEvent->DpiExtraInfo);
180 
181  status = IntNotifyIntroEvent(introEventProcessCreationViolation, pEvent, sizeof(*pEvent));
182  if (!INT_SUCCESS(status))
183  {
184  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
185  }
186 
187  return INT_STATUS_SUCCESS;
188 }
189 
190 
191 static __forceinline BOOLEAN
193  _In_ WIN_PROCESS_OBJECT const *First,
194  _In_ WIN_PROCESS_OBJECT const *Second)
195 {
196  if (memcmp(First->Name, Second->Name, IMAGE_BASE_NAME_LEN) == 0)
197  {
198  return First->MainModuleAddress == Second->MainModuleAddress;
199  }
200 
201  return FALSE;
202 }
203 
204 
205 static INTSTATUS
207  _In_ WIN_PROCESS_OBJECT *Child,
208  _In_ WIN_PROCESS_OBJECT *RealParent,
209  _Out_ WIN_PROCESS_OBJECT **Originator,
210  _Out_ WIN_PROCESS_OBJECT **Victim,
212  )
227 {
228  *Originator = NULL;
229  *Victim = NULL;
230  *PcType = 0;
231 
232  if (!(RealParent->ProtectionMask & PROC_OPT_PROT_PREVENT_CHILD_CREATION))
233  {
235  }
236 
237  if (IntWinDpiIsSelf(Child, RealParent))
238  {
240  }
241 
242  *Originator = Child;
243  *Victim = RealParent;
244  *PcType = 0;
245 
246  return INT_STATUS_SUCCESS;
247 }
248 
249 
250 static INTSTATUS
252  _In_ WIN_PROCESS_OBJECT *Child,
253  _In_ WIN_PROCESS_OBJECT *RealParent,
254  _Out_ WIN_PROCESS_OBJECT **Originator,
255  _Out_ WIN_PROCESS_OBJECT **Victim,
257  )
271 {
272  *Originator = NULL;
273  *Victim = NULL;
274  *PcType = 0;
275 
277  {
279  }
280 
281  if (!Child->CreationInfo.TokenStolenFromEprocess)
282  {
284  }
285 
286  *Originator = Child;
287  *Victim = RealParent;
289 
290  return INT_STATUS_SUCCESS;
291 }
292 
293 
294 static INTSTATUS
296  _In_ WIN_PROCESS_OBJECT *Child,
297  _In_ WIN_PROCESS_OBJECT *RealParent,
298  _Out_ WIN_PROCESS_OBJECT **Originator,
299  _Out_ WIN_PROCESS_OBJECT **Victim,
301  )
316 {
317  *Originator = NULL;
318  *Victim = NULL;
319  *PcType = 0;
320 
322  {
324  }
325 
326  if (!Child->CreationInfo.ParentHasTokenPrivsAltered)
327  {
329  }
330 
331  // Here there might be two possible cases:
332  // a) The parent has been exploited and, after a LPE, has been put to create some new malicious process.
333  // b) The parent has run an exploit in order to gain increased privileges and now runs new processes
334  // which normally it should not run.
335  // As a) seems the most likely scenario in the wild, we'll let it this way.
336  *Originator = Child;
337  *Victim = RealParent;
339 
340  return INT_STATUS_SUCCESS;
341 }
342 
343 
344 static INTSTATUS
346  _In_ WIN_PROCESS_OBJECT *Child,
347  _In_ WIN_PROCESS_OBJECT *RealParent,
348  _Out_ WIN_PROCESS_OBJECT **Originator,
349  _Out_ WIN_PROCESS_OBJECT **Victim,
351  )
366 {
367  *Originator = NULL;
368  *Victim = NULL;
369  *PcType = 0;
370 
372  {
374  }
375 
376  if (!Child->CreationInfo.ParentHasAlteredSecDescPtr)
377  {
379  }
380 
381  // We are going to consider that the child process is the originator (after a successful exploit, the parent process
382  // will attempt to launch a "payload" process).
383  *Originator = Child;
384  *Victim = RealParent;
386 
387  return INT_STATUS_SUCCESS;
388 }
389 
390 
391 static INTSTATUS
393  _In_ WIN_PROCESS_OBJECT *Child,
394  _In_ WIN_PROCESS_OBJECT *RealParent,
395  _Out_ WIN_PROCESS_OBJECT **Originator,
396  _Out_ WIN_PROCESS_OBJECT **Victim,
398  )
413 {
414  *Originator = NULL;
415  *Victim = NULL;
416  *PcType = 0;
417 
419  {
421  }
422 
423  if (!Child->CreationInfo.ParentHasEditedAcl)
424  {
426  }
427 
428  // We are going to consider that the child process is the originator (after a successful exploit, the parent process
429  // will attempt to launch a "payload" process).
430  *Originator = Child;
431  *Victim = RealParent;
433 
434  return INT_STATUS_SUCCESS;
435 }
436 
437 
438 static INTSTATUS
440  _In_ WIN_PROCESS_OBJECT *Child,
441  _In_ WIN_PROCESS_OBJECT *RealParent,
442  _Out_ WIN_PROCESS_OBJECT **Originator,
443  _Out_ WIN_PROCESS_OBJECT **Victim,
445  )
459 {
460  *Originator = NULL;
461  *Victim = NULL;
462  *PcType = 0;
463 
465  {
467  }
468 
469  if (!Child->CreationInfo.ParentHasPivotedStack)
470  {
472  }
473 
474  if (IntWinDpiIsSelf(Child, RealParent))
475  {
477  }
478 
479  // The real parent is most likely the victim here as it has the stack pivoted, but this may not always
480  // mean that it is without sin, as it can end up in this way after a process hollow (in which case
481  // the _IntWinProcIsSelf check from above should be removed)
482  *Originator = Child;
483  *Victim = RealParent;
485 
486  return INT_STATUS_SUCCESS;
487 }
488 
489 
490 static INTSTATUS
492  _In_ WIN_PROCESS_OBJECT *Child,
493  _In_ WIN_PROCESS_OBJECT *RealParent,
494  _Out_ WIN_PROCESS_OBJECT **Originator,
495  _Out_ WIN_PROCESS_OBJECT **Victim,
497  )
511 {
512  *Originator = NULL;
513  *Victim = NULL;
514  *PcType = 0;
515 
517  {
519  }
520 
521  if (!Child->CreationInfo.DebuggerEprocess)
522  {
524  }
525 
526  if (IntWinDpiIsSelf(Child, RealParent))
527  {
529  }
530 
531  *Originator = RealParent;
532  *Victim = Child;
534 
535  return INT_STATUS_SUCCESS;
536 }
537 
538 
539 static INTSTATUS
541  _In_ WIN_PROCESS_OBJECT *Child,
542  _In_ WIN_PROCESS_OBJECT *RealParent,
543  _Out_ WIN_PROCESS_OBJECT **Originator,
544  _Out_ WIN_PROCESS_OBJECT **Victim,
546  )
560 {
561  *Originator = NULL;
562  *Victim = NULL;
563  *PcType = 0;
564 
566  {
568  }
569 
570  if (!Child->CreationInfo.ParentHasBeenHeapSprayed)
571  {
573  }
574 
575  // It's the same as in the case of pivoted stack.
576  *Originator = Child;
577  *Victim = RealParent;
579 
580  return INT_STATUS_SUCCESS;
581 }
582 
583 
584 static INTSTATUS
586  _In_ WIN_PROCESS_OBJECT *Child,
587  _In_ WIN_PROCESS_OBJECT *RealParent,
588  _Out_ WIN_PROCESS_OBJECT **Originator,
589  _Out_ WIN_PROCESS_OBJECT **Victim,
591  )
605 {
606  *Originator = NULL;
607  *Victim = NULL;
608  *PcType = 0;
609 
611  {
613  }
614 
615  if (!Child->CreationInfo.ParentThreadSuspicious)
616  {
618  }
619 
620  // It's the same as in the case of pivoted stack.
621  *Originator = Child;
622  *Victim = RealParent;
624 
625  return INT_STATUS_SUCCESS;
626 }
627 
628 
629 static QWORD
632  _In_ WIN_PROCESS_OBJECT *Originator,
633  _In_ WIN_PROCESS_OBJECT *Victim
634  )
646 {
647  UNREFERENCED_PARAMETER(Victim);
648 
649  if (PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
650  {
651  WORD maxNumberOfHeapVals = 0;
652  DWORD maxPageHeapVals = 0;
653 
654  for (DWORD val = 0x1; val < HEAP_SPRAY_NR_PAGES; val++)
655  {
656  QWORD heapVal = (val << 24) | (val << 16) | (val << 8) | val;
657 
658  if (Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
659  {
660  return (heapVal & PAGE_MASK) + Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset;
661  }
662 
663  if (Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount >= maxNumberOfHeapVals &&
664  Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
665  {
666  maxNumberOfHeapVals = (WORD)Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
667  maxPageHeapVals = heapVal & PAGE_MASK;
668  }
669  }
670 
671  // If nothing was detected, there should be a page containing heap values.
672  return maxPageHeapVals;
673  }
674  else if (PcType == INT_PC_VIOLATION_DPI_THREAD_START)
675  {
676  return Originator->DpiExtraInfo.DpiThreadStartExtraInfo.StartAddress;
677  }
678 
679  return 0;
680 }
681 
682 
683 void
686  _In_ WIN_PROCESS_OBJECT *Originator,
687  _In_ WIN_PROCESS_OBJECT *Victim,
688  _Inout_ INTRO_ACTION *Action,
690  )
709 {
710  QWORD scflags = 0;
711 
712  UNREFERENCED_PARAMETER(Victim);
713 
714  switch (PcType)
715  {
717  // Since we will break on the first page which is detected through shemu, we won't keep a per-page
718  // shellcode flags, but rather the flags of the first detected page.
719  scflags = Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.ShellcodeFlags;
720  break;
722  scflags = Originator->DpiExtraInfo.DpiThreadStartExtraInfo.ShellcodeFlags;
723  break;
724  default:
725  return;
726  }
727 
728  // The detection may have been given due to something else (e.g. on heap spray due to heap vals).
729  if (scflags == 0)
730  {
731  return;
732  }
733 
734  // Shellcode flags (as set by the shellcode emulator) may be overriden via CAMI. A flag marked for feedback
735  // will cause the alert to be logged & sent, but no actual detection will appear. Note that we force feedback
736  // for shellcode flags if and only if all the reported flags are marked as feedback. If there is a single
737  // shellcode flag set that is not feedback, a normal detection will be generated.
738  if ((scflags & gGuest.ShemuOptions.Feedback) != 0 &&
739  (scflags & ~gGuest.ShemuOptions.Feedback) == 0)
740  {
741  LOG("Current scflags 0x%016llx shemu feedback 0x%016llx, will force feedback!\n", scflags, gGuest.ShemuOptions.Feedback);
742  *Action = introGuestAllowed;
743  *Reason = introReasonAllowedFeedback;
744  }
745 }
746 
747 
750  _In_ WIN_PROCESS_OBJECT *Child,
751  _In_ WIN_PROCESS_OBJECT *RealParent
752  )
767 {
768  INTRO_ACTION retAction = introGuestAllowed;
769 
770  // The order here matters:
771  // 1. Check for creations that violate the PROC_OPT_PROT_PREVENT_CHILD_CREATION flag because if that one is
772  // set it means that someone asked us to block process creations from a specific process
773  // 2. Check for stolen tokens
774  // 3. Check for token privileges altered in a malicious way.
775  // 4. Check for pivoted stack
776  // 5. Check for a debug flag
777  // 6. Check for a heap spray
778  // 7. Check if a thread was created on a zone considered suspicious
779  // 8. Check for altered security descriptor
780  // 9. Check for edited ACL (SACL/DACL)
781  // The first check that generates an alert sends it and we don't do the other checks (unless in beta/feedback only,
782  // when we want to see everything)
784  {
794  };
795 
796  for (DWORD i = 0; i < ARRAYSIZE(handlers); i++)
797  {
798  PFUNC_IntWinDpiProcessCreationHandler handler = handlers[i];
799  INTSTATUS status;
800  EXCEPTION_UM_ORIGINATOR originator = { 0 };
801  EXCEPTION_VICTIM_ZONE victim = { 0 };
802  WIN_PROCESS_OBJECT *procOrig = NULL;
803  WIN_PROCESS_OBJECT *procVictim = NULL;
804  INTRO_ACTION action;
805  INTRO_ACTION_REASON reason;
807  QWORD protFlag;
808  QWORD address;
809 
810  action = introGuestNotAllowed;
811  reason = introReasonInternalError;
812 
813  status = handler(Child, RealParent, &procOrig, &procVictim, &pcType);
814  if (!INT_SUCCESS(status))
815  {
816  ERROR("[ERROR] Process creation violation callback %d failed: 0x%08x\n", i, status);
817  continue;
818  }
819  else if (INT_STATUS_NOT_NEEDED_HINT == status)
820  {
821  // This handler does not apply in this case, go to the next one
822  continue;
823  }
824 
825  address = IntWinDpiGetViolationAddress(pcType, procOrig, procVictim);
826 
827  status = IntExceptUserGetOriginator(procOrig, FALSE, address, NULL, &originator);
828  if (!INT_SUCCESS(status))
829  {
830  ERROR("[ERROR] IntExceptUserGetOriginator failed: 0x%08x\n", status);
831  goto _send_alert;
832  }
833 
834  status = IntExceptGetVictimProcessCreation(procVictim,
837  &victim);
838  if (!INT_SUCCESS(status))
839  {
840  ERROR("[ERROR] IntExceptGetVictimProcessCreation failed: 0x%08x\n", status);
841  goto _send_alert;
842  }
843 
844  originator.PcType = pcType;
845 
846  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventProcessCreationViolation);
847 
848 _send_alert:
850 
851  IntWinDpiForceFeedbackIfNeeded(pcType, procOrig, procVictim, &action, &reason);
852 
853  if (IntPolicyCoreTakeAction(protFlag, &action, &reason))
854  {
855  status = IntWinDpiSendProcessCreationViolation(procVictim, procOrig, action, reason, pcType);
856  if (!INT_SUCCESS(status))
857  {
858  ERROR("[ERROR] IntWinProcSendProcessCreationViolation failed with status: 0x%08x.\n", status);
859  }
860 
861  IntPolicyCoreForceBetaIfNeeded(protFlag, &action);
862  }
863 
864  // Keep the highest action as the final action
865  retAction = MAX(retAction, action);
866  if (introGuestNotAllowed == action &&
867  reason != introReasonAllowedFeedback) // We want to keep going if this is a feedback only alert
868  {
869  break;
870  }
871  }
872 
873  return retAction;
874 }
875 
876 
877 static INTSTATUS
879  _Inout_ WIN_PROCESS_OBJECT *Process,
880  _In_ QWORD DebugHandle
881  )
903 {
904  INTSTATUS status;
905  QWORD currentThread = 0;
906  QWORD attachedEprocess = 0;
907  QWORD flags = 0;
908  QWORD debugPort = 0;
909  WIN_PROCESS_OBJECT *attachedProc = NULL;
910 
911  // From IDA: if the fifth parameter (or fourth on windows 7) is a valid handle, then the current process
912  // is debugged by the caller to PspInsertProcess (which will be the Real Parent Process in this case).
913  if (DebugHandle)
914  {
915  // The debugger is the real parent process.
916  Process->CreationInfo.DebuggerEprocess = Process->RealParentEprocess;
917  return INT_STATUS_SUCCESS;
918  }
919 
920  status = IntWinThrGetCurrentThread(gVcpu->Index, &currentThread);
921  if (!INT_SUCCESS(status))
922  {
923  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
924  return status;
925  }
926 
927  status = IntKernVirtMemRead(currentThread + WIN_KM_FIELD(Thread, AttachedProcess),
929  &attachedEprocess,
930  NULL);
931  if (!INT_SUCCESS(status))
932  {
933  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
934  return status;
935  }
936 
937  status = IntKernVirtMemRead(attachedEprocess + WIN_KM_FIELD(Process, Flags),
939  &flags,
940  NULL);
941  if (!INT_SUCCESS(status))
942  {
943  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
944  return status;
945  }
946 
947  status = IntKernVirtMemRead(attachedEprocess + WIN_KM_FIELD(Process, DebugPort),
949  &debugPort,
950  NULL);
951  if (!INT_SUCCESS(status))
952  {
953  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
954  return status;
955  }
956 
957  attachedProc = IntWinProcFindObjectByEprocess(attachedEprocess);
958  if (NULL == attachedProc)
959  {
960  ERROR("[ERROR] Attached process with EPROCESS: 0x%016llx is NULL!\n", attachedEprocess);
961  return INT_STATUS_NOT_FOUND;
962  }
963 
964  // From IDA: If the attached process has the NoInheritDebug flag NOT set (flag 2) and has a debug port object set,
965  // then the process inherits the debug port object from the attached process. In this case, the debugger for the
966  // current process is identical to the debugger of the attached process.
967  if (debugPort && (flags & WIN_KM_FIELD(EprocessFlags, NoDebugInherit)) == 0)
968  {
969  // The debugger is the attached process's debugger.
970  Process->CreationInfo.DebuggerEprocess = attachedProc->CreationInfo.DebuggerEprocess;
971  }
972 
973  return INT_STATUS_SUCCESS;
974 }
975 
976 
977 static INTSTATUS
979  _In_ WIN_PROCESS_OBJECT *Process,
980  _In_opt_ WIN_PROCESS_OBJECT *RealParent
981  )
990 {
991  INTSTATUS status = INT_STATUS_SUCCESS;
992  QWORD userRsp = 0;
993  DWORD segCs = 0;
994  BOOLEAN fallback = TRUE;
995  BOOLEAN isPivotedWow64 = FALSE;
996 
997  // We only fallback to stack-parsing for trap frame if the current process is not a
998  // system one and his parent is not the System process.
999  if (RealParent)
1000  {
1001  fallback = !Process->SystemProcess && RealParent->Pid != 4;
1002  }
1003 
1004  status = IntWinStackUserTrapFrameGetGeneric(&userRsp, &segCs, fallback, &Process->DpiExtraInfo);
1005  if (!INT_SUCCESS(status))
1006  {
1007  // If we fail to get the TrapFrame for a system process creation or when the parent has pid 4
1008  // or we choose to skip the check operation for another reason
1009  // we will consider that the stack isn't pivoted
1010  if (!fallback || INT_STATUS_NOT_NEEDED_HINT == status)
1011  {
1012  Process->CreationInfo.ParentHasPivotedStack = FALSE;
1013 
1014  status = INT_STATUS_SUCCESS;
1015  }
1016  else
1017  {
1018  ERROR("[ERROR] IntWinStackUserTrapFrameGetGeneric failed: 0x%08x\n", status);
1019  }
1020 
1021  return status;
1022  }
1023  else if (INT_STATUS_NOT_NEEDED_HINT == status)
1024  {
1025  return status;
1026  }
1027 
1028  if (NULL != RealParent && RealParent->Wow64Process)
1029  {
1030  status = IntWinStackWow64CheckIsPivoted(Process, RealParent, &Process->DpiExtraInfo);
1031  if (!INT_SUCCESS(status))
1032  {
1033  ERROR("[ERROR] IntWinStackWow64CheckIsPivoted failed: 0x%08x\n", status);
1034  }
1035 
1036  isPivotedWow64 = Process->CreationInfo.ParentHasPivotedStack;
1037  goto _skip_check_64;
1038  }
1039 
1040  status = IntWinStackUserCheckIsPivoted(userRsp, segCs, FALSE, &Process->DpiExtraInfo,
1041  &Process->CreationInfo.ParentHasPivotedStack);
1042  if (!INT_SUCCESS(status))
1043  {
1044  ERROR("[ERROR] IntWinStackUserCheckIsPivoted failed: 0x%08x.\n", status);
1045  return status;
1046  }
1047  else if (Process->CreationInfo.ParentHasPivotedStack)
1048  {
1049  WARNING("[WARNING] Process 0x%016llx created with pivoted stack\n", Process->EprocessAddress);
1050  }
1051 
1052 _skip_check_64:
1053  Process->CreationInfo.ParentHasPivotedStack = Process->CreationInfo.ParentHasPivotedStack || isPivotedWow64;
1054 
1055  return status;
1056 }
1057 
1058 
1059 static INTSTATUS
1061  _In_ WIN_PROCESS_OBJECT *Process,
1062  _In_ WIN_PROCESS_OBJECT *Parent
1063  )
1072 {
1073  WIN_PROCESS_OBJECT *pStolenFrom;
1074 
1075  if (IntWinTokenPtrIsStolen(Parent, TRUE, &pStolenFrom, NULL, NULL))
1076  {
1077  Process->CreationInfo.TokenStolenFromEprocess = pStolenFrom->EprocessAddress;
1078  Process->DpiExtraInfo.DpiStolenTokenExtraInfo.StolenFromEprocess = pStolenFrom->EprocessAddress;
1079  }
1080 
1081  return INT_STATUS_SUCCESS;
1082 }
1083 
1084 
1085 static INTSTATUS
1087  _In_ WIN_PROCESS_OBJECT *Process,
1088  _In_ WIN_PROCESS_OBJECT *Parent
1089  )
1098 {
1099  static BYTE securityDescriptorBuffer[INTRO_SECURITY_DESCRIPTOR_SIZE];
1100  WIN_PROCESS_OBJECT *pStolenFrom = NULL;
1101  INTSTATUS status;
1102  DWORD totalSize = 0;
1103  QWORD oldValue = 0;
1104  QWORD newValue = 0;
1105  ACL *sacl = NULL;
1106  ACL *dacl = NULL;
1107 
1108  memset(securityDescriptorBuffer, 0, INTRO_SECURITY_DESCRIPTOR_SIZE);
1109 
1110  if (IntWinSDIsSecDescPtrAltered(Parent, &pStolenFrom, &oldValue, &newValue))
1111  {
1112  Process->CreationInfo.ParentHasAlteredSecDescPtr = TRUE;
1113 
1114  Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.SecDescStolenFromEproc =
1115  pStolenFrom ? pStolenFrom->EprocessAddress : 0;
1116  Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.NewPtrValue = newValue;
1117  Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.OldPtrValue = oldValue;
1118 
1119  status = IntWinSDReadSecDesc(newValue,
1121  securityDescriptorBuffer,
1122  &totalSize,
1123  &sacl,
1124  &dacl);
1125  if (INT_SUCCESS(status))
1126  {
1127  if (sacl)
1128  {
1129  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.NewSacl, sacl, sizeof(ACL));
1130  }
1131 
1132  if (dacl)
1133  {
1134  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.NewDacl, dacl, sizeof(ACL));
1135  }
1136  }
1137 
1138  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.OldSacl, &Parent->SecurityDescriptor.Sacl, sizeof(ACL));
1139  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.OldDacl, &Parent->SecurityDescriptor.Dacl, sizeof(ACL));
1140  }
1141 
1142  return INT_STATUS_SUCCESS;
1143 }
1144 
1145 
1146 static INTSTATUS
1148  _In_ WIN_PROCESS_OBJECT *Process,
1149  _In_ WIN_PROCESS_OBJECT *Parent
1150  )
1159 {
1160  static BYTE securityDescriptorBuffer[INTRO_SECURITY_DESCRIPTOR_SIZE];
1161  DWORD totalSize;
1162  ACL *sacl = NULL;
1163  ACL *dacl = NULL;
1164 
1165  memset(securityDescriptorBuffer, 0, INTRO_SECURITY_DESCRIPTOR_SIZE);
1166 
1167  if (IntWinSDIsAclEdited(Parent, INTRO_SECURITY_DESCRIPTOR_SIZE, securityDescriptorBuffer, &totalSize, &sacl, &dacl))
1168  {
1169  Process->CreationInfo.ParentHasEditedAcl = TRUE;
1170 
1171  if (sacl)
1172  {
1173  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.NewSacl, sacl, sizeof(ACL));
1174  }
1175 
1176  if (dacl)
1177  {
1178  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.NewDacl, dacl, sizeof(ACL));
1179  }
1180 
1181  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.OldSacl, &Parent->SecurityDescriptor.Sacl, sizeof(ACL));
1182  memcpy(&Parent->DpiExtraInfo.DpiSecDescAclExtraInfo.OldDacl, &Parent->SecurityDescriptor.Dacl, sizeof(ACL));
1183  }
1184 
1185  return INT_STATUS_SUCCESS;
1186 }
1187 
1188 
1189 static INTSTATUS
1191  _In_ WIN_PROCESS_OBJECT *Process,
1192  _In_ WIN_PROCESS_OBJECT *Parent
1193  )
1202 {
1203  INTSTATUS status;
1204  BOOLEAN presentIncreased = FALSE, enabledIncreased = FALSE;
1205  QWORD present = 0, enabled = 0;
1206 
1207  status = IntWinTokenCheckCurrentPrivileges(Parent,
1208  Parent->OriginalTokenPtr,
1209  FALSE,
1210  &presentIncreased,
1211  &enabledIncreased,
1212  &present,
1213  &enabled);
1214  if (!INT_SUCCESS(status))
1215  {
1217  {
1218  // Don't propagate the error, just warn it, as it is benign.
1219  WARNING("[WARNING] IntWinTokenCheckCurrentPrivileges failed: 0x%08x\n", status);
1220  return INT_STATUS_SUCCESS;
1221  }
1222 
1223  return status;
1224  }
1225 
1226  if (presentIncreased || enabledIncreased || Parent->PrivsChangeDetected)
1227  {
1228  Process->CreationInfo.ParentHasTokenPrivsAltered = TRUE;
1229 
1230  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.OldPresent = Parent->OriginalPresentPrivs;
1231  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.OldEnabled = Parent->OriginalEnabledPrivs;
1232  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.NewPresent = present;
1233  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.NewEnabled = enabled;
1234  }
1235 
1236  return INT_STATUS_SUCCESS;
1237 }
1238 
1239 
1240 static INTSTATUS
1242  _Inout_ WIN_PROCESS_OBJECT *Process,
1243  _In_ WIN_PROCESS_OBJECT *Parent
1244  )
1253 {
1254  INTSTATUS status;
1255  DWORD totalHeapValCnt = 0;
1256  DWORD totalMappedPages = 0;
1257 
1258  if (gGuest.Guest64 && !Parent->Wow64Process)
1259  {
1261  }
1262 
1263  for (DWORD val = 0x1; val <= HEAP_SPRAY_NR_PAGES; val++)
1264  {
1265  DWORD heapVal = (val << 24) | (val << 16) | (val << 8) | val;
1266  BYTE *mappedBytes;
1267  WORD heapValCnt = 0;
1268  BOOLEAN foundFirstNops = FALSE;
1269  DWORD firstNopOccurrence = 0;
1270  IG_ARCH_REGS regs = { 0 };
1271  QWORD shflags = 0;
1272  VA_TRANSLATION tr = { 0 };
1273 
1274  status = IntTranslateVirtualAddressEx(heapVal & PAGE_MASK, Parent->Cr3, 0, &tr);
1275  if (!INT_SUCCESS(status))
1276  {
1277  continue;
1278  }
1279 
1280  if (!(tr.Flags & PT_P))
1281  {
1282  continue;
1283  }
1284 
1285  // We can safely mark it as mapped at this point.
1286  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped = 1;
1287 
1288  if (!tr.IsExecutable)
1289  {
1290  continue;
1291  }
1292 
1293  status = IntVirtMemMap(heapVal & PAGE_MASK, PAGE_SIZE, Parent->Cr3, 0, &mappedBytes);
1294  if (!INT_SUCCESS(status))
1295  {
1296  continue;
1297  }
1298 
1299  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable = tr.IsExecutable;
1300 
1301  totalMappedPages++;
1302 
1303  for (DWORD i = 0; i < PAGE_SIZE; i++)
1304  {
1305  if (i % 4 == 0)
1306  {
1307  if (((DWORD *)mappedBytes)[i / 4] == heapVal)
1308  {
1309  heapValCnt++;
1310  totalHeapValCnt++;
1311  }
1312  }
1313 
1314  if (mappedBytes[i] == 0x90 && !foundFirstNops)
1315  {
1316  if (i > 0 && mappedBytes[i - 1] == 0x90)
1317  {
1318  firstNopOccurrence = i;
1319  foundFirstNops = TRUE;
1320  }
1321  }
1322  }
1323 
1324  IntVirtMemUnmap(&mappedBytes);
1325 
1326  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount = heapValCnt;
1327 
1328  // For now a sign of heap spraying is that at least a quarter of the page is filled
1329  // with the value that we mapped.
1330  if (heapValCnt >= PAGE_SIZE / 16)
1331  {
1332  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1333  break;
1334  }
1335 
1336  // At this point, if there was not any nop sequence found from where to start the emulation
1337  // the firstNopOccurrence variable will be equal to 0. We'll start the emulation from the
1338  // beginning of the page, as the shellcode might have spawned on multiple pages.
1339 
1340  regs.Rip = (heapVal & PAGE_MASK) + firstNopOccurrence;
1341  regs.Cr3 = Parent->Cr3;
1342  // Dummy value, so there would not be underflows if the stack is 0 and some instruction
1343  // accesses something on the stack, behind RSP.
1344  regs.Rsp = 0x10000;
1345 
1346  status = IntShcIsSuspiciousCode((heapVal & PAGE_MASK) + firstNopOccurrence,
1347  tr.PhysicalAddress,
1349  &regs,
1350  &shflags);
1351  if (!INT_SUCCESS(status))
1352  {
1353  ERROR("[ERROR] IntShcIsSuspiciousCode failed: 0x%08x\n", status);
1354  return status;
1355  }
1356 
1357  if (shflags != 0)
1358  {
1359  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.ShellcodeFlags = shflags;
1360  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected = 1;
1361  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset = firstNopOccurrence;
1362  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1363  // There's no point in continuing, other than statistics.
1364  break;
1365  }
1366 
1367  }
1368 
1369  // Very heuristically: if we have mapped 5 pages and we found at least 500 heap values, then we consider
1370  // it was heap sprayed.
1371  if (totalMappedPages > 5 && totalHeapValCnt > 500)
1372  {
1373  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1374  }
1375 
1376  return INT_STATUS_SUCCESS;
1377 }
1378 
1379 
1380 static INTSTATUS
1382  _Inout_ WIN_PROCESS_OBJECT *Process,
1383  _In_ WIN_PROCESS_OBJECT *Parent
1384  )
1395 {
1396  INTSTATUS status;
1397  QWORD thread = 0;
1398  QWORD startAddress = 0;
1399  IG_ARCH_REGS regs = { 0 };
1400  IG_CS_TYPE csType;
1401  QWORD gpa = 0;
1402  QWORD scflags = 0;
1403 
1404  if (Process->IsAgent)
1405  {
1407  }
1408 
1409  status = IntWinThrGetCurrentThread(gVcpu->Index, &thread);
1410  if (!INT_SUCCESS(status))
1411  {
1412  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
1413  return status;
1414  }
1415 
1416  status = IntKernVirtMemFetchWordSize(thread + WIN_KM_FIELD(Thread, Win32StartAddress), &startAddress);
1417  if (!INT_SUCCESS(status))
1418  {
1419  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
1420  return status;
1421  }
1422 
1423  status = IntTranslateVirtualAddress(startAddress, Parent->Cr3, &gpa);
1424  if (!INT_SUCCESS(status))
1425  {
1426  WARNING("[WARNING] IntTranslateVirtualAddress failed for 0x%016llx: 0x%08x\n", startAddress, status);
1427 
1428  // If the page has been swapped out, don't propagate the error.
1430  {
1431  return INT_STATUS_SUCCESS;
1432  }
1433 
1434  return status;
1435  }
1436 
1437  csType = Parent->Wow64Process || !gGuest.Guest64 ? IG_CS_TYPE_32B : IG_CS_TYPE_64B;
1438 
1439  regs.Rip = startAddress;
1440  regs.Cr3 = Parent->Cr3;
1441  // Dummy value, so there would not be underflows if the stack is 0 and some instruction
1442  // accesses something on the stack, behind RSP.
1443  regs.Rsp = 0x10000;
1444 
1445  status = IntShcIsSuspiciousCode(startAddress, gpa, csType, &regs, &scflags);
1446  if (!INT_SUCCESS(status))
1447  {
1448  ERROR("[ERROR] IntShcIsSuspiciousCode failed: 0x%08x\n", status);
1449  return status;
1450  }
1451 
1452  if (scflags != 0)
1453  {
1454  VAD vad = { 0 };
1455  QWORD vadroot = 0;
1456 
1457  // If we're in an imaged mapped vad, don't give a detection. But if we failed to get the vad, then
1458  // we won't know for sure, and better give a detection in this case.
1459  status = IntKernVirtMemFetchWordSize(Parent->EprocessAddress + WIN_KM_FIELD(Process, VadRoot), &vadroot);
1460  if (!INT_SUCCESS(status))
1461  {
1462  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
1463  goto _detect;
1464  }
1465 
1466  status = IntWinVadFetchByRange(vadroot, startAddress & PAGE_MASK, startAddress & PAGE_MASK, &vad);
1467  if (!INT_SUCCESS(status))
1468  {
1469  ERROR("[ERROR] IntWinVadFetchByRange failed: 0x%08x\n", status);
1470  goto _detect;
1471  }
1472 
1473  if (vad.VadType == VadImageMap)
1474  {
1475  goto _exit;
1476  }
1477 
1478 _detect:
1479  Process->DpiExtraInfo.DpiThreadStartExtraInfo.ShellcodeFlags = scflags;
1480  Process->DpiExtraInfo.DpiThreadStartExtraInfo.StartAddress = startAddress;
1481  Process->CreationInfo.ParentThreadSuspicious = TRUE;
1482  }
1483 
1484 _exit:
1485  return INT_STATUS_SUCCESS;
1486 }
1487 
1488 
1489 static __forceinline BOOLEAN
1491  _In_ WIN_PROCESS_OBJECT *Process,
1492  _In_ WIN_PROCESS_OBJECT *Parent
1493  )
1502 {
1503  // We'll let werfault to be created if the parent process had an exception.
1504  if (Process->NameHash == 0x56d1611d && // werfault.exe
1505  Parent->LastException != 0)
1506  {
1507  return TRUE;
1508  }
1509 
1510  // Add there any other cases on which DPI wouldn't need to be checked in the future
1511 
1512  return FALSE;
1513 }
1514 
1515 
1516 void
1518  _Inout_ WIN_PROCESS_OBJECT *Process,
1519  _In_ WIN_PROCESS_OBJECT *Parent,
1520  _In_ QWORD DebugHandle
1521  )
1530 {
1531  if (IntWinDpiIsDpiWhiteListed(Process, Parent))
1532  {
1533  return;
1534  }
1535 
1537  {
1539 
1540  INTSTATUS status = IntWinDpiGetProcessDebugFlag(Process, DebugHandle);
1541  if (!INT_SUCCESS(status))
1542  {
1543  ERROR("[ERROR] IntWinProcGetProcessDebugFlag failed: 0x%08x\n", status);
1544  }
1545 
1547  }
1548 
1550  {
1551  // We don't check the stack of the system process.
1552  if (__likely(Process->Pid != 4))
1553  {
1555 
1556  INTSTATUS status = IntWinDpiValidatePivotedStack(Process, Parent);
1557  if (!INT_SUCCESS(status))
1558  {
1559  ERROR("[ERROR] IntWinProcValidatePivotedStack failed: 0x%08x\n", status);
1560  }
1561 
1563  }
1564  }
1565 
1567  {
1569 
1570  INTSTATUS status = IntWinDpiValidateParentProcessToken(Process, Parent);
1571  if (!INT_SUCCESS(status))
1572  {
1573  ERROR("[ERROR] IntWinProcValidateCreatedProcessToken failed: 0x%08x\n", status);
1574  }
1575 
1577  }
1578 
1580  {
1582 
1583  INTSTATUS status = IntWinDpiValidateTokenPrivs(Process, Parent);
1584  if (!INT_SUCCESS(status))
1585  {
1586  ERROR("[ERROR] IntWinDpiValidateTokenPrivs failed: 0x%08x\n", status);
1587  }
1588 
1590  }
1591 
1593  {
1595 
1596  INTSTATUS status = IntWinDpiValidateHeapSpray(Process, Parent);
1597  if (!INT_SUCCESS(status))
1598  {
1599  ERROR("[ERROR] IntWinProcValidateHeapSpray failed: 0x%08x\n", status);
1600  }
1601 
1603  }
1604 
1606  {
1608 
1609  INTSTATUS status = IntWinDpiValidateThreadStart(Process, Parent);
1610  if (!INT_SUCCESS(status))
1611  {
1612  ERROR("[ERROR] IntWinDpiValidateThreadStart failed: 0x%08x\n", status);
1613  }
1614 
1616  }
1617 
1619  {
1621 
1622  INTSTATUS status = IntWinDpiValidateParentSecDesc(Process, Parent);
1623  if (!INT_SUCCESS(status))
1624  {
1625  ERROR("[ERROR] IntWinDpiValidateParentSecDesc failed: 0x%08x\n", status);
1626  }
1627 
1628  status = IntWinDpiValidateParentAclEdit(Process, Parent);
1629  if (!INT_SUCCESS(status))
1630  {
1631  ERROR("[ERROR] IntWinDpiValidateParentAcl failed: 0x%08x\n", status);
1632  }
1633 
1635  }
1636 }
void IntWinDpiForceFeedbackIfNeeded(INTRO_PC_VIOLATION_TYPE PcType, WIN_PROCESS_OBJECT *Originator, WIN_PROCESS_OBJECT *Victim, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Enforces feedback-only alert on the current DPI violation based on different rules.
Definition: windpi.c:684
#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
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
Trusted Developer Utilities.
Definition: intro_types.h:1158
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
static BOOLEAN IntWinDpiIsDpiWhiteListed(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Used to whitelist some DPI (Deep Process Inspection) corner cases.
Definition: windpi.c:1490
#define HEAP_SPRAY_NR_PAGES
Definition: windpi.h:22
Sent for unauthorized process creation alerts. See EVENT_PROCESS_CREATION_VIOLATION.
Definition: intro_types.h:115
#define INTRO_OPT_PROT_DPI_TOKEN_STEAL
Enable process creation protection for stolen token.
Definition: intro_types.h:492
Measures the security descriptor DPI protection information gathering.
Definition: stats.h:102
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
BOOLEAN IntWinSDIsAclEdited(WIN_PROCESS_OBJECT *Process, DWORD BufferSize, BYTE *SecurityDescriptorBuffer, DWORD *ReadSize, ACL **NewSacl, ACL **NewDacl)
This function reads the ACLs for the given process (returning the data using the provided buffer and ...
Definition: winsecdesc.c:916
The creation of a process was attempted while the parent had its heap sprayed.
Definition: intro_types.h:1666
INTSTATUS IntAlertFillDpiExtraInfo(DPI_EXTRA_INFO *CollectedExtraInfo, INTRO_PC_VIOLATION_TYPE PcType, WIN_PROCESS_OBJECT *VictimProcess, INTRO_DPI_EXTRA_INFO *ExtraInfo)
Fills the collected DPI extra information.
Definition: alerts.c:1371
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
INTRO_PROCESS Victim
The process that was compromised.
Definition: intro_types.h:1788
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
uint8_t BYTE
Definition: intro_types.h:47
Measures the pivoted stack DPI protection information gathering.
Definition: stats.h:87
DWORD Index
The VCPU number.
Definition: guests.h:172
#define _In_
Definition: intro_sal.h:21
#define INTRO_OPT_PROT_DPI_STACK_PIVOT
Enable process creation protection for pivoted stack.
Definition: intro_types.h:490
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
Measures the debug flag DPI protection information gathering.
Definition: stats.h:86
#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
uint16_t WORD
Definition: intro_types.h:48
Event structure for process creation violation events.
Definition: intro_types.h:1767
#define STATS_EXIT(id)
Definition: stats.h:160
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
void IntWinDpiGatherDpiInfo(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent, QWORD DebugHandle)
Gathers all the necessary DPI (Deep Process Inspection) information that will later be used to decide...
Definition: windpi.c:1517
static INTSTATUS IntWinDpiSendProcessCreationViolation(WIN_PROCESS_OBJECT *VictimProc, WIN_PROCESS_OBJECT *OriginatorProc, INTRO_ACTION Action, INTRO_ACTION_REASON Reason, INTRO_PC_VIOLATION_TYPE PcType)
Send a process creation violation event.
Definition: windpi.c:120
User-mode exception.
Definition: exceptions.h:60
enum _MITRE_ID MITRE_ID
Mitre attack techniques.
Process creation violation.
Definition: intro_types.h:262
struct _WIN_PROCESS_OBJECT::@232 CreationInfo
QWORD Feedback
Options that will be forced to feedback only mode.
Definition: guests.h:255
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
INTSTATUS IntWinThrGetCurrentThread(DWORD CpuNumber, QWORD *EthreadAddress)
Get the ETHREAD structure address of the thread currently running on the given CPU.
Definition: winthread.c:26
#define INTRO_SECURITY_DESCRIPTOR_SIZE
The size of the buffers in which we store the security descriptors. The security descriptor is compos...
Definition: intro_types.h:740
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
INTSTATUS IntExceptGetVictimProcessCreation(void *Process, INTRO_OBJECT_TYPE ObjectType, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim for process-creation violation...
static INTSTATUS IntWinDpiValidatePivotedStack(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *RealParent)
Determines if the parent process has a pivoted stack.
Definition: windpi.c:978
INTRO_PC_VIOLATION_TYPE
Process creation violation flags.
Definition: intro_types.h:1651
#define ARRAYSIZE(A)
Definition: introdefs.h:101
static INTSTATUS IntWinDpiHandleDpiPivotedStack(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI pivoted stack policy set by INTRO_OPT_PROT_DPI_STACK_PIVO...
Definition: windpi.c:439
INTSTATUS IntWinStackWow64CheckIsPivoted(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *RealParent, DPI_EXTRA_INFO *DpiExtraInfo)
Check whether a wow64 process&#39; stack is pivoted.
Definition: winstack.c:2203
Measures the stolen token flag DPI protection information gathering.
Definition: stats.h:88
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
Process creation violation DPI.
Definition: intro_types.h:265
#define ERROR(fmt,...)
Definition: glue.h:62
Describes a user-mode originator.
Definition: exceptions.h:994
#define INTRO_OPT_PROT_DPI
Aggregates all the deep process inspection flags.
Definition: intro_types.h:534
INTSTATUS IntShcIsSuspiciousCode(QWORD Gva, QWORD Gpa, DWORD CsType, IG_ARCH_REGS *Registers, QWORD *ShellcodeFlags)
Checks if the code located at the given guest virtual address is suspicious or not.
Definition: shellcode.c:25
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
static INTSTATUS IntWinDpiHandleDpiHeapSpray(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI heap spray policy set by INTRO_OPT_PROT_DPI_HEAP_SPRAY.
Definition: windpi.c:540
Measures the thread start DPI protection information gathering.
Definition: stats.h:91
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
static INTSTATUS IntWinDpiHandleDpiTokenPrivs(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI token privileges policy set by INTRO_OPT_PROT_DPI_TOKEN_P...
Definition: windpi.c:295
BOOLEAN IsExecutable
True if this page is executable.
Definition: introcore.h:136
QWORD DebuggerEprocess
This will keep the EPROCESS of the debugger process (if any).
Definition: winprocess.h:284
Measures the heap spray DPI protection information gathering.
Definition: stats.h:89
EVENT_PROCESS_CREATION_VIOLATION ProcessCreation
Definition: alerts.h:31
#define IMAGE_BASE_NAME_LEN
The maximum length of a process name.
Definition: winguest.h:15
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
INTRO_PC_VIOLATION_TYPE PcType
Valid if the current violation is DPI Process Creation Violation.
Definition: exceptions.h:1041
#define INTRO_OPT_PROT_DPI_TOKEN_PRIVS
Enable process creation protection for parent which has violated Token privileges constraints...
Definition: intro_types.h:507
An access control list.
Definition: wddefs.h:637
#define LOG(fmt,...)
Definition: glue.h:61
32-bit selector.
Definition: glueiface.h:187
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
IG_CS_TYPE
The type of the code segment.
Definition: glueiface.h:183
Execution through API call.
Definition: intro_types.h:1151
Access Token Manipulation.
Definition: intro_types.h:1153
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
Exposes the functions used to provide Windows Threads related support.
static INTSTATUS IntWinDpiHandleDpiThreadStart(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation was triggered from a thread which started executing suspicious code...
Definition: windpi.c:585
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
static MITRE_ID IntWinDpiGetDpiMitreId(INTRO_PC_VIOLATION_TYPE Flags)
Get the MITRE attack technique ID for the given DPI (Deep Process Inspection) flags.
Definition: windpi.c:59
#define _Inout_
Definition: intro_sal.h:20
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1769
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
BOOLEAN IntWinSDIsSecDescPtrAltered(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT **VictimProcess, QWORD *OldValue, QWORD *NewValue)
This function checks if the security descriptor pointer of a process has been altered or not...
Definition: winsecdesc.c:829
#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
static INTSTATUS IntWinDpiValidateHeapSpray(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the parent process has been heap sprayed.
Definition: windpi.c:1241
The parent of a process has a stolen access token when it created the child.
Definition: intro_types.h:1663
#define memzero(a, s)
Definition: introcrt.h:35
#define PT_P
Definition: pgtable.h:83
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
QWORD Current
The currently used options.
Definition: guests.h:236
static INTSTATUS IntWinDpiHandleDpiAclEdit(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI security descriptor policy set by INTRO_OPT_PROT_DPI_SD_A...
Definition: windpi.c:392
static INTSTATUS IntWinDpiHandleDpiSecDesc(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI security descriptor policy set by INTRO_OPT_PROT_DPI_SD_A...
Definition: windpi.c:345
static INTSTATUS IntWinDpiValidateParentAclEdit(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the parent process has a an altered ACL (SACL/DACL).
Definition: windpi.c:1147
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:625
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1999
The creation of a process was attempted with token privileges altered in a malicious way...
Definition: intro_types.h:1669
#define TRUE
Definition: intro_types.h:30
The parent of a process had a pivoted stack when it created the child.
Definition: intro_types.h:1660
static INTSTATUS IntWinDpiValidateTokenPrivs(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the parent process token privileges have not been altered in a malicious way...
Definition: windpi.c:1190
static INTSTATUS IntWinDpiHandleDpiDebug(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI debug flag policy set by INTRO_OPT_PROT_DPI_DEBUG.
Definition: windpi.c:491
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:367
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
VAD_TYPE VadType
The type of the VAD.
Definition: winvad.h:118
INTSTATUS IntWinTokenCheckCurrentPrivileges(WIN_PROCESS_OBJECT *Process, QWORD TokenPtr, BOOLEAN IntegrityCheck, 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:811
#define WARNING(fmt,...)
Definition: glue.h:60
static INTSTATUS IntWinDpiGetProcessDebugFlag(WIN_PROCESS_OBJECT *Process, QWORD DebugHandle)
Determines if the process is being debugged and sets the WIN_PROCESS_OBJECT.CreationInfo field debugg...
Definition: windpi.c:878
QWORD TokenStolenFromEprocess
This will keep the EPROCESS of the process from which the current process stole the token...
Definition: winprocess.h:287
INTSTATUS IntExceptUserGetOriginator(void *Process, BOOLEAN ModuleWrite, QWORD Address, INSTRUX *Instrux, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to get the information about the user-mode originator.
static INTSTATUS IntWinDpiHandleDpiStolenToken(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation breaks the DPI token steal policy set by INTRO_OPT_PROT_DPI_TOKEN_STEAL...
Definition: windpi.c:251
#define PAGE_SIZE
Definition: common.h:70
Describes the modified zone.
Definition: exceptions.h:893
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
#define INTRO_OPT_PROT_DPI_HEAP_SPRAY
Enable process creation protection for heap sprayed parent.
Definition: intro_types.h:494
#define __forceinline
Definition: introtypes.h:61
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:740
uint32_t DWORD
Definition: intro_types.h:49
INTSTATUS IntWinVadFetchByRange(QWORD VadRoot, QWORD StartPage, QWORD EndPage, VAD *Vad)
Fetches and returns a VAD object containing the range represented by [StartPage, EndPage].
Definition: winvad.c:3877
static INTSTATUS IntWinDpiHandleNormalCreationRights(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Checks if a process creation contradicts the non-DPI process creation policy set by the PROC_OPT_PROT...
Definition: windpi.c:206
static INTSTATUS IntWinDpiValidateParentProcessToken(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the child process stole the security token from any other process.
Definition: windpi.c:1060
#define PROC_OPT_PROT_PREVENT_CHILD_CREATION
Prevent the process from creating child processes (other than instances of itself).
Definition: intro_types.h:360
INTRO_PC_VIOLATION_TYPE PcType
The type of process creation violation.
Definition: intro_types.h:1813
enum _INTRO_ACTION INTRO_ACTION
Event actions.
The action was allowed, but it has the BETA flag (Introcore is in log-only mode). ...
Definition: intro_types.h:185
#define MAX(a, b)
Definition: introdefs.h:151
__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
INTSTATUS IntWinSDReadSecDesc(QWORD SecurityDescriptorGva, DWORD BufferSize, BYTE *SecurityDescriptorBuffer, DWORD *ReadSize, ACL **Sacl, ACL **Dacl)
This function reads the ACLs (along with the ACEs) from the given GVA and returns the data using the ...
Definition: winsecdesc.c:362
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:970
static INTSTATUS IntWinDpiValidateThreadStart(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the current thread from the parent process has been started in order to execute some su...
Definition: windpi.c:1381
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:90
static QWORD IntWinDpiGetViolationAddress(INTRO_PC_VIOLATION_TYPE PcType, WIN_PROCESS_OBJECT *Originator, WIN_PROCESS_OBJECT *Victim)
Gets the violation address, sent through Originator in exception mechanism.
Definition: windpi.c:630
The parent of a process tried to obtain debug privileges over the child.
Definition: intro_types.h:1657
The parent of a process has an altered security descriptor pointer.
Definition: intro_types.h:1675
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
#define INTRO_OPT_PROT_DPI_SD_ACL
Enable detection of Security Descriptor pointer modifications and ACL modifications on process creati...
Definition: intro_types.h:524
INTRO_PROCESS Originator
The process that attempted the violation.
Definition: intro_types.h:1807
static INTSTATUS IntWinDpiValidateParentSecDesc(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent)
Determines if the parent process has a an altered security descriptor pointer.
Definition: windpi.c:1086
#define INTRO_OPT_PROT_DPI_THREAD_SHELL
Examines the code where the current thread started execution when the current thread creates a proces...
Definition: intro_types.h:509
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:96
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1672
INTRO_PROT_OPTIONS ShemuOptions
Flags which describe the way shemu will give detections.
Definition: guests.h:272
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
INTRO_ACTION IntWinDpiCheckCreation(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent)
Analyzes all the process creations rules in order to decided if the process creation should be allowe...
Definition: windpi.c:749
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
Definition: introstatus.h:434
static BOOLEAN IntWinDpiIsSelf(WIN_PROCESS_OBJECT const *First, WIN_PROCESS_OBJECT const *Second)
Definition: windpi.c:192
INTRO_DPI_EXTRA_INFO DpiExtraInfo
A structure which contains extra information regarding the DPI violation that was detected...
Definition: intro_types.h:1831
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
#define __likely(x)
Definition: common.h:63
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
64-bit selector.
Definition: glueiface.h:188
#define INTRO_OPT_PROT_DPI_DEBUG
Enable process creation protection for child processes created with debug flag.
Definition: intro_types.h:488
Holds register state.
Definition: glueiface.h:30
INTSTATUS IntWinStackUserTrapFrameGetGeneric(QWORD *UserRsp, DWORD *SegCs, BOOLEAN Fallback, DPI_EXTRA_INFO *DpiExtraInfo)
Get a bit trap frame from a kernel stack.
Definition: winstack.c:2020
The parent of a process has an altered access control entry (inside SACL or DACL).
Definition: intro_types.h:1678
Exploitation for Client Execution.
Definition: intro_types.h:1157
Exposes the functions responsible for DPI (Deep Process Inspection) information gathering (used to de...
A representation of a Windows VAD structure.
Definition: winvad.h:80
#define PAGE_MASK
Definition: pgtable.h:35
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:271
INTSTATUS(* PFUNC_IntWinDpiProcessCreationHandler)(WIN_PROCESS_OBJECT *Child, WIN_PROCESS_OBJECT *RealParent, WIN_PROCESS_OBJECT **Originator, WIN_PROCESS_OBJECT **Victim, INTRO_PC_VIOLATION_TYPE *PcType)
Process creation callback, used to check if a process creation breaks one of the currently enabled po...
Definition: windpi.c:48
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
INTSTATUS IntWinStackUserCheckIsPivoted(QWORD UserRsp, DWORD SegCs, BOOLEAN IsWow64Stack, DPI_EXTRA_INFO *DpiExtraInfo, BOOLEAN *IsPivoted)
Check whether the stack is pivoted by checking if it&#39;s in the bounds of the stack base and limit from...
Definition: winstack.c:1741
Measures the token privileges DPI protection information gathering.
Definition: stats.h:90
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83