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 
23 
24 
46 typedef INTSTATUS
48  _In_ WIN_PROCESS_OBJECT *Child,
49  _In_ WIN_PROCESS_OBJECT *RealParent,
50  _Out_ WIN_PROCESS_OBJECT **Originator,
51  _Out_ WIN_PROCESS_OBJECT **Victim,
53  );
54 
55 
57 static MITRE_ID
60  )
68 {
69  // In theory, we could have multiple DPI flags set (Stolen
70  // Token + Debug Flag - for example). In this case we are
71  // going to pick the most dangerous type of attack.
72 
74  {
75  return idAccessToken;
76  }
77 
79  {
80  return idAccessToken;
81  }
82 
84  {
85  return idExploitClientExec;
86  }
87 
89  {
90  return idTrustedDevUtil;
91  }
92 
94  {
95  return idExploitClientExec;
96  }
97 
99  {
100  return idExploitClientExec;
101  }
102 
103  LOG("[ERROR] We do not have any known DPI flag set -> Flags:0x%x\n", Flags);
104  return 0;
105 }
106 
107 
108 static INTSTATUS
110  _In_ WIN_PROCESS_OBJECT *VictimProc,
111  _In_ WIN_PROCESS_OBJECT *OriginatorProc,
112  _In_ INTRO_ACTION Action,
113  _In_ INTRO_ACTION_REASON Reason,
115  )
127 {
128  INTSTATUS status;
130  DPI_EXTRA_INFO *extraInfo;
131 
132  pEvent = &gAlert.ProcessCreation;
133  memzero(pEvent, sizeof(*pEvent));
134 
135  pEvent->Header.Action = Action;
136  pEvent->Header.Reason = Reason;
137  pEvent->Header.MitreID = idExecApi;
138 
139  pEvent->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_PREVENT_CHILD_CREATION, VictimProc, Reason, 0);
140 
142 
144  &pEvent->Header.CurrentProcess);
145 
147 
148  IntAlertFillWinProcess(VictimProc, &pEvent->Victim);
149  IntAlertFillWinProcess(OriginatorProc, &pEvent->Originator);
150 
151  pEvent->PcType = PcType;
152  if (pEvent->PcType)
153  {
154  pEvent->Header.MitreID = IntWinDpiGetDpiMitreId(pEvent->PcType);
155  }
156 
158  {
159  extraInfo = &VictimProc->DpiExtraInfo;
160  }
161  else
162  {
163  extraInfo = &OriginatorProc->DpiExtraInfo;
164  }
165 
166  IntAlertFillDpiExtraInfo(extraInfo, pEvent->PcType, VictimProc, &pEvent->DpiExtraInfo);
167 
168  status = IntNotifyIntroEvent(introEventProcessCreationViolation, pEvent, sizeof(*pEvent));
169  if (!INT_SUCCESS(status))
170  {
171  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
172  }
173 
174  return INT_STATUS_SUCCESS;
175 }
176 
177 
178 static __forceinline BOOLEAN
180  _In_ WIN_PROCESS_OBJECT const *First,
181  _In_ WIN_PROCESS_OBJECT const *Second)
182 {
183  if (memcmp(First->Name, Second->Name, IMAGE_BASE_NAME_LEN) == 0)
184  {
185  return First->MainModuleAddress == Second->MainModuleAddress;
186  }
187 
188  return FALSE;
189 }
190 
191 
192 static INTSTATUS
194  _In_ WIN_PROCESS_OBJECT *Child,
195  _In_ WIN_PROCESS_OBJECT *RealParent,
196  _Out_ WIN_PROCESS_OBJECT **Originator,
197  _Out_ WIN_PROCESS_OBJECT **Victim,
199  )
214 {
215  *Originator = NULL;
216  *Victim = NULL;
217  *PcType = 0;
218 
219  if (!(RealParent->ProtectionMask & PROC_OPT_PROT_PREVENT_CHILD_CREATION))
220  {
222  }
223 
224  if (IntWinDpiIsSelf(Child, RealParent))
225  {
227  }
228 
229  *Originator = Child;
230  *Victim = RealParent;
231  *PcType = 0;
232 
233  return INT_STATUS_SUCCESS;
234 }
235 
236 
237 static INTSTATUS
239  _In_ WIN_PROCESS_OBJECT *Child,
240  _In_ WIN_PROCESS_OBJECT *RealParent,
241  _Out_ WIN_PROCESS_OBJECT **Originator,
242  _Out_ WIN_PROCESS_OBJECT **Victim,
244  )
258 {
259  *Originator = NULL;
260  *Victim = NULL;
261  *PcType = 0;
262 
264  {
266  }
267 
268  if (!Child->CreationInfo.TokenStolenFromEprocess)
269  {
271  }
272 
273  *Originator = Child;
274  *Victim = RealParent;
276 
277  return INT_STATUS_SUCCESS;
278 }
279 
280 
281 static INTSTATUS
283  _In_ WIN_PROCESS_OBJECT *Child,
284  _In_ WIN_PROCESS_OBJECT *RealParent,
285  _Out_ WIN_PROCESS_OBJECT **Originator,
286  _Out_ WIN_PROCESS_OBJECT **Victim,
302 {
303  *Originator = NULL;
304  *Victim = NULL;
305  *PcType = 0;
306 
308  {
310  }
311 
312  if (!Child->CreationInfo.ParentHasTokenPrivsAltered)
313  {
315  }
316 
317  // Here there might be two possible cases:
318  // a) The parent has been exploited and, after a LPE, has been put to create some new malicious process.
319  // b) The parent has run an exploit in order to gain increased privileges and now runs new processes
320  // which normally it should not run.
321  // As a) seems the most likely scenario in the wild, we'll let it this way.
322  *Originator = Child;
323  *Victim = RealParent;
325 
326  return INT_STATUS_SUCCESS;
327 }
328 
329 
330 static INTSTATUS
332  _In_ WIN_PROCESS_OBJECT *Child,
333  _In_ WIN_PROCESS_OBJECT *RealParent,
334  _Out_ WIN_PROCESS_OBJECT **Originator,
335  _Out_ WIN_PROCESS_OBJECT **Victim,
337  )
351 {
352  *Originator = NULL;
353  *Victim = NULL;
354  *PcType = 0;
355 
357  {
359  }
360 
361  if (!Child->CreationInfo.ParentHasPivotedStack)
362  {
364  }
365 
366  if (IntWinDpiIsSelf(Child, RealParent))
367  {
369  }
370 
371  // The real parent is most likely the victim here as it has the stack pivoted, but this may not always
372  // mean that it is without sin, as it can end up in this way after a process hollow (in which case
373  // the _IntWinProcIsSelf check from above should be removed)
374  *Originator = Child;
375  *Victim = RealParent;
377 
378  return INT_STATUS_SUCCESS;
379 }
380 
381 
382 static INTSTATUS
384  _In_ WIN_PROCESS_OBJECT *Child,
385  _In_ WIN_PROCESS_OBJECT *RealParent,
386  _Out_ WIN_PROCESS_OBJECT **Originator,
387  _Out_ WIN_PROCESS_OBJECT **Victim,
389  )
403 {
404  *Originator = NULL;
405  *Victim = NULL;
406  *PcType = 0;
407 
409  {
411  }
412 
413  if (!Child->CreationInfo.DebuggerEprocess)
414  {
416  }
417 
418  if (IntWinDpiIsSelf(Child, RealParent))
419  {
421  }
422 
423  *Originator = RealParent;
424  *Victim = Child;
426 
427  return INT_STATUS_SUCCESS;
428 }
429 
430 
431 static INTSTATUS
433  _In_ WIN_PROCESS_OBJECT *Child,
434  _In_ WIN_PROCESS_OBJECT *RealParent,
435  _Out_ WIN_PROCESS_OBJECT **Originator,
436  _Out_ WIN_PROCESS_OBJECT **Victim,
438  )
452 {
453  *Originator = NULL;
454  *Victim = NULL;
455  *PcType = 0;
456 
458  {
460  }
461 
462  if (!Child->CreationInfo.ParentHasBeenHeapSprayed)
463  {
465  }
466 
467  // It's the same as in the case of pivoted stack.
468  *Originator = Child;
469  *Victim = RealParent;
471 
472  return INT_STATUS_SUCCESS;
473 }
474 
475 
476 static INTSTATUS
478  _In_ WIN_PROCESS_OBJECT *Child,
479  _In_ WIN_PROCESS_OBJECT *RealParent,
480  _Out_ WIN_PROCESS_OBJECT **Originator,
481  _Out_ WIN_PROCESS_OBJECT **Victim,
483  )
497 {
498  *Originator = NULL;
499  *Victim = NULL;
500  *PcType = 0;
501 
503  {
505  }
506 
507  if (!Child->CreationInfo.ParentThreadSuspicious)
508  {
510  }
511 
512  // It's the same as in the case of pivoted stack.
513  *Originator = Child;
514  *Victim = RealParent;
516 
517  return INT_STATUS_SUCCESS;
518 }
519 
520 
521 static QWORD
524  _In_ WIN_PROCESS_OBJECT *Originator,
525  _In_ WIN_PROCESS_OBJECT *Victim
526  )
538 {
539  UNREFERENCED_PARAMETER(Victim);
540 
541  if (PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
542  {
543  WORD maxNumberOfHeapVals = 0;
544  DWORD maxPageHeapVals = 0;
545 
546  for (DWORD val = 0x1; val < HEAP_SPRAY_NR_PAGES; val++)
547  {
548  QWORD heapVal = (val << 24) | (val << 16) | (val << 8) | val;
549 
550  if (Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
551  {
552  return (heapVal & PAGE_MASK) + Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset;
553  }
554 
555  if (Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount >= maxNumberOfHeapVals &&
556  Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
557  {
558  maxNumberOfHeapVals = (WORD)Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
559  maxPageHeapVals = heapVal & PAGE_MASK;
560  }
561  }
562 
563  // If nothing was detected, there should be a page containing heap values.
564  return maxPageHeapVals;
565  }
566  else if (PcType == INT_PC_VIOLATION_DPI_THREAD_START)
567  {
568  return Originator->DpiExtraInfo.DpiThreadStartExtraInfo.StartAddress;
569  }
570 
571  return 0;
572 }
573 
574 
575 void
578  _In_ WIN_PROCESS_OBJECT *Originator,
579  _In_ WIN_PROCESS_OBJECT *Victim,
580  _Inout_ INTRO_ACTION *Action,
582  )
601 {
602  QWORD scflags = 0;
603 
604  UNREFERENCED_PARAMETER(Victim);
605 
606  switch (PcType)
607  {
609  // Since we will break on the first page which is detected through shemu, we won't keep a per-page
610  // shellcode flags, but rather the flags of the first detected page.
611  scflags = Originator->DpiExtraInfo.DpiHeapSprayExtraInfo.ShellcodeFlags;
612  break;
614  scflags = Originator->DpiExtraInfo.DpiThreadStartExtraInfo.ShellcodeFlags;
615  break;
616  default:
617  return;
618  }
619 
620  // The detection may have been given due to something else (e.g. on heap spray due to heap vals).
621  if (scflags == 0)
622  {
623  return;
624  }
625 
626  // Shellcode flags (as set by the shellcode emulator) may be overriden via CAMI. A flag marked for feedback
627  // will cause the alert to be logged & sent, but no actual detection will appear. Note that we force feedback
628  // for shellcode flags if and only if all the reported flags are marked as feedback. If there is a single
629  // shellcode flag set that is not feedback, a normal detection will be generated.
630  if ((scflags & gGuest.ShemuOptions.Feedback) != 0 &&
631  (scflags & ~gGuest.ShemuOptions.Feedback) == 0)
632  {
633  LOG("Current scflags 0x%016llx shemu feedback 0x%016llx, will force feedback!\n", scflags, gGuest.ShemuOptions.Feedback);
634  *Action = introGuestAllowed;
635  *Reason = introReasonAllowedFeedback;
636  }
637 }
638 
639 
642  _In_ WIN_PROCESS_OBJECT *Child,
643  _In_ WIN_PROCESS_OBJECT *RealParent
644  )
659 {
660  INTRO_ACTION retAction = introGuestAllowed;
661 
662  // The order here matters:
663  // 1. Check for creations that violate the PROC_OPT_PROT_PREVENT_CHILD_CREATION flag because if that one is
664  // set it means that someone asked us to block process creations from a specific process
665  // 2. Check for stolen tokens
666  // 3. Check for token privileges altered in a malicious way.
667  // 4. Check for pivoted stack
668  // 5. Check for a debug flag
669  // 6. Check for a heap spray
670  // 7. Check if a thread was created on a zone considered suspicious
671  // The first check that generates an alert sends it and we don't do the other checks (unless in beta/feedback only,
672  // when we want to see everything)
674  {
682  };
683 
684  for (DWORD i = 0; i < ARRAYSIZE(handlers); i++)
685  {
686  PFUNC_IntWinDpiProcessCreationHandler handler = handlers[i];
687  INTSTATUS status;
688  EXCEPTION_UM_ORIGINATOR originator = { 0 };
689  EXCEPTION_VICTIM_ZONE victim = { 0 };
690  WIN_PROCESS_OBJECT *procOrig = NULL;
691  WIN_PROCESS_OBJECT *procVictim = NULL;
692  INTRO_ACTION action;
693  INTRO_ACTION_REASON reason;
695  QWORD protFlag;
696  QWORD address;
697 
698  action = introGuestNotAllowed;
699  reason = introReasonInternalError;
700 
701  status = handler(Child, RealParent, &procOrig, &procVictim, &pcType);
702  if (!INT_SUCCESS(status))
703  {
704  ERROR("[ERROR] Process creation violation callback %d failed: 0x%08x\n", i, status);
705  continue;
706  }
707  else if (INT_STATUS_NOT_NEEDED_HINT == status)
708  {
709  // This handler does not apply in this case, go to the next one
710  continue;
711  }
712 
713  address = IntWinDpiGetViolationAddress(pcType, procOrig, procVictim);
714 
715  status = IntExceptUserGetOriginator(procOrig, FALSE, address, NULL, &originator);
716  if (!INT_SUCCESS(status))
717  {
718  ERROR("[ERROR] IntExceptUserGetOriginator failed: 0x%08x\n", status);
719  goto _send_alert;
720  }
721 
722  status = IntExceptGetVictimProcessCreation(procVictim,
725  &victim);
726  if (!INT_SUCCESS(status))
727  {
728  ERROR("[ERROR] IntExceptGetVictimProcessCreation failed: 0x%08x\n", status);
729  goto _send_alert;
730  }
731 
732  originator.PcType = pcType;
733 
734  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventProcessCreationViolation);
735 
736 _send_alert:
738 
739  IntWinDpiForceFeedbackIfNeeded(pcType, procOrig, procVictim, &action, &reason);
740 
741  if (IntPolicyCoreTakeAction(protFlag, &action, &reason))
742  {
743  status = IntWinDpiSendProcessCreationViolation(procVictim, procOrig, action, reason, pcType);
744  if (!INT_SUCCESS(status))
745  {
746  ERROR("[ERROR] IntWinProcSendProcessCreationViolation failed with status: 0x%08x.\n", status);
747  }
748 
749  IntPolicyCoreForceBetaIfNeeded(protFlag, &action);
750  }
751 
752  // Keep the highest action as the final action
753  retAction = MAX(retAction, action);
754  if (introGuestNotAllowed == action &&
755  reason != introReasonAllowedFeedback) // We want to keep going if this is a feedback only alert
756  {
757  break;
758  }
759  }
760 
761  return retAction;
762 }
763 
764 
765 static INTSTATUS
767  _Inout_ WIN_PROCESS_OBJECT *Process,
768  _In_ QWORD DebugHandle
769  )
791 {
792  INTSTATUS status;
793  QWORD currentThread = 0;
794  QWORD attachedEprocess = 0;
795  QWORD flags = 0;
796  QWORD debugPort = 0;
797  WIN_PROCESS_OBJECT *attachedProc = NULL;
798 
799  // From IDA: if the fifth parameter (or fourth on windows 7) is a valid handle, then the current process
800  // is debugged by the caller to PspInsertProcess (which will be the Real Parent Process in this case).
801  if (DebugHandle)
802  {
803  // The debugger is the real parent process.
804  Process->CreationInfo.DebuggerEprocess = Process->RealParentEprocess;
805  return INT_STATUS_SUCCESS;
806  }
807 
808  status = IntWinThrGetCurrentThread(gVcpu->Index, &currentThread);
809  if (!INT_SUCCESS(status))
810  {
811  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
812  return status;
813  }
814 
815  status = IntKernVirtMemRead(currentThread + WIN_KM_FIELD(Thread, AttachedProcess),
817  &attachedEprocess,
818  NULL);
819  if (!INT_SUCCESS(status))
820  {
821  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
822  return status;
823  }
824 
825  status = IntKernVirtMemRead(attachedEprocess + WIN_KM_FIELD(Process, Flags),
827  &flags,
828  NULL);
829  if (!INT_SUCCESS(status))
830  {
831  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
832  return status;
833  }
834 
835  status = IntKernVirtMemRead(attachedEprocess + WIN_KM_FIELD(Process, DebugPort),
837  &debugPort,
838  NULL);
839  if (!INT_SUCCESS(status))
840  {
841  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
842  return status;
843  }
844 
845  attachedProc = IntWinProcFindObjectByEprocess(attachedEprocess);
846  if (NULL == attachedProc)
847  {
848  ERROR("[ERROR] Attached process with EPROCESS: 0x%016llx is NULL!\n", attachedEprocess);
849  return INT_STATUS_NOT_FOUND;
850  }
851 
852  // From IDA: If the attached process has the NoInheritDebug flag NOT set (flag 2) and has a debug port object set,
853  // then the process inherits the debug port object from the attached process. In this case, the debugger for the
854  // current process is identical to the debugger of the attached process.
855  if (debugPort && (flags & WIN_KM_FIELD(EprocessFlags, NoDebugInherit)) == 0)
856  {
857  // The debugger is the attached process's debugger.
858  Process->CreationInfo.DebuggerEprocess = attachedProc->CreationInfo.DebuggerEprocess;
859  }
860 
861  return INT_STATUS_SUCCESS;
862 }
863 
864 
865 static INTSTATUS
867  _In_ WIN_PROCESS_OBJECT *Process,
868  _In_opt_ WIN_PROCESS_OBJECT *RealParent
869  )
878 {
879  INTSTATUS status = INT_STATUS_SUCCESS;
880  QWORD userRsp = 0;
881  DWORD segCs = 0;
882  BOOLEAN fallback = TRUE;
883  BOOLEAN isPivotedWow64 = FALSE;
884 
885  // We only fallback to stack-parsing for trap frame if the current process is not a
886  // system one and his parent is not the System process.
887  if (RealParent)
888  {
889  fallback = !Process->SystemProcess && RealParent->Pid != 4;
890  }
891 
892  status = IntWinStackUserTrapFrameGetGeneric(&userRsp, &segCs, fallback, &Process->DpiExtraInfo);
893  if (!INT_SUCCESS(status))
894  {
895  // If we fail to get the TrapFrame for a system process creation or when the parent has pid 4
896  // or we choose to skip the check operation for another reason
897  // we will consider that the stack isn't pivoted
898  if (!fallback || INT_STATUS_NOT_NEEDED_HINT == status)
899  {
900  Process->CreationInfo.ParentHasPivotedStack = FALSE;
901 
902  status = INT_STATUS_SUCCESS;
903  }
904  else
905  {
906  ERROR("[ERROR] IntWinStackUserTrapFrameGetGeneric failed: 0x%08x\n", status);
907  }
908 
909  return status;
910  }
911  else if (INT_STATUS_NOT_NEEDED_HINT == status)
912  {
913  return status;
914  }
915 
916  if (NULL != RealParent && RealParent->Wow64Process)
917  {
918  status = IntWinStackWow64CheckIsPivoted(Process, RealParent, &Process->DpiExtraInfo);
919  if (!INT_SUCCESS(status))
920  {
921  ERROR("[ERROR] IntWinStackWow64CheckIsPivoted failed: 0x%08x\n", status);
922  }
923 
924  isPivotedWow64 = Process->CreationInfo.ParentHasPivotedStack;
925  goto _skip_check_64;
926  }
927 
928  status = IntWinStackUserCheckIsPivoted(userRsp, segCs, FALSE, &Process->DpiExtraInfo,
929  &Process->CreationInfo.ParentHasPivotedStack);
930  if (!INT_SUCCESS(status))
931  {
932  ERROR("[ERROR] IntWinStackUserCheckIsPivoted failed: 0x%08x.\n", status);
933  return status;
934  }
935  else if (Process->CreationInfo.ParentHasPivotedStack)
936  {
937  WARNING("[WARNING] Process 0x%016llx created with pivoted stack\n", Process->EprocessAddress);
938  }
939 
940 _skip_check_64:
941  Process->CreationInfo.ParentHasPivotedStack = Process->CreationInfo.ParentHasPivotedStack || isPivotedWow64;
942 
943  return status;
944 }
945 
946 
947 static INTSTATUS
949  _In_ WIN_PROCESS_OBJECT *Process,
950  _In_ WIN_PROCESS_OBJECT *Parent
951  )
960 {
961  WIN_PROCESS_OBJECT *pStolenFrom;
962 
963  if (IntWinTokenPtrIsStolen(Parent, TRUE, &pStolenFrom, NULL, NULL))
964  {
965  Process->CreationInfo.TokenStolenFromEprocess = pStolenFrom->EprocessAddress;
966  Process->DpiExtraInfo.DpiStolenTokenExtraInfo.StolenFromEprocess = pStolenFrom->EprocessAddress;
967  }
968 
969  return INT_STATUS_SUCCESS;
970 }
971 
972 
973 static INTSTATUS
975  _In_ WIN_PROCESS_OBJECT* Process,
976  _In_ WIN_PROCESS_OBJECT* Parent
977  )
986 {
987  INTSTATUS status;
988  BOOLEAN presentIncreased = FALSE, enabledIncreased = FALSE;
989  QWORD present = 0, enabled = 0;
990 
991  status = IntWinTokenCheckCurrentPrivileges(Parent,
992  Parent->OriginalTokenPtr,
993  &presentIncreased,
994  &enabledIncreased,
995  &present,
996  &enabled);
997  if (!INT_SUCCESS(status))
998  {
1000  {
1001  // Don't propagate the error, just warn it, as it is benign.
1002  WARNING("[WARNING] IntWinTokenCheckCurrentPrivileges failed: 0x%08x\n", status);
1003  return INT_STATUS_SUCCESS;
1004  }
1005 
1006  return status;
1007  }
1008 
1009  if (presentIncreased || enabledIncreased || Parent->PrivsChangeDetected)
1010  {
1011  Process->CreationInfo.ParentHasTokenPrivsAltered = TRUE;
1012 
1013  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.OldPresent = Parent->OriginalPresentPrivs;
1014  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.OldEnabled = Parent->OriginalEnabledPrivs;
1015  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.NewPresent = present;
1016  Process->DpiExtraInfo.DpiTokenPrivsExtraInfo.NewEnabled = enabled;
1017  }
1018 
1019  return INT_STATUS_SUCCESS;
1020 }
1021 
1022 
1023 static INTSTATUS
1025  _Inout_ WIN_PROCESS_OBJECT *Process,
1026  _In_ WIN_PROCESS_OBJECT *Parent
1027  )
1036 {
1037  INTSTATUS status;
1038  DWORD totalHeapValCnt = 0;
1039  DWORD totalMappedPages = 0;
1040 
1041  if (gGuest.Guest64 && !Parent->Wow64Process)
1042  {
1044  }
1045 
1046  for (DWORD val = 0x1; val <= HEAP_SPRAY_NR_PAGES; val++)
1047  {
1048  DWORD heapVal = (val << 24) | (val << 16) | (val << 8) | val;
1049  BYTE *mappedBytes;
1050  WORD heapValCnt = 0;
1051  BOOLEAN foundFirstNops = FALSE;
1052  DWORD firstNopOccurrence = 0;
1053  IG_ARCH_REGS regs = { 0 };
1054  QWORD shflags = 0;
1055  VA_TRANSLATION tr = { 0 };
1056 
1057  status = IntTranslateVirtualAddressEx(heapVal & PAGE_MASK, Parent->Cr3, 0, &tr);
1058  if (!INT_SUCCESS(status))
1059  {
1060  continue;
1061  }
1062 
1063  if (!(tr.Flags & PT_P))
1064  {
1065  continue;
1066  }
1067 
1068  status = IntVirtMemMap(heapVal & PAGE_MASK, PAGE_SIZE, Parent->Cr3, 0, &mappedBytes);
1069  if (!INT_SUCCESS(status))
1070  {
1071  continue;
1072  }
1073 
1074  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped = 1;
1075  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable = tr.IsExecutable;
1076 
1077  totalMappedPages++;
1078 
1079  for (DWORD i = 0; i < PAGE_SIZE; i++)
1080  {
1081  if (i % 4 == 0)
1082  {
1083  if (((DWORD *)mappedBytes)[i / 4] == heapVal)
1084  {
1085  heapValCnt++;
1086  totalHeapValCnt++;
1087  }
1088  }
1089 
1090  if (mappedBytes[i] == 0x90 && !foundFirstNops)
1091  {
1092  if (i > 0 && mappedBytes[i - 1] == 0x90)
1093  {
1094  firstNopOccurrence = i;
1095  foundFirstNops = TRUE;
1096  }
1097  }
1098  }
1099 
1100  IntVirtMemUnmap(&mappedBytes);
1101 
1102  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount = heapValCnt;
1103 
1104  // For now a sign of heap spraying is that at least a quarter of the page is filled
1105  // with the value that we mapped.
1106  if (heapValCnt >= PAGE_SIZE / 16)
1107  {
1108  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1109  break;
1110  }
1111 
1112  // At this point, if there was not any nop sequence found from where to start the emulation
1113  // the firstNopOccurrence variable will be equal to 0. We'll start the emulation from the
1114  // beginning of the page, as the shellcode might have spawned on multiple pages.
1115 
1116  regs.Rip = (heapVal & PAGE_MASK) + firstNopOccurrence;
1117  regs.Cr3 = Parent->Cr3;
1118  // Dummy value, so there would not be underflows if the stack is 0 and some instruction
1119  // accesses something on the stack, behind RSP.
1120  regs.Rsp = 0x10000;
1121 
1122  status = IntShcIsSuspiciousCode((heapVal & PAGE_MASK) + firstNopOccurrence,
1123  tr.PhysicalAddress,
1125  &regs,
1126  &shflags);
1127  if (!INT_SUCCESS(status))
1128  {
1129  ERROR("[ERROR] IntShcIsSuspiciousCode failed: 0x%08x\n", status);
1130  return status;
1131  }
1132 
1133  if (shflags != 0)
1134  {
1135  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.ShellcodeFlags = shflags;
1136  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected = 1;
1137  Process->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset = firstNopOccurrence;
1138  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1139  // There's no point in continuing, other than statistics.
1140  break;
1141  }
1142 
1143  }
1144 
1145  // Very heuristically: if we have mapped 5 pages and we found at least 500 heap values, then we consider
1146  // it was heap sprayed.
1147  if (totalMappedPages > 5 && totalHeapValCnt > 500)
1148  {
1149  Process->CreationInfo.ParentHasBeenHeapSprayed = TRUE;
1150  }
1151 
1152  return INT_STATUS_SUCCESS;
1153 }
1154 
1155 
1156 static INTSTATUS
1158  _Inout_ WIN_PROCESS_OBJECT *Process,
1159  _In_ WIN_PROCESS_OBJECT *Parent
1160  )
1171 {
1172  INTSTATUS status;
1173  QWORD thread = 0;
1174  QWORD startAddress = 0;
1175  IG_ARCH_REGS regs = { 0 };
1176  IG_CS_TYPE csType;
1177  QWORD gpa = 0;
1178  QWORD scflags = 0;
1179 
1180  if (Process->IsAgent)
1181  {
1183  }
1184 
1185  status = IntWinThrGetCurrentThread(gVcpu->Index, &thread);
1186  if (!INT_SUCCESS(status))
1187  {
1188  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
1189  return status;
1190  }
1191 
1192  status = IntKernVirtMemFetchWordSize(thread + WIN_KM_FIELD(Thread, Win32StartAddress), &startAddress);
1193  if (!INT_SUCCESS(status))
1194  {
1195  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
1196  return status;
1197  }
1198 
1199  status = IntTranslateVirtualAddress(startAddress, Parent->Cr3, &gpa);
1200  if (!INT_SUCCESS(status))
1201  {
1202  WARNING("[WARNING] IntTranslateVirtualAddress failed for 0x%016llx: 0x%08x\n", startAddress, status);
1203 
1204  // If the page has been swapped out, don't propagate the error.
1206  {
1207  return INT_STATUS_SUCCESS;
1208  }
1209 
1210  return status;
1211  }
1212 
1213  csType = Parent->Wow64Process || !gGuest.Guest64 ? IG_CS_TYPE_32B : IG_CS_TYPE_64B;
1214 
1215  regs.Rip = startAddress;
1216  regs.Cr3 = Parent->Cr3;
1217  // Dummy value, so there would not be underflows if the stack is 0 and some instruction
1218  // accesses something on the stack, behind RSP.
1219  regs.Rsp = 0x10000;
1220 
1221  status = IntShcIsSuspiciousCode(startAddress, gpa, csType, &regs, &scflags);
1222  if (!INT_SUCCESS(status))
1223  {
1224  ERROR("[ERROR] IntShcIsSuspiciousCode failed: 0x%08x\n", status);
1225  return status;
1226  }
1227 
1228  if (scflags != 0)
1229  {
1230  VAD vad = { 0 };
1231  QWORD vadroot = 0;
1232 
1233  // If we're in an imaged mapped vad, don't give a detection. But if we failed to get the vad, then
1234  // we won't know for sure, and better give a detection in this case.
1235  status = IntKernVirtMemFetchWordSize(Parent->EprocessAddress + WIN_KM_FIELD(Process, VadRoot), &vadroot);
1236  if (!INT_SUCCESS(status))
1237  {
1238  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
1239  goto _detect;
1240  }
1241 
1242  status = IntWinVadFetchByRange(vadroot, startAddress & PAGE_MASK, startAddress & PAGE_MASK, &vad);
1243  if (!INT_SUCCESS(status))
1244  {
1245  ERROR("[ERROR] IntWinVadFetchByRange failed: 0x%08x\n", status);
1246  goto _detect;
1247  }
1248 
1249  if (vad.VadType == VadImageMap)
1250  {
1251  goto _exit;
1252  }
1253 
1254 _detect:
1255  Process->DpiExtraInfo.DpiThreadStartExtraInfo.ShellcodeFlags = scflags;
1256  Process->DpiExtraInfo.DpiThreadStartExtraInfo.StartAddress = startAddress;
1257  Process->CreationInfo.ParentThreadSuspicious = TRUE;
1258  }
1259 
1260 _exit:
1261  return INT_STATUS_SUCCESS;
1262 }
1263 
1264 
1265 static __forceinline BOOLEAN
1267  _In_ WIN_PROCESS_OBJECT *Process,
1268  _In_ WIN_PROCESS_OBJECT *Parent
1269  )
1278 {
1279  // We'll let werfault to be created if the parent process had an exception.
1280  if (Process->NameHash == 0x56d1611d && // werfault.exe
1281  Parent->LastException != 0)
1282  {
1283  return TRUE;
1284  }
1285 
1286  // Add there any other cases on which DPI wouldn't need to be checked in the future
1287 
1288  return FALSE;
1289 }
1290 
1291 
1292 void
1294  _Inout_ WIN_PROCESS_OBJECT *Process,
1295  _In_ WIN_PROCESS_OBJECT *Parent,
1296  _In_ QWORD DebugHandle
1297  )
1306 {
1307  if (IntWinDpiIsDpiWhiteListed(Process, Parent))
1308  {
1309  return;
1310  }
1311 
1313  {
1315 
1316  INTSTATUS status = IntWinDpiGetProcessDebugFlag(Process, DebugHandle);
1317  if (!INT_SUCCESS(status))
1318  {
1319  ERROR("[ERROR] IntWinProcGetProcessDebugFlag failed: 0x%08x\n", status);
1320  }
1321 
1323  }
1324 
1326  {
1327  // We don't check the stack of the system process.
1328  if (__likely(Process->Pid != 4))
1329  {
1331 
1332  INTSTATUS status = IntWinDpiValidatePivotedStack(Process, Parent);
1333  if (!INT_SUCCESS(status))
1334  {
1335  ERROR("[ERROR] IntWinProcValidatePivotedStack failed: 0x%08x\n", status);
1336  }
1337 
1339  }
1340  }
1341 
1343  {
1345 
1346  INTSTATUS status = IntWinDpiValidateParentProcessToken(Process, Parent);
1347  if (!INT_SUCCESS(status))
1348  {
1349  ERROR("[ERROR] IntWinProcValidateCreatedProcessToken failed: 0x%08x\n", status);
1350  }
1351 
1353  }
1354 
1356  {
1358 
1359  INTSTATUS status = IntWinDpiValidateTokenPrivs(Process, Parent);
1360  if (!INT_SUCCESS(status))
1361  {
1362  ERROR("[ERROR] IntWinDpiValidateTokenPrivs failed: 0x%08x\n", status);
1363  }
1364 
1366  }
1367 
1369  {
1371 
1372  INTSTATUS status = IntWinDpiValidateHeapSpray(Process, Parent);
1373  if (!INT_SUCCESS(status))
1374  {
1375  ERROR("[ERROR] IntWinProcValidateHeapSpray failed: 0x%08x\n", status);
1376  }
1377 
1379  }
1380 
1382  {
1384 
1385  INTSTATUS status = IntWinDpiValidateThreadStart(Process, Parent);
1386  if (!INT_SUCCESS(status))
1387  {
1388  ERROR("[ERROR] IntWinDpiValidateThreadStart failed: 0x%08x\n", status);
1389  }
1390 
1392  }
1393 }
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:576
#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:1047
_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:1266
#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:476
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
The creation of a process was attempted while the parent had its heap sprayed.
Definition: intro_types.h:1531
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:1368
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:1629
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:474
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1088
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:1610
#define STATS_EXIT(id)
Definition: stats.h:148
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:1293
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:109
User-mode exception.
Definition: exceptions.h:61
enum _MITRE_ID MITRE_ID
Mitre attack techniques.
Process creation violation.
Definition: intro_types.h:259
QWORD Feedback
Options that will be forced to feedback only mode.
Definition: guests.h:251
#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
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
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:866
INTRO_PC_VIOLATION_TYPE
Process creation violation flags.
Definition: intro_types.h:1516
#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:331
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:2093
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:262
#define ERROR(fmt,...)
Definition: glue.h:62
Describes a user-mode originator.
Definition: exceptions.h:933
#define INTRO_OPT_PROT_DPI
Aggregates all the deep process inspection flags.
Definition: intro_types.h:502
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:432
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:282
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:278
Measures the heap spray DPI protection information gathering.
Definition: stats.h:89
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
EVENT_PROCESS_CREATION_VIOLATION ProcessCreation
Definition: alerts.h:31
#define IMAGE_BASE_NAME_LEN
The maximum length of a process name.
Definition: winguest.h:14
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:980
#define INTRO_OPT_PROT_DPI_TOKEN_PRIVS
Enable process creation protection for parent which has violated Token privileges constraints...
Definition: intro_types.h:491
#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:1040
Access Token Manipulation.
Definition: intro_types.h:1042
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1084
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:477
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:58
#define _Inout_
Definition: intro_sal.h:20
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1612
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
#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
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:1024
The parent of a process has a stolen access token when it created the child.
Definition: intro_types.h:1528
#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:286
unsigned long long QWORD
Definition: intro_types.h:53
QWORD Current
The currently used options.
Definition: guests.h:232
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
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:1534
#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:1525
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:974
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:383
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:363
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
#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:766
QWORD TokenStolenFromEprocess
This will keep the EPROCESS of the process from which the current process stole the token...
Definition: winprocess.h:281
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:238
#define PAGE_SIZE
Definition: common.h:53
Describes the modified zone.
Definition: exceptions.h:847
#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:478
#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:726
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:3861
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:193
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:948
#define PROC_OPT_PROT_PREVENT_CHILD_CREATION
Prevent the process from creating child processes (other than instances of itself).
Definition: intro_types.h:349
INTRO_PC_VIOLATION_TYPE PcType
The type of process creation violation.
Definition: intro_types.h:1652
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
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:884
struct _WIN_PROCESS_OBJECT::@227 CreationInfo
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:1157
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:88
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:522
The parent of a process tried to obtain debug privileges over the child.
Definition: intro_types.h:1522
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
INTRO_PROCESS Originator
The process that attempted the violation.
Definition: intro_types.h:1646
#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:493
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:23
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1537
INTRO_PROT_OPTIONS ShemuOptions
Flags which describe the way shemu will give detections.
Definition: guests.h:268
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1083
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:641
#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:179
INTRO_DPI_EXTRA_INFO DpiExtraInfo
A structure which contains extra information regarding the DPI violation that was detected...
Definition: intro_types.h:1668
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
#define __likely(x)
Definition: common.h:46
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1086
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
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:472
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:1910
Exploitation for Client Execution.
Definition: intro_types.h:1046
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:267
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:47
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
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:1631
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:81