Bitdefender Hypervisor Memory Introspection
winprocess.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winprocess.h"
6 #include "alerts.h"
7 #include "crc32.h"
8 #include "gpacache.h"
9 #include "icache.h"
10 #include "kernvm.h"
11 #include "ptfilter.h"
12 #include "swapmem.h"
13 #include "winagent.h"
14 #include "winobj.h"
15 #include "winpfn.h"
16 #include "winprocesshp.h"
17 #include "winselfmap.h"
18 #include "wincmdline.h"
19 #include "windpi.h"
20 #include "wintoken.h"
21 #include "winpe.h"
22 #include "winsecdesc.h"
23 
29 #define CMDLINE_LEN_NO_SCAN ALERT_CMDLINE_MAX_LEN
30 
37 #define CMDLINE_MAX_LEN (WORD_MAX - 1)
38 
40 extern RBTREE gWinProcTreeCr3;
43 
57 
58 
62 static LIST_HEAD gWinProtectedProcesses = LIST_HEAD_INIT(gWinProtectedProcesses);
63 
68 
72 const WCHAR gSystemPath[] = u"\\windows\\system32\\";
73 
77 const WCHAR gSysWowPath[] = u"\\windows\\syswow64\\";
78 
83 {
84  {
85  .ImageBaseNamePattern = "smss.exe",
86  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
87  .FullPathPattern = u"c:\\windows\\system32\\smss.exe",
88  .FullNamePattern = u"smss.exe"
89  },
90 
91  {
92  .ImageBaseNamePattern = "csrss.exe",
93  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
94  .FullPathPattern = u"c:\\windows\\system32\\csrss.exe",
95  .FullNamePattern = u"csrss.exe"
96  },
97 
98  {
99  .ImageBaseNamePattern = "wininit.exe",
100  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
101  .FullPathPattern = u"c:\\windows\\system32\\wininit.exe",
102  .FullNamePattern = u"wininit.exe"
103  },
104 
105  {
106  .ImageBaseNamePattern = "winlogon.exe",
107  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
108  .FullPathPattern = u"c:\\windows\\system32\\winlogon.exe",
109  .FullNamePattern = u"winlogon.exe"
110  },
111 
112  {
113  .ImageBaseNamePattern = "lsass.EXE",
114  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
115  .FullPathPattern = u"c:\\windows\\system32\\lsass.EXE",
116  .FullNamePattern = u"lsass.exe"
117  },
118 
119  {
120  .ImageBaseNamePattern = "services.EXE",
121  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
122  .FullPathPattern = u"c:\\windows\\system32\\services.EXE",
123  .FullNamePattern = u"services.exe"
124  },
125 };
126 
127 
132 {
133  {
134  .ImageBaseNamePattern = "powershell.exe",
135  .Protection = { .Original = PROC_OPT_PROT_SCAN_CMD_LINE, .Current = PROC_OPT_PROT_SCAN_CMD_LINE },
136  .FullPathPattern = u"c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe",
137  .FullNamePattern = u"powershell.exe"
138  },
139 };
140 
141 
146 static const char *gCmdLineProcesses[] =
147 {
148  "svchost.exe",
149  "chrome.exe", // Needed in order to detect NaCl instances
150 
151  // these are rather generic processes that host external code which may generate alerts (especially injections)
152  "rundll32.exe",
153  "dllhost.exe",
154 
155  "winword.exe",
156  "excel.exe",
157  "powerpnt.exe",
158 
159  "wscript.exe",
160  "mshta.exe",
161 };
162 
163 
164 static INTSTATUS
166  _In_ QWORD EprocessAddress,
167  _In_ QWORD Cr3,
168  _In_ DWORD Pid
169  );
170 
171 static INTSTATUS
173  _In_ WIN_PROCESS_OBJECT *Process
174  );
175 
176 static INTSTATUS
178  _In_ WIN_PROCESS_OBJECT *Process,
179  _Out_ WIN_PROCESS_SUBSYSTEM **Subsystem,
180  _In_ BYTE SubsystemType
181  );
182 
183 
184 static BOOLEAN
186  _In_ QWORD EprocessAddress,
187  _In_ BYTE *Eprocess
188  )
198 {
199  WIN_MITIGATION_FLAGS2 flags2 = { 0 };
200 
201  // If older than Windows 10 Redstone 3
202  if (gGuest.OSVersion < 16299)
203  {
204  return FALSE;
205  }
206 
207  if (0 == WIN_KM_FIELD(Process, MitigationFlags2))
208  {
209  WARNING("[WARNING] MitigationFlags2 Offset in Eprocess is not known for Windows version %d!\n",
210  gGuest.OSVersion);
211 
212  return FALSE;
213  }
214 
215  memcpy(&flags2, Eprocess + WIN_KM_FIELD(Process, MitigationFlags2), sizeof(flags2));
216 
217  TRACE("[WINPROC] Process @ 0x%016llx has Mitigation Flags 2 = 0x%08x\n", EprocessAddress, flags2.Flags);
218 
219  return flags2.Flags != 0;
220 }
221 
222 
223 static INTSTATUS
225  _In_ WIN_PROCESS_OBJECT *Process
226  )
234 {
235  INTSTATUS status;
236  DWORD offset;
237  BYTE execopts;
238 
239  // Assume that DEP is not enforced
240  Process->EnforcedDep = FALSE;
241 
242  // Not protected against exploits, leave it be.
243  if (!Process->ProtExploits)
244  {
246  }
247 
248  // If the process flags enable beta detections, don't do the DEP enforcement as it will crash the application.
249  if (IntPolicyProcIsBeta(Process, 0))
250  {
252  }
253 
254  // There is no way to not have DEP for a 64-bit process, so there's nothing left for us to do
255  if (gGuest.Guest64 && !Process->Wow64Process)
256  {
258  }
259 
260  offset = WIN_KM_FIELD(Process, KexecOptions);
261  if (0 == offset)
262  {
264  }
265 
266  status = IntKernVirtMemRead(Process->EprocessAddress + offset, 1, &execopts, NULL);
267  if (!INT_SUCCESS(status))
268  {
269  ERROR("[ERROR] Failed fetching the _KEXECUTE_OPTIONS from %llx: 0x%08x\n", Process->EprocessAddress, status);
270  return status;
271  }
272 
273  // Make sure we clear ExecuteEnable and set ExecuteDisable and Permanent flags.
274  execopts &= ~KEXEC_OPT_EXEC_ENABLE;
276 
277  status = IntVirtMemSafeWrite(gGuest.Mm.SystemCr3, Process->EprocessAddress + offset, 1, &execopts, IG_CS_RING_0);
278  if (!INT_SUCCESS(status))
279  {
280  ERROR("[ERROR] Failed patching the _KEXECUTE_OPTIONS at %llx: 0x%08x\n", Process->EprocessAddress, status);
281  return status;
282  }
283 
284  Process->EnforcedDep = TRUE;
285 
286  return INT_STATUS_SUCCESS;
287 }
288 
289 
290 static INTSTATUS
292  _In_ WIN_PROCESS_OBJECT *Process
293  )
304 {
305  INTSTATUS status;
306  char c[2];
307 
308  if (!Process->Protected)
309  {
310  memcpy(c, &Process->OriginalSpareValue, 2);
311  }
312  else
313  {
314  c[0] = '*';
315  c[1] = 0;
316 
317  if (Process->MonitorVad)
318  {
319  c[1] |= winProcExitVad;
320  }
321 
322  if (Process->ProtWriteMem)
323  {
324  c[1] |= winProcExitWriteMemory;
325 
326  if (Process->Lsass)
327  {
328  c[1] |= winProcExitReadMemory;
329  }
330  }
331 
332  if (Process->ProtThreadCtx)
333  {
334  c[1] |= winProcExitThreadCtx;
335  }
336 
337  if (Process->ProtQueueApc)
338  {
339  c[1] |= winProcExitQueueApc;
340  }
341 
342  if (Process->ProtInstrument)
343  {
344  c[1] |= winProcExitSetProcInfo;
345  }
346  }
347 
349  Process->EprocessAddress + WIN_KM_FIELD(Process, Spare),
350  sizeof(c),
351  &c,
352  IG_CS_RING_0);
353  if (!INT_SUCCESS(status))
354  {
355  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
356  return status;
357  }
358 
359  return INT_STATUS_SUCCESS;
360 }
361 
362 
363 static INTSTATUS
365  _In_ WIN_PROCESS_OBJECT *Process,
366  _In_ BOOLEAN Mark
367  )
379 {
380  INTSTATUS status;
381  CHAR c;
382 
383  c = Mark ? '?' : '\0';
384 
386  Process->EprocessAddress + WIN_KM_FIELD(Process, Name) + 14,
387  1,
388  &c,
389  IG_CS_RING_0);
390  if (!INT_SUCCESS(status))
391  {
392  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
393  return status;
394  }
395 
396  return INT_STATUS_SUCCESS;
397 }
398 
399 
400 static INTSTATUS
402  _In_ WIN_PROCESS_OBJECT *Process,
403  _In_ BOOLEAN Created
404  )
415 {
416  INTSTATUS status;
417  PEVENT_AGENT_EVENT pAgentEvent;
418 
419  if (!Process->IsAgent)
420  {
422  }
423 
424  pAgentEvent = &gAlert.Agent;
425  memzero(pAgentEvent, sizeof(*pAgentEvent));
426 
427  pAgentEvent->Event = Created ? agentStarted : agentTerminated;
428  pAgentEvent->AgentTag = Process->AgentTag;
429 
430  if (!Created)
431  {
432  pAgentEvent->ErrorCode = Process->ExitStatus;
433  }
434 
436 
437  status = IntNotifyIntroEvent(introEventAgentEvent, pAgentEvent, sizeof(*pAgentEvent));
438  if (!INT_SUCCESS(status))
439  {
440  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
441  }
442 
443  return INT_STATUS_SUCCESS;
444 }
445 
446 
447 static INTSTATUS
449  _In_ WIN_PROCESS_OBJECT *Process,
450  _In_ BOOLEAN Created,
451  _In_ BOOLEAN Crashed
452  )
464 {
465  INTSTATUS status;
466  PEVENT_PROCESS_EVENT pProcEvent;
467  WIN_PROCESS_OBJECT *pParent;
468 
470  {
472  }
473 
474  pProcEvent = &gAlert.Process;
475  memzero(pProcEvent, sizeof(*pProcEvent));
476 
477  pProcEvent->Created = Created;
478  pProcEvent->Protected = Process->Protected ? TRUE : FALSE;
479  pProcEvent->Crashed = Crashed;
480  pProcEvent->ExitStatus = Process->ExitStatus;
481 
483 
484  IntAlertFillWinProcess(Process, &pProcEvent->Child);
485 
486  pParent = IntWinProcFindObjectByEprocess(Process->ParentEprocess);
487  if (NULL != pParent)
488  {
489  IntAlertFillWinProcess(pParent, &pProcEvent->Parent);
490  }
491  else
492  {
493  pProcEvent->Parent.Valid = FALSE;
494  }
495 
496  status = IntNotifyIntroEvent(introEventProcessEvent, pProcEvent, sizeof(*pProcEvent));
497  if (!INT_SUCCESS(status))
498  {
499  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
500  }
501 
502  return status;
503 }
504 
505 
506 static INTSTATUS
508  _In_ WIN_PROCESS_OBJECT *Process
509  )
520 {
521  INTSTATUS status;
522  PEVENT_EXCEPTION_EVENT pExceptionEvent;
523 
525  {
527  }
528 
529  if (0 == Process->LastException)
530  {
532  }
533 
534  LOG("[PROCESS] Last exception encountered in %s: 0x%08x @ RIP 0x%016llx\n",
535  Process->Name, Process->LastException, Process->LastExceptionRip);
536 
537  pExceptionEvent = &gAlert.Exception;
538  memzero(pExceptionEvent, sizeof(*pExceptionEvent));
539 
540  pExceptionEvent->Continuable = Process->LastExceptionContinuable;
541  pExceptionEvent->ExceptionCode = Process->LastException;
542  pExceptionEvent->Rip = Process->LastExceptionRip;
543 
544  IntAlertFillWinProcess(Process, &pExceptionEvent->CurrentProcess);
545 
546  status = IntNotifyIntroEvent(introEventExceptionEvent, pExceptionEvent, sizeof(*pExceptionEvent));
547  if (!INT_SUCCESS(status))
548  {
549  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
550  }
551 
552  return INT_STATUS_SUCCESS;
553 }
554 
555 
556 static void
558  _In_ WIN_PROCESS_SUBSYSTEM *Subsystem
559  )
565 {
566  if (gGuest.Guest64 && (winSubsys32Bit == Subsystem->SubsystemType))
567  {
568  Subsystem->SystemDirPath = gSysWowPath;
569  }
570  else
571  {
572  Subsystem->SystemDirPath = gSystemPath;
573  }
574 }
575 
576 
577 INTSTATUS
579  _In_ WIN_PROCESS_OBJECT *Process,
580  _Out_ WIN_PROCESS_SUBSYSTEM **Subsystem,
581  _In_ BYTE SubsystemType
582  )
593 {
594  WIN_PROCESS_SUBSYSTEM *pSubs = HpAllocWithTag(sizeof(*pSubs), IC_TAG_SUBS);
595  if (NULL == pSubs)
596  {
598  }
599 
600  pSubs->Process = Process;
601  pSubs->SubsystemType = SubsystemType;
602 
604 
606 
607  *Subsystem = pSubs;
608 
609  return INT_STATUS_SUCCESS;
610 }
611 
612 
613 static INTSTATUS
615  _In_ WIN_PROCESS_SUBSYSTEM *Subsystem
616  )
625 {
626  LIST_ENTRY *listMod;
627  PWIN_PROCESS_MODULE pMod;
628 
629  if (NULL == Subsystem)
630  {
632  }
633 
634  listMod = Subsystem->ProcessModules.Flink;
635  while (listMod != &Subsystem->ProcessModules)
636  {
637  pMod = CONTAINING_RECORD(listMod, WIN_PROCESS_MODULE, Link);
638 
639  listMod = listMod->Flink;
640 
641  RemoveEntryList(&pMod->Link);
642 
643  IntWinModUnHookModule(pMod);
644 
645  IntWinModRemoveModule(pMod);
646  }
647 
648  HpFreeAndNullWithTag(&Subsystem, IC_TAG_SUBS);
649 
650  return INT_STATUS_SUCCESS;
651 }
652 
653 
654 static INTSTATUS
656  _In_ void *Context,
657  _In_ QWORD Cr3,
658  _In_ QWORD VirtualAddress,
659  _In_ QWORD PhysicalAddress,
660  _In_reads_bytes_(DataSize) void *Data,
661  _In_ DWORD DataSize,
662  _In_ DWORD Flags
663  )
680 {
681  INTSTATUS status = INT_STATUS_SUCCESS;
682  WIN_PROCESS_OBJECT *pProcess = NULL;
683  PCHAR pCmdLine = NULL;
684 
686  UNREFERENCED_PARAMETER(VirtualAddress);
687  UNREFERENCED_PARAMETER(PhysicalAddress);
688  UNREFERENCED_PARAMETER(Flags);
689 
690  if (NULL == Context)
691  {
693  }
694 
695  if (NULL == Data)
696  {
698  }
699 
700  pProcess = (PWIN_PROCESS_OBJECT)Context;
701 
702  pProcess->CmdBufSwapHandle = NULL;
703 
704  // The command line is a WCHAR buffer that is not necessarily NULL-terminated. Introcore saves it as a
705  // NULL-terminated CHAR buffer, so allocate half the size + 1 extra CHAR for the NULL-terminator;
706  // there's no need to explicitly add the NULL-terminator at the end, as the allocator already gives
707  // as a 0-filled buffer.
708  pProcess->CommandLineSize = DataSize / sizeof(WCHAR) + 1;
709 
710  pCmdLine = HpAllocWithTag(pProcess->CommandLineSize, IC_TAG_PCMD);
711  if (NULL == pCmdLine)
712  {
714  }
715 
716  // It is ok to pass CommandLineSize here as the function will stop at CommandLineSize - 1
717  pProcess->CommandLine = utf16tolowerutf8(pCmdLine, Data, pProcess->CommandLineSize);
718 
719  TRACE("[PROCESS] Process `%s` with PID %d and EPROCESS `0x%016llx` started with command line `%s`\n",
720  pProcess->Name, pProcess->Pid, pProcess->EprocessAddress, pProcess->CommandLine);
721 
722  // For chrome.exe, check if this is a NaCl instance
723  if (0 == strcasecmp(pProcess->Name, "chrome.exe"))
724  {
725 #define NACL_CMD_LINE "--type=nacl-loader" // NaCl processes have this switch in the command line
726 
727  if (strstr(pProcess->CommandLine, NACL_CMD_LINE))
728  {
729  LOG("[WINPROC] Process `%s` (%d) with command line `%s` has NaCl enabled!\n",
730  pProcess->Name, pProcess->Pid, pProcess->CommandLine);
731  pProcess->HasNaClEnabled = TRUE;
732  }
733  }
734 
736  {
737  status = IntWinInspectCommandLine(pProcess);
738  if (!INT_SUCCESS(status))
739  {
740  ERROR("[ERROR] IntWinPsInspectCommandLine failed: 0x%x\n", status);
741  }
742  }
743 
744  return status;
745 }
746 
747 
748 static INTSTATUS
750  _In_ void *Context,
751  _In_ QWORD Cr3,
752  _In_ QWORD VirtualAddress,
753  _In_ QWORD PhysicalAddress,
754  _In_reads_bytes_(DataSize) void *Data,
755  _In_ DWORD DataSize,
756  _In_ DWORD Flags
757  )
772 {
773  INTSTATUS status = INT_STATUS_SUCCESS;
774  WIN_PROCESS_OBJECT *pProcess = Context;
775  DWORD readLength;
776  QWORD gva;
777 
779  UNREFERENCED_PARAMETER(VirtualAddress);
780  UNREFERENCED_PARAMETER(PhysicalAddress);
781  UNREFERENCED_PARAMETER(DataSize);
782  UNREFERENCED_PARAMETER(Flags);
783 
784  if (NULL == Context)
785  {
787  }
788 
789  if (NULL == Data)
790  {
792  }
793 
794  pProcess->CmdLineSwapHandle = NULL;
795 
796  readLength = (pProcess->ProtectionMask & PROC_OPT_PROT_SCAN_CMD_LINE) ?
798 
799  if ((gGuest.Guest64 && pProcess->Wow64Process) || (!gGuest.Guest64))
800  {
801  UNICODE_STRING32 *pUsCmdLine = (UNICODE_STRING32 *)Data;
802 
803  readLength = MIN(readLength, pUsCmdLine->Length);
804  gva = pUsCmdLine->Buffer;
805  }
806  else
807  {
808  UNICODE_STRING64 *pUsCmdLine = (UNICODE_STRING64 *)Data;
809 
810  readLength = MIN(readLength, pUsCmdLine->Length);
811  gva = pUsCmdLine->Buffer;
812  }
813 
814  status = IntSwapMemReadData(pProcess->Cr3, gva, readLength, SWAPMEM_OPT_UM_FAULT, Context, 0,
816  if (!INT_SUCCESS(status))
817  {
818  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
819  }
820 
821  return status;
822 }
823 
824 
825 static INTSTATUS
827  _In_ void *Context,
828  _In_ QWORD Cr3,
829  _In_ QWORD VirtualAddress,
830  _In_ QWORD PhysicalAddress,
831  _In_reads_bytes_(DataSize) void *Data,
832  _In_ DWORD DataSize,
833  _In_ DWORD Flags
834  )
849 {
850  INTSTATUS status;
851  WIN_PROCESS_OBJECT *pProcess = Context;
852  DWORD readSize;
853  QWORD usersParamsGva;
854 
856  UNREFERENCED_PARAMETER(VirtualAddress);
857  UNREFERENCED_PARAMETER(PhysicalAddress);
858  UNREFERENCED_PARAMETER(DataSize);
859  UNREFERENCED_PARAMETER(Flags);
860 
861  if (NULL == Context)
862  {
864  }
865 
866  if (NULL == Data)
867  {
869  }
870 
871  pProcess->ParamsSwapHandle = NULL;
872 
873  if ((gGuest.Guest64 && pProcess->Wow64Process) || (!gGuest.Guest64))
874  {
875  usersParamsGva = *(DWORD *)Data;
876  usersParamsGva += FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS32, CommandLine);
877  readSize = sizeof(UNICODE_STRING32);
878  }
879  else
880  {
881  usersParamsGva = *(QWORD *)Data;
882  usersParamsGva += FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS64, CommandLine);
883 
884  readSize = sizeof(UNICODE_STRING64);
885  }
886 
887  // read UserParameters.CommandLine
888  status = IntSwapMemReadData(pProcess->Cr3, usersParamsGva, readSize, SWAPMEM_OPT_UM_FAULT, Context,
890  if (!INT_SUCCESS(status))
891  {
892  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
893  }
894 
895  return status;
896 }
897 
898 
899 INTSTATUS
901  _In_ WIN_PROCESS_OBJECT *Process
902  )
910 {
911  INTSTATUS status;
912  QWORD gva;
913  DWORD readSize;
914 
915  if (NULL == Process)
916  {
918  }
919 
920  if ((gGuest.Guest64 && Process->Wow64Process) || (!gGuest.Guest64))
921  {
922  if (0 == Process->Peb32Address)
923  {
924  WARNING("[WARNING] Peb32 is NULL!\n");
926  }
927 
928  gva = Process->Peb32Address + FIELD_OFFSET(PEB32, ProcessParameters);
929  readSize = sizeof(DWORD);
930  }
931  else
932  {
933  if (0 == Process->Peb64Address)
934  {
935  WARNING("[WARNING] Peb64 is NULL!\n");
937  }
938 
939  gva = Process->Peb64Address + FIELD_OFFSET(PEB64, ProcessParameters);
940 
941  readSize = sizeof(QWORD);
942  }
943 
944  // Read Peb.RtlUserProcessParameters
945  status = IntSwapMemReadData(Process->Cr3, gva, readSize, SWAPMEM_OPT_UM_FAULT, Process, 0,
946  IntWinGetPrcoCmdLineHandleUserParamsInMemory, NULL, &Process->ParamsSwapHandle);
947  if (!INT_SUCCESS(status))
948  {
949  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
950  }
951 
952  return status;
953 }
954 
955 
956 static void
958  _In_ const WCHAR *FullPath,
960  _Out_ const WCHAR **FullName
961  )
969 {
970  SIZE_T fplen, len;
971  DWORD i;
972  const WCHAR *pivot;
973 
974  len = 0;
975  fplen = wstrlen(FullPath);
976 
977  // copy the base name locally.
978  pivot = FullPath + fplen;
979 
980  do
981  {
982  pivot--;
983  } while ((pivot >= FullPath) && (*pivot != u'\\'));
984 
985  pivot++;
986 
987  *FullName = pivot;
988 
989  for (i = 0; (i < 15) && (pivot[i] != 0); i++)
990  {
991  BaseName[i] = (CHAR)pivot[i]; // This is what the kernel does internally, so we're safe.
992  }
993 
994  BaseName[i] = 0;
995 
996  while ((len < IMAGE_BASE_NAME_LEN) && (BaseName[len] != 0))
997  {
998  len++;
999  }
1000 
1001  // Fill in the end of the name with NULLs.
1002  if (len < IMAGE_BASE_NAME_LEN)
1003  {
1004  memset(BaseName + len, 0, IMAGE_BASE_NAME_LEN - len);
1005  }
1006 
1007  BaseName[14] = 0;
1008 }
1009 
1010 
1011 static const PROTECTED_PROCESS_INFO *
1013  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
1014  _In_ BOOLEAN IsSystem
1015  )
1025 {
1026  LIST_ENTRY *list;
1027 
1029  {
1030  for (DWORD i = 0; i < ARRAYSIZE(gWinForcedProtectedProcesses); i++)
1031  {
1032  if (IntMatchPatternUtf8(gWinForcedProtectedProcesses[i].ImageBaseNamePattern,
1033  BaseName,
1035  {
1036  return &gWinForcedProtectedProcesses[i];
1037  }
1038  }
1039 
1040  list = gWinProtectedProcesses.Flink;
1041  while (list != &gWinProtectedProcesses)
1042  {
1044 
1045  list = list->Flink;
1046 
1048  {
1049  return pProc;
1050  }
1051  }
1052  }
1053 
1054  if (0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_UM_SYS_PROCS) && IsSystem)
1055  {
1056  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1057  {
1058  if (IntMatchPatternUtf8(gSystemProcesses[i].ImageBaseNamePattern, BaseName, INTRO_MATCH_TRUNCATED))
1059  {
1060  return &gSystemProcesses[i];
1061  }
1062  }
1063  }
1064 
1065  return NULL;
1066 }
1067 
1068 
1069 const PROTECTED_PROCESS_INFO *
1071  _In_ PWCHAR Path,
1072  _In_ BOOLEAN IsSystem
1073  )
1083 {
1084  LIST_ENTRY *list;
1085  CHAR baseName[16];
1086  const WCHAR *fullName;
1087  BOOLEAN match;
1088 
1089  fullName = NULL;
1090 
1091  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
1092 
1093  // Search the misc process list.
1095  {
1096  for (DWORD i = 0; i < ARRAYSIZE(gWinForcedProtectedProcesses); i++)
1097  {
1098  // Make sure the image base name matches.
1099  match = IntMatchPatternUtf8(gWinForcedProtectedProcesses[i].ImageBaseNamePattern,
1100  baseName,
1102 
1103  // Make sure the full name matches.
1104  match = match && IntMatchPatternUtf16(gWinForcedProtectedProcesses[i].FullNamePattern, fullName, 0);
1105 
1106  if (match)
1107  {
1108  return &gWinForcedProtectedProcesses[i];
1109  }
1110  }
1111 
1112  list = gWinProtectedProcesses.Flink;
1113  while (list != &gWinProtectedProcesses)
1114  {
1116 
1117  list = list->Flink;
1118 
1119  // Make sure the image base name matches.
1121 
1122  // Make sure the full name matches.
1123  match = match && IntMatchPatternUtf16(pProc->FullNamePattern, fullName, 0);
1124 
1125  // Make sure the full path matches, if present.
1126  if ((0 != (gGuest.CoreOptions.Current & INTRO_OPT_FULL_PATH)) &&
1127  (0 == (pProc->Flags & PROT_PROC_FLAG_NO_PATH)))
1128  {
1129  match = match && IntMatchPatternUtf16(pProc->FullPathPattern, Path, 0);
1130  }
1131 
1132  if (match)
1133  {
1134  return pProc;
1135  }
1136  }
1137  }
1138 
1139  // Search the system process list,
1140  if (0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_UM_SYS_PROCS) && IsSystem)
1141  {
1142  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1143  {
1144  // Make sure the image base name matches.
1145  match = IntMatchPatternUtf8(gSystemProcesses[i].ImageBaseNamePattern, baseName, INTRO_MATCH_TRUNCATED);
1146 
1147  // Make sure the full name matches.
1148  match = match && IntMatchPatternUtf16(gSystemProcesses[i].FullNamePattern, fullName, 0);
1149 
1150  if (match)
1151  {
1152  return &gSystemProcesses[i];
1153  }
1154  }
1155  }
1156 
1157  return NULL;
1158 }
1159 
1160 
1161 INTSTATUS
1163  void
1164  )
1171 {
1172  LIST_ENTRY *pList = gWinProcesses.Flink;
1173  while (pList != &gWinProcesses)
1174  {
1175  INTSTATUS status;
1177  const PROTECTED_PROCESS_INFO *pProtInfo;
1178 
1179  pList = pList->Flink;
1180 
1181  if (pProc->SystemProcess && pProc->Protected)
1182  {
1184  }
1185 
1186  // Check if the process is protected or not.
1187  if (NULL != pProc->Path)
1188  {
1189  pProtInfo = IntWinProcGetProtectedInfoEx(pProc->Path->Path, !!pProc->SystemProcess);
1190  }
1191  else
1192  {
1193  pProtInfo = IntWinProcGetProtectedInfo(pProc->Name, !!pProc->SystemProcess);
1194  }
1195 
1196  if (NULL != pProtInfo)
1197  {
1198  // We can end up with an inconsistent state if we attempt to re-protect a process (we could deactivate
1199  // the protection and then re-activate it with the new flags).
1200  // Note that the next time a process with the given name will start, the flags provided now will be used
1201  // to protect it.
1202  if (pProc->Context != pProtInfo->Context)
1203  {
1204  pProc->Context = pProtInfo->Context;
1205  }
1206 
1207  pProc->FeedbackMask = pProtInfo->Protection.Feedback;
1208  pProc->BetaMask = pProtInfo->Protection.Beta;
1209 
1210  if (pProc->Protected && (pProtInfo->Protection.Current != pProc->ProtectionMask))
1211  {
1212  // Process is already protected, but with other flags.
1213  LOG("[PROCESS] Changing protection flags for process %s (Eprocess %llx): 0x%x -> 0x%x\n",
1214  pProc->Name, pProc->EprocessAddress, pProc->ProtectionMask, pProtInfo->Protection.Original);
1215 
1216  status = IntWinProcChangeProtectionFlags(pProc, pProc->ProtectionMask, pProtInfo->Protection.Original);
1217  if (!INT_SUCCESS(status))
1218  {
1219  INTSTATUS status2;
1220 
1221  status2 = IntWinProcUnprotect(pProc);
1222  if (!INT_SUCCESS(status2))
1223  {
1224  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status2);
1225  }
1226 
1227  memset(&gErrorContext, 0, sizeof(gErrorContext));
1230 
1233  &gErrorContext);
1234  }
1235  }
1236  else if (!pProc->Protected)
1237  {
1238  LOG("[PROCESS] Process %s (Eprocess %llx) has already started, will activate static protection\n",
1239  pProc->Name, pProc->EprocessAddress);
1240 
1241  pProc->LateProtection = TRUE;
1242  pProc->ProtectionMask = pProtInfo->Protection.Current;
1243 
1244  pProc->Protected = TRUE;
1245  pProc->Context = pProtInfo->Context;
1246 
1247  status = IntWinProcProtect(pProc);
1248  if (!INT_SUCCESS(status))
1249  {
1250  ERROR("[ERROR] IntWinProcActivateProtection failed: 0x%x\n", status);
1251  }
1252  }
1253  }
1254  else
1255  {
1256  if (pProc->Protected)
1257  {
1258  LOG("[PROCESS] Deactivating protection for process %s (Pid %d, Cr3 0x%016llx)\n",
1259  pProc->Name, pProc->Pid, pProc->Cr3);
1260 
1261  status = IntWinProcUnprotect(pProc);
1262  if (!INT_SUCCESS(status))
1263  {
1264  ERROR("[ERROR] IntWinProcUnhookProcess failed for 0x%016llx (Cr3 0x%016llx): 0x%08x\n",
1265  pProc->EprocessAddress, pProc->Cr3, status);
1266  }
1267  }
1268  }
1269  }
1270 
1271  return INT_STATUS_SUCCESS;
1272 }
1273 
1274 
1275 static void
1277  _In_ QWORD Cr3,
1278  _In_ QWORD Eprocess
1279  )
1293 {
1294  WIN_PROCESS_OBJECT *duplicate;
1295 
1296  duplicate = IntWinProcFindObjectByCr3(Cr3);
1297  if (NULL != duplicate)
1298  {
1299  INTSTATUS status;
1300 
1301  ERROR("[ERROR] Duplicate process for CR3 0x%016llx: '%s', will remove it.\n", Cr3, duplicate->Name);
1302 
1303  status = IntWinProcDeleteProcessObject(duplicate->EprocessAddress, Cr3, duplicate->Pid);
1304  if (!INT_SUCCESS(status))
1305  {
1306  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
1307  }
1308  }
1309 
1310  duplicate = IntWinProcFindObjectByEprocess(Eprocess);
1311  if (NULL != duplicate)
1312  {
1313  INTSTATUS status;
1314 
1315  ERROR("[ERROR] Duplicate process for EPROCESS 0x%016llx: '%s', will remove it.\n", Eprocess, duplicate->Name);
1316 
1317  status = IntWinProcDeleteProcessObject(Eprocess, duplicate->Cr3, duplicate->Pid);
1318  if (!INT_SUCCESS(status))
1319  {
1320  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
1321  }
1322  }
1323 }
1324 
1325 
1326 static void
1328  _Inout_ WIN_PROCESS_OBJECT *Process,
1329  _In_ const BYTE *EprocessBuffer
1330  )
1344 {
1345  if (gGuest.KptiActive)
1346  {
1347  if (gGuest.Guest64)
1348  {
1349  Process->UserCr3 = *(QWORD const *)(EprocessBuffer + WIN_KM_FIELD(Process, UserCr3));
1350 
1351  if (Process->UserCr3 < PAGE_SIZE)
1352  {
1353  Process->UserCr3 = Process->Cr3;
1354  }
1355  }
1356  else
1357  {
1358  if (Process->Pid != 4)
1359  {
1360  Process->UserCr3 = Process->Cr3 | 0x20;
1361  }
1362  else
1363  {
1364  Process->UserCr3 = Process->Cr3;
1365  }
1366  }
1367  }
1368  else
1369  {
1370  Process->UserCr3 = Process->Cr3;
1371  }
1372 }
1373 
1374 
1375 static INTSTATUS
1377  _In_ WIN_PROCESS_OBJECT *Process
1378  )
1392 {
1393  INTSTATUS status;
1394 
1395  status = IntWinPfnLockGpa(Process->Cr3, (WIN_PFN_LOCK **)&Process->Cr3PageLockObject);
1396  if (!INT_SUCCESS(status))
1397  {
1398  ERROR("[ERROR] IntWinPfnLockGpa failed for process '%s', eprocess %llx, cr3 %llx: 0x%08x\n",
1399  Process->Name, Process->EprocessAddress, Process->Cr3, status);
1400 
1402 
1403  return status;
1404  }
1405 
1406  if ((Process->UserCr3 != Process->Cr3) && (Process->UserCr3 >= PAGE_SIZE))
1407  {
1408  status = IntWinPfnLockGpa(Process->UserCr3, (PWIN_PFN_LOCK *)&Process->UserCr3PageLockObject);
1409  if (!INT_SUCCESS(status))
1410  {
1411  ERROR("[ERROR] IntWinPfnLockGpa failed for process '%s', eprocess %llx, user cr3 %llx: 0x%08x\n",
1412  Process->Name, Process->EprocessAddress, Process->UserCr3, status);
1413 
1415 
1416  return status;
1417  }
1418  }
1419 
1420  return INT_STATUS_SUCCESS;
1421 }
1422 
1423 
1424 static INTSTATUS
1426  _In_ WIN_PROCESS_OBJECT *Process
1427  )
1438 {
1439  INTSTATUS status;
1440 
1441  if (NULL != Process->Cr3PageLockObject)
1442  {
1443  status = IntWinPfnRemoveLock(Process->Cr3PageLockObject, FALSE);
1444  if (!INT_SUCCESS(status))
1445  {
1446  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
1447  }
1448 
1449  Process->Cr3PageLockObject = NULL;
1450  }
1451 
1452  if (NULL != Process->UserCr3PageLockObject)
1453  {
1454  status = IntWinPfnRemoveLock(Process->UserCr3PageLockObject, FALSE);
1455  if (!INT_SUCCESS(status))
1456  {
1457  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
1458  }
1459 
1460  Process->UserCr3PageLockObject = NULL;
1461  }
1462 
1463  return INT_STATUS_SUCCESS;
1464 }
1465 
1466 
1467 static void
1469  _Inout_ WIN_PROCESS_OBJECT *Process,
1470  _In_ const WIN_PROCESS_OBJECT *Parent
1471  )
1485 {
1486  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1487  {
1488  if (0 == strcasecmp(Process->Name, gSystemProcesses[i].ImageBaseNamePattern))
1489  {
1490  // We've found a system process name. Make sure it was started by another system process.
1491  // Special case is services.exe, which although is flagged as system, can't spawn other system processes.
1492  // If it could, it would be trivial to register a service 'c:\csrss.exe', which would be started by
1493  // services.exe, and would be flagged as system.
1494  if ((NULL != Parent) && (Parent->SystemProcess))
1495  {
1496  if (0 == strcasecmp("services.exe", Parent->Name))
1497  {
1498  WARNING("[WARNING] Process '%s' is started by services.exe! Will not be flagged as system!\n",
1499  Process->Name);
1500  }
1501  else
1502  {
1503  Process->SystemProcess = TRUE;
1504  }
1505  }
1506  else if (NULL == Parent && 0 == Process->ParentEprocess)
1507  {
1508  // This is an important thing: if we are being initialized from within the OS or after hibernation,
1509  // we CAN'T safely determine if a process is system or not. Therefore, we will do a hack: whenever
1510  // a process with a system name is created, and that process is not in fact a system process, we will
1511  // slightly patch it's name, so that it won't match anymore on resume from hibernation.
1512  // Right here we assume that all processes that have a system name are actually legitimate. If we're
1513  // being started from within the OS, we can assume anything - the system may well be very infected
1514  // already. Note that we will have a parent when we monitor process creation, but we don't have the
1515  // parent when getting the already created list of processes. In that case, the parent will be 0.
1516  Process->SystemProcess = TRUE;
1517  }
1518 
1519  // We had name match, but the process isn't in fact system. We have to patch the name.
1520  if (!Process->SystemProcess)
1521  {
1522  BYTE c = '!';
1523  INTSTATUS status;
1524 
1525  WARNING("[WARNING] Process '%s' is not in fact system; parent is 0x%016llx\n",
1526  Process->Name, Process->ParentEprocess);
1527 
1528  // Scramble the name inside the EPROCESS.
1529  status = IntVirtMemSafeWrite(0, Process->EprocessAddress + WIN_KM_FIELD(Process, Name),
1530  1, &c, IG_CS_RING_0);
1531  if (!INT_SUCCESS(status))
1532  {
1533  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
1534  }
1535  }
1536 
1537  break;
1538  }
1539  }
1540 }
1541 
1542 
1543 INTSTATUS
1545  _Out_ WIN_PROCESS_OBJECT **Process,
1546  _In_ QWORD EprocessAddress,
1547  _In_ PBYTE EprocessBuffer,
1548  _In_ QWORD ParentEprocess,
1549  _In_ QWORD RealParentEprocess,
1550  _In_ QWORD Cr3,
1551  _In_ DWORD Pid,
1552  _In_ BOOLEAN StaticScan
1553  )
1582 {
1583  INTSTATUS status;
1584  BOOLEAN isAgent;
1585  WIN_PROCESS_OBJECT *pProc, *pParent, *pRealParent;
1586  const BOOLEAN protTokenPtr = 0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_KM_TOKEN_PTR);
1587  const BOOLEAN protTokenPrivs = 0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_KM_TOKEN_PRIVS);
1588  DWORD flags = 0;
1589 
1590  if (NULL == Process)
1591  {
1593  }
1594 
1595  if (0 == EprocessAddress)
1596  {
1598  }
1599 
1600  if (NULL == EprocessBuffer)
1601  {
1603  }
1604 
1605  IntWinProcHandleDuplicate(Cr3, EprocessAddress);
1606 
1607  pProc = HpAllocWithTag(sizeof(*pProc), IC_TAG_POBJ);
1608  if (NULL == pProc)
1609  {
1611  }
1612 
1613  flags = *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Flags));
1614  pProc->Outswapped = !!(flags & WIN_KM_FIELD(EprocessFlags, OutSwapped));
1615 
1616  // Now we can actually initialize the process.
1617  STATIC_ASSERT(IMAGE_BASE_NAME_LEN == 2 * sizeof(QWORD), "QWORD by QWORD copy of process name will fail");
1618 
1619  *(QWORD *)(pProc->Name) = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Name));
1620  *(QWORD *)(pProc->Name + sizeof(QWORD)) = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Name) + sizeof(QWORD));
1621 
1622  pProc->Name[CSTRLEN(pProc->Name)] = 0;
1623 
1624  // Workaround for system process, which doesn't have a ImageName
1625  if ((pProc->Name[0] == 0) && (4 == Pid))
1626  {
1627  strlcpy(pProc->Name, "system", sizeof(pProc->Name));
1628  }
1629 
1630  IntWinVadProcessInit(pProc);
1631 
1632  strlower_utf8(pProc->Name, strlen(pProc->Name));
1633 
1634  pProc->NameHash = Crc32String(pProc->Name, INITIAL_CRC_VALUE);
1635  pProc->Cr3 = Cr3;
1636  pProc->Pid = Pid;
1637  pProc->EprocessAddress = EprocessAddress;
1638  pProc->ParentEprocess = ParentEprocess;
1639  pProc->RealParentEprocess = RealParentEprocess;
1640  pProc->StaticDetected = StaticScan;
1641  pProc->LateProtection = StaticScan;
1642 
1643  IntWinProcSetUserCr3(pProc, EprocessBuffer);
1644 
1645 
1646  if (!pProc->Outswapped)
1647  {
1648  // Lock the CR3 of this process in memory. We don't want the OS to mangle with the CR3, since it is used
1649  // for exceptions.
1650  // NOTE: This is a hard-error, we disable Introcore if this fails.
1651  status = IntWinProcLockCr3(pProc);
1652  if (!INT_SUCCESS(status))
1653  {
1654  goto cleanup_and_exit;
1655  }
1656  }
1657 
1658  if (4 != Pid)
1659  {
1660  pProc->CreationTime = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, CreateTime));
1661  }
1662  else
1663  {
1664  // Workaround for the System process: when the System process is originally created, it has
1665  // CreationTime 0. Sometimes after that, the kernel will modify it to reflect the actual creation
1666  // time, but it's too late for us. In order to ensure that we will always have the same uuid for the
1667  // System process, we force the Creationtime to 0.
1668  pProc->CreationTime = 0;
1669  }
1670 
1671  if (gGuest.Guest64)
1672  {
1673  if (0 != WIN_KM_FIELD(Process, SectionBase))
1674  {
1675  pProc->MainModuleAddress = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, SectionBase));
1676  }
1677 
1678  pProc->OriginalTokenPtr = EX_FAST_REF_TO_PTR(TRUE, *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Token)));
1679 
1680  if (4 != Pid)
1681  {
1682  pProc->Peb64Address = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Peb));
1683  pProc->Peb32Address = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, WoW64));
1684 
1685  // Starting with Windows 10, build > 10240 (TH1), WoW64Process doesn't point directly to the
1686  // PEB32, but instead to a _EWOW64PROCESS, which contains the PEB address (first 8 bytes) and the
1687  // machine type (next 2 bytes).
1689  {
1690  status = IntKernVirtMemFetchQword(pProc->Peb32Address, &pProc->Peb32Address);
1691  if (!INT_SUCCESS(status))
1692  {
1693  ERROR("[ERROR] IntKernVirtMemFetchQword failed for %llx (EWOW64): 0x%08x\n",
1694  pProc->Peb32Address,
1695  status);
1696 
1697  goto cleanup_and_exit;
1698  }
1699  }
1700 
1701  if (0 != pProc->Peb32Address && gGuest.Guest64)
1702  {
1703  pProc->Wow64Process = TRUE;
1704  }
1705  }
1706  }
1707  else
1708  {
1709  if (0 != WIN_KM_FIELD(Process, SectionBase))
1710  {
1711  pProc->MainModuleAddress = *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, SectionBase));
1712  }
1713 
1714  pProc->OriginalTokenPtr = EX_FAST_REF_TO_PTR(FALSE, *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Token)));
1715 
1716  if (4 != Pid)
1717  {
1718  pProc->Peb64Address = *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Peb));
1719  pProc->Peb32Address = pProc->Peb64Address;
1720 
1721  pProc->Wow64Process = FALSE;
1722  }
1723  }
1724 
1725  // Protect the token privileges, if needed.
1726  status = IntWinTokenPrivsProtectOnProcess(pProc);
1727  if (!INT_SUCCESS(status))
1728  {
1729  ERROR("[ERROR] IntWinTokenPrivsProtectOnProcess failed: 0x%08x\n", status);
1730  }
1731 
1732  status = IntWinSDProtectSecDesc(pProc);
1733  if (!INT_SUCCESS(status))
1734  {
1735  WARNING("[WARNING] IntWinSDProtectSecDesc failed: 0x%08x\n", status);
1736  }
1737 
1738  // Get the original spare value. Applying the protection will overwrite the Spare field
1739  // in in-guest EPROCESS so we should save it before.
1740  status = IntKernVirtMemRead(pProc->EprocessAddress + WIN_KM_FIELD(Process, Spare),
1741  sizeof(pProc->OriginalSpareValue), &pProc->OriginalSpareValue, NULL);
1742  if (!INT_SUCCESS(status))
1743  {
1744  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
1745  goto cleanup_and_exit;
1746  }
1747 
1748  if (0 != pProc->OriginalSpareValue)
1749  {
1750  WARNING("[WARNING] Spare value for eprocess 0x%016llx at offset %x is not 0! (0x%04x)\n",
1751  pProc->EprocessAddress, WIN_KM_FIELD(Process, Spare), pProc->OriginalSpareValue);
1752  }
1753 
1754  // pParent and pRealParent will be NULL if ParentEprocess, or RealParentEprocess are 0
1756  pRealParent = IntWinProcFindObjectByEprocess(pProc->RealParentEprocess);
1757 
1758  if (protTokenPtr && !StaticScan)
1759  {
1760  if (pParent != NULL)
1761  {
1762  status = IntWinTokenPtrCheckIntegrityOnProcess(pParent);
1763  if (!INT_SUCCESS(status))
1764  {
1765  WARNING("[WARNING] IntWinTokenPtrCheckIntegrityOnProcess failed for parent 0x%016llx: 0x%x\n",
1766  pParent->EprocessAddress, status);
1767  }
1768  }
1769 
1770  if (pRealParent != NULL)
1771  {
1772  status = IntWinTokenPtrCheckIntegrityOnProcess(pRealParent);
1773  if (!INT_SUCCESS(status))
1774  {
1775  WARNING("[WARNING] IntWinTokenPtrCheckIntegrityOnProcess failed for real parent 0x%016llx: 0x%x\n",
1776  pRealParent->EprocessAddress, status);
1777  }
1778  }
1779  }
1780 
1781  if (protTokenPrivs && !StaticScan)
1782  {
1783  if (pParent != NULL)
1784  {
1785  status = IntWinTokenPrivsCheckIntegrityOnProcess(pParent);
1786  if (!INT_SUCCESS(status))
1787  {
1788  WARNING("[WARNING] IntWinTokenPrivsCheckIntegrityOnProcess failed for parent 0x%016llx: 0x%x\n",
1789  pParent->EprocessAddress, status);
1790  }
1791  }
1792 
1793  if (pRealParent != NULL)
1794  {
1795  status = IntWinTokenPrivsCheckIntegrityOnProcess(pRealParent);
1796  if (!INT_SUCCESS(status))
1797  {
1798  WARNING("[WARNING] IntWinTokenPrivsCheckIntegrityOnProcess failed for real parent 0x%016llx: 0x%x\n",
1799  pRealParent->EprocessAddress, status);
1800  }
1801  }
1802  }
1803 
1804  if (4 == Pid)
1805  {
1806  // The initial System process is always marked as system.
1807  pProc->SystemProcess = TRUE;
1808 
1809  if (pProc->Cr3 != gGuest.Mm.SystemCr3)
1810  {
1811  WARNING("[WARNING] Possible System CR3 (0x%016llx) mismatch: "
1812  "System process (0x%016llx) has CR3 0x%016llx\n",
1813  gGuest.Mm.SystemCr3, pProc->EprocessAddress, pProc->Cr3);
1814  }
1815  }
1816 
1817  IntWinProcMarkAsSystemProcess(pProc, pParent);
1818 
1819  // If this is the "services.exe" process, than this means the we can now safely inject remediation agents.
1820  if (0 == strcasecmp(pProc->Name, "services.exe"))
1821  {
1822  status = IntAgentEnableInjection();
1823  if (!INT_SUCCESS(status))
1824  {
1825  ERROR("[ERROR] IntAgentEnableInjection failed: 0x%08x\n", status);
1826  }
1827 
1829  if (!INT_SUCCESS(status))
1830  {
1831  ERROR("[ERROR] IntWinGuestFindDriversNamespace: 0x%08x\n", status);
1832  }
1833 
1835  {
1837  }
1838  }
1839 
1840  if (0 == strcasecmp(pProc->Name, "lsass.exe"))
1841  {
1842  pProc->Lsass = 1;
1843  }
1844 
1845  IntWinAgentCheckIfProcessAgentAndIncrement(pProc->Name, &isAgent, &pProc->AgentTag);
1846 
1847  pProc->IsAgent = isAgent;
1848 
1849  if (gGuest.Guest64)
1850  {
1851  // If we're on 64 bit windows than we will surely have 64 bit subsystem.
1853  if (!INT_SUCCESS(status))
1854  {
1855  ERROR("[ERROR] IntWinProcCreateProcessSubsystem failed: 0x%08x\n", status);
1856  goto cleanup_and_exit;
1857  }
1858 
1859  pProc->Subsystemx64->PebAddress = pProc->Peb64Address;
1860 
1861  if (NULL != pParent && pParent->Wow64Process)
1862  {
1863  if (!pProc->Wow64Process)
1864  {
1865  TRACE("------------> Special case %s (0x%016llx) / 32 -> %s (0x%016llx) / 64\n",
1866  pParent->Name, pParent->EprocessAddress, pProc->Name, pProc->EprocessAddress);
1867  }
1868 
1869  pProc->ParentWow64 = TRUE;
1870  }
1871  }
1872 
1873  if (!gGuest.Guest64 || pProc->Wow64Process)
1874  {
1875  // 32 bit guests and Wow64 processes also have a 32 bit subsystem.
1877  if (!INT_SUCCESS(status))
1878  {
1879  ERROR("[ERROR] IntWinProcCreateProcessSubsystem failed: 0x%08x\n", status);
1880  goto cleanup_and_exit;
1881  }
1882 
1883  pProc->Subsystemx86->PebAddress = pProc->Peb32Address;
1884  }
1885 
1886  // Determine if the process will be protected or not. A process will be protected if:
1887  // 1. It is inside the list of protected processes.
1888  // 2. It is a system process
1889  // 3. The flag INTRO_OPT_ENABLE_PROTECTION_ALL was used at creation.
1890  // Note: we don't care about static protection; that must be enabled & used by default from now on!
1892  {
1893  const PROTECTED_PROCESS_INFO *pProtInfo = IntWinProcGetProtectedInfo(pProc->Name, !!pProc->SystemProcess);
1894  if (NULL != pProtInfo)
1895  {
1896  pProc->Protected = TRUE;
1897  pProc->ProtectionMask = pProtInfo->Protection.Current;
1898  pProc->BetaMask = pProtInfo->Protection.Beta;
1899  pProc->FeedbackMask = pProtInfo->Protection.Feedback;
1900  pProc->Context = pProtInfo->Context;
1901  }
1902  }
1903 
1904  // If we are running on Napoca, we don`t want to obtain the entire command line for multiple reasons:
1905  // 1) Napoca does not support the scan engines, so they can not call our callback function
1906  // (resulting in a memory leak since the callback function is used to free the command line buffer).
1907  // 2) Reading the command line using #PF can bring an unnecessary performance penalty.
1908  if (!pProc->Outswapped)
1909  {
1911  {
1912  status = IntWinProcReadCommandLine(pProc);
1913  if (!INT_SUCCESS(status))
1914  {
1915  ERROR("[ERROR] IntWinProcReadCommandLine failed: 0x%x\n", status);
1916  }
1917  }
1918  else
1919  {
1920  for (DWORD i = 0; i < ARRAYSIZE(gCmdLineProcesses); i++)
1921  {
1922  if (0 == strncmp(pProc->Name, gCmdLineProcesses[i], strlen(pProc->Name)))
1923  {
1924  status = IntWinProcReadCommandLine(pProc);
1925  if (!INT_SUCCESS(status))
1926  {
1927  ERROR("[ERROR] IntWinProcReadCommandLine failed: 0x%x\n", status);
1928  }
1929 
1930  break;
1931  }
1932  }
1933  }
1934  }
1935 
1936  if (pProc->LateProtection || pProc->StaticDetected || pProc->SystemProcess)
1937  {
1938  pProc->StartInitializing = TRUE;
1939  pProc->Initialized = TRUE;
1940 
1941  // don't allow one time exceptions for static detected processes
1942  pProc->OneTimeInjectionDone = TRUE;
1943  }
1944 
1945  if (pProc->Protected)
1946  {
1947  pProc->ExploitGuardEnabled = IntWinProcIsExploitGuardEnabled(EprocessAddress, EprocessBuffer);
1948  TRACE("[WINPROC] Process `%s` has Exploit Guard %s\n",
1949  pProc->Name, pProc->ExploitGuardEnabled ? "Enabled" : "Disabled");
1950  }
1951 
1953 
1954  if (pProc->StaticDetected && !pProc->IsAgent)
1955  {
1956  pProc->IsAgent = pProc->IsPreviousAgent = '?' == pProc->Name[14];
1957  }
1958 
1959  if (!pProc->Outswapped)
1960  {
1961  status = IntWinSelfMapGetAndCheckSelfMapEntry(pProc);
1962  if (!INT_SUCCESS(status))
1963  {
1964  ERROR("[ERROR] IntWinProcGetAndCheckSelfMapEntry failed: 0x%08x\n", status);
1965  }
1966  }
1967 
1968  if (__unlikely(4 == pProc->Pid))
1969  {
1970  status = IntWinSelfMapProtectSelfMapIndex(pProc);
1971  if (!INT_SUCCESS(status))
1972  {
1973  ERROR("[ERROR] IntWinProcProtectSelfMapIndex failed: 0x%08x\n", status);
1974  }
1975  }
1976 
1977  if (!pProc->Outswapped)
1978  {
1979  status = IntWinProcProtect(pProc);
1980  if (!INT_SUCCESS(status))
1981  {
1982  ERROR("[ERROR] IntWinProcProtect failed: 0x%08x\n", status);
1983  }
1984  }
1985 
1986  if (!pProc->MonitorVad && !pProc->Outswapped)
1987  {
1988  // NOTE: The VAD tree is not imported when the process is out-swapped because the #WIN_PROCESS_OBJECT will be
1989  // deleted and a new #WIN_PROCESS_OBJECT will be created.
1990  status = IntWinVadProcImportMainModuleVad(pProc);
1991  if (!INT_SUCCESS(status))
1992  {
1993  ERROR("[ERROR] IntWinProcImportMainModuleVad failed: 0x%08x\n", status);
1994  }
1995  }
1996 
1997  status = IntWinProcSendProcessEvent(pProc, TRUE, FALSE);
1998  if (!INT_SUCCESS(status))
1999  {
2000  ERROR("[ERROR] IntWinProcSendProcessEvent failed: 0x%08x\n", status);
2001  }
2002 
2003  status = IntWinProcSendAgentEvent(pProc, TRUE);
2004  if (!INT_SUCCESS(status))
2005  {
2006  ERROR("[ERROR] IntWinProcSendAgentEvent failed: 0x%08x\n", status);
2007  }
2008 
2009  TRACE("[PROCESS] '%s' (%08x), path %s, pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, "
2010  "UserCR3 0x%016llx, parent at 0x%016llx/0x%016llx; %s, %s %s\n",
2011  pProc->Name, pProc->NameHash, pProc->Path ? utf16_for_log(pProc->Path->Path) : "<invalid>",
2012  Pid, pProc->EprocessAddress, pProc->Cr3, pProc->UserCr3, ParentEprocess, RealParentEprocess,
2013  pProc->SystemProcess ? "SYSTEM" : "not system", pProc->IsAgent ? "AGENT" : "not agent",
2014  pProc->Outswapped ? ", Outswapped" : "");
2015 
2016  *Process = pProc;
2017 
2018  return INT_STATUS_SUCCESS;
2019 
2020 cleanup_and_exit:
2021  if (NULL != pProc)
2022  {
2023  IntWinProcRemoveProcess(pProc);
2024  }
2025 
2026  return status;
2027 }
2028 
2029 
2030 static INTSTATUS
2032  _In_ WIN_PROCESS_OBJECT *Process
2033  )
2044 {
2045  INTSTATUS status;
2046 
2047  if (NULL != Process->Cr3PageLockObject)
2048  {
2049  status = IntWinPfnRemoveLock(Process->Cr3PageLockObject, FALSE);
2050  if (!INT_SUCCESS(status))
2051  {
2052  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
2053  }
2054 
2055  Process->Cr3PageLockObject = NULL;
2056  }
2057 
2058  if (NULL != Process->UserCr3PageLockObject)
2059  {
2060  status = IntWinPfnRemoveLock(Process->UserCr3PageLockObject, FALSE);
2061  if (!INT_SUCCESS(status))
2062  {
2063  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
2064  }
2065 
2066  Process->UserCr3PageLockObject = NULL;
2067  }
2068 
2069  // Restore the first two letters in the spare
2071  Process->EprocessAddress + WIN_KM_FIELD(Process, Spare),
2072  2,
2073  &Process->OriginalSpareValue,
2074  IG_CS_RING_0);
2075  if (!INT_SUCCESS(status))
2076  {
2077  ERROR("[ERROR] IntKernVirtMemWrite failed: 0x%08x\n", status);
2078  }
2079 
2080  // Remove the command line swap handle.
2081  if (NULL != Process->CmdBufSwapHandle)
2082  {
2083  status = IntSwapMemRemoveTransaction(Process->CmdBufSwapHandle);
2084  if (!INT_SUCCESS(status))
2085  {
2086  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2087  }
2088 
2089  Process->CmdBufSwapHandle = NULL;
2090  }
2091 
2092  if (NULL != Process->CmdLineSwapHandle)
2093  {
2094  status = IntSwapMemRemoveTransaction(Process->CmdLineSwapHandle);
2095  if (!INT_SUCCESS(status))
2096  {
2097  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2098  }
2099 
2100  Process->CmdLineSwapHandle = NULL;
2101  }
2102 
2103  if (NULL != Process->ParamsSwapHandle)
2104  {
2105  status = IntSwapMemRemoveTransaction(Process->ParamsSwapHandle);
2106  if (!INT_SUCCESS(status))
2107  {
2108  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2109  }
2110 
2111  Process->ParamsSwapHandle = NULL;
2112  }
2113 
2114  if (NULL != Process->Subsystemx64)
2115  {
2116  status = IntWinProcRemoveSubsystem(Process->Subsystemx64);
2117  if (!INT_SUCCESS(status))
2118  {
2119  ERROR("[ERROR] IntWinProcRemoveSubsystem failed: 0x%08x\n", status);
2120  }
2121 
2122  Process->Subsystemx64 = NULL;
2123  }
2124 
2125  if (NULL != Process->Subsystemx86)
2126  {
2127  status = IntWinProcRemoveSubsystem(Process->Subsystemx86);
2128  if (!INT_SUCCESS(status))
2129  {
2130  ERROR("[ERROR] IntWinProcRemoveSubsystem failed: 0x%08x\n", status);
2131  }
2132 
2133  Process->Subsystemx86 = NULL;
2134  }
2135 
2136  if (NULL != Process->MainModuleVad)
2137  {
2138  IntWinVadDestroyObject((VAD **)&Process->MainModuleVad);
2139  }
2140 
2142 
2143  // This must be the last thing done - we must call this AFTER removing all the other transactions
2144  // (those with handle) otherwise we may cause a use-after-free. Also, this must be done for TIB swaps - on
2145  // suspicious page executions, sometimes we need to swap in the TIB; there is no way to cleanly save handles for
2146  // those, since a page may be executed in the context of multiple threads, which would mean that it could be
2147  // possible to request multiple TIB swaps for the same page.
2148  status = IntSwapMemRemoveTransactionsForVaSpace(Process->Cr3);
2149  if (!INT_SUCCESS(status))
2150  {
2151  ERROR("[ERROR] IntSwapMemRemoveTransactionsForVaSpace failed: 0x%08x\n", status);
2152  }
2153 
2154  if (NULL != Process->VadPages)
2155  {
2156  HpFreeAndNullWithTag(&Process->VadPages, IC_TAG_VADP);
2157  }
2158 
2159  if (NULL != Process->CommandLine)
2160  {
2161  HpFreeAndNullWithTag(&Process->CommandLine, IC_TAG_PCMD);
2162  }
2163 
2164  HpFreeAndNullWithTag(&Process, IC_TAG_POBJ);
2165 
2166  return INT_STATUS_SUCCESS;
2167 }
2168 
2169 
2170 static INTSTATUS
2172  _In_ QWORD EprocessAddress,
2173  _In_ QWORD Cr3,
2174  _In_ DWORD Pid
2175  )
2190 {
2191  INTSTATUS status = INT_STATUS_SUCCESS;
2192  BOOLEAN bFound = FALSE;
2193  BOOLEAN isAgent = FALSE;
2194 
2195  LIST_ENTRY *list = gWinProcesses.Flink;
2196  while (list != &gWinProcesses)
2197  {
2199 
2200  list = list->Flink;
2201 
2202  // Reset the parent EPROCESS for every process that has the terminated process as a parent.
2203  if (pProc->ParentEprocess == EprocessAddress)
2204  {
2205  pProc->ParentEprocess = 0;
2206  }
2207 
2208  if (pProc->RealParentEprocess == EprocessAddress)
2209  {
2210  pProc->RealParentEprocess = 0;
2211  }
2212 
2213  if ((pProc->Pid == Pid) && (pProc->EprocessAddress == EprocessAddress) && (pProc->Cr3 == Cr3))
2214  {
2215  BOOLEAN bCrashed = FALSE;
2216  BOOLEAN lastAgent = FALSE;
2217 
2218  bFound = TRUE;
2219  pProc->Terminating = TRUE;
2220 
2221  // Get the crashed flag from the EPROCESS.
2222  if (0 != WIN_KM_FIELD(Process, Flags3))
2223  {
2224  DWORD flags3 = 0;
2225 
2226  status = IntKernVirtMemFetchDword(pProc->EprocessAddress + WIN_KM_FIELD(Process, Flags3), &flags3);
2227  if (!INT_SUCCESS(status))
2228  {
2229  ERROR("[ERROR] IntKernVirtMemFetchDword failed for 0x%016llx: 0x%08x\n",
2230  pProc->EprocessAddress + WIN_KM_FIELD(Process, Flags3), status);
2231  }
2232  else
2233  {
2234  bCrashed = 0 != (WIN_KM_FIELD(EprocessFlags, 3Crashed) & flags3);
2235  }
2236  }
2237 
2238  if (0 != WIN_KM_FIELD(Process, ExitStatus))
2239  {
2240  status = IntKernVirtMemFetchDword(EprocessAddress + WIN_KM_FIELD(Process, ExitStatus),
2241  &pProc->ExitStatus);
2242  if (!INT_SUCCESS(status))
2243  {
2244  ERROR("[ERROR] IntKernVirtMemFetchDword failed for 0x%016llx: 0x%08x\n",
2245  EprocessAddress + WIN_KM_FIELD(Process, ExitStatus), status);
2246  }
2247  }
2248 
2249  if (bCrashed)
2250  {
2251  TRACE("[PROCESS] Process `%d` with Eprocess at 0x%016llx and Cr3 0x%016llx crashed.\n",
2252  pProc->Pid, pProc->EprocessAddress, pProc->Cr3);
2253  }
2254 
2255  IntWinAgentCheckIfProcessAgentAndDecrement(pProc->Name, &isAgent, &pProc->AgentTag, &lastAgent);
2256  pProc->IsAgent = isAgent;
2257 
2258  TRACE("[PROCESS] '%s', pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, UserCR3 0x%016llx just terminated\n",
2259  pProc->Name, pProc->Pid, pProc->EprocessAddress, pProc->Cr3, pProc->UserCr3);
2260 
2261  status = IntWinProcSendProcessExceptionEvent(pProc);
2262  if (!INT_SUCCESS(status))
2263  {
2264  ERROR("[ERROR] IntWinProcSendProcessExceptionEvent failed: 0x%08x\n", status);
2265  }
2266 
2267  status = IntWinProcSendProcessEvent(pProc, FALSE, bCrashed);
2268  if (!INT_SUCCESS(status))
2269  {
2270  ERROR("[ERROR] IntWinProcSendProcessEvent failed: 0x%08x\n", status);
2271  }
2272 
2273  if (lastAgent)
2274  {
2275  status = IntWinProcSendAgentEvent(pProc, FALSE);
2276  if (!INT_SUCCESS(status))
2277  {
2278  ERROR("[ERROR] IntWinProcSendAgentEvent failed: 0x%08x\n", status);
2279  }
2280  }
2281 
2283 
2284  status = IntWinSelfMapUnprotectSelfMapIndex(pProc);
2285  if (!INT_SUCCESS(status))
2286  {
2287  ERROR("[ERROR] IntWinProcUnprotectSelfMapIndex failed: 0x%08x\n", status);
2288  }
2289 
2290  if (pProc->Protected)
2291  {
2292  status = IntWinProcUnprotect(pProc);
2293  if (!INT_SUCCESS(status))
2294  {
2295  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
2296  }
2297  }
2298 
2299  // validate one last time the token privileges
2301  {
2303  if (!INT_SUCCESS(status) && (INT_STATUS_PAGE_NOT_PRESENT != status))
2304  {
2305  ERROR("[ERROR] IntWinTokenPrivsCheckIntegrityOnProcess failed: 0x%08x\n", status);
2306  }
2307  }
2308 
2309  // Validate one last time token and self map integrity
2311  {
2312  status = IntWinTokenPtrCheckIntegrityOnProcess(pProc);
2313  if (!INT_SUCCESS(status) && (INT_STATUS_PAGE_NOT_PRESENT != status))
2314  {
2315  ERROR("[ERROR] IntWinProcTokenCheckIntegrityInternal failed: 0x%08x\n", status);
2316  }
2317  }
2318 
2319  status = IntWinSelfMapGetAndCheckSelfMapEntry(pProc);
2320  if (!INT_SUCCESS(status))
2321  {
2322  ERROR("[ERROR] IntWinSelfMapGetAndCheckSelfMapEntry failed: 0x%08x\n", status);
2323  }
2324 
2325  status = IntWinProcRemoveProcess(pProc);
2326  if (!INT_SUCCESS(status))
2327  {
2328  ERROR("[ERROR] IntWinProcRemoveProcess failed: 0x%08x\n", status);
2329  }
2330  }
2331  }
2332 
2333  // Remove this process's entries from the list of pending UDs as this process terminated
2335 
2336  if (!bFound)
2337  {
2338  return INT_STATUS_NOT_FOUND;
2339  }
2340 
2341  return status;
2342 }
2343 
2344 
2345 INTSTATUS
2347  _In_ QWORD FunctionAddress,
2348  _In_ void *Handler,
2349  _In_ void *Descriptor
2350  )
2365 {
2366  PAPI_HOOK_HANDLER pHandler = Handler;
2367  DWORD offsetRetn = 0x09;
2368 
2369  UNREFERENCED_PARAMETER(FunctionAddress);
2370  UNREFERENCED_PARAMETER(Descriptor);
2371 
2372  if (gGuest.OSVersion == 7600 || gGuest.OSVersion == 9200)
2373  {
2374  pHandler->Code[offsetRetn] = 0x1C;
2375  }
2376 
2377  if (gGuest.OSVersion == 7601 || gGuest.OSVersion == 7602)
2378  {
2379  pHandler->Code[offsetRetn] = 0x20;
2380  }
2381 
2382  return INT_STATUS_SUCCESS;
2383 }
2384 
2385 
2386 INTSTATUS
2388  _In_ QWORD FunctionAddress,
2389  _In_ void *Handler,
2390  _In_ void *Descriptor
2391  )
2401 {
2402  PAPI_HOOK_HANDLER pHandler = Handler;
2403  PAPI_HOOK_DESCRIPTOR pDescriptor = Descriptor;
2404  DWORD offset = 0x01;
2405  BYTE instruction[7] = { 0 };
2406 
2407  UNREFERENCED_PARAMETER(FunctionAddress);
2408 
2409  instruction[0] = 0x48;
2410  instruction[1] = 0x8b;
2411 
2412  switch (pDescriptor->Arguments.Argv[0])
2413  {
2414  case NDR_RBX:
2415  instruction[2] = 0x83;
2416  break;
2417 
2418  case NDR_RDI:
2419  instruction[2] = 0x87;
2420  break;
2421 
2422  case NDR_RSI:
2423  instruction[2] = 0x86;
2424  break;
2425 
2426  case NDR_RBP:
2427  instruction[1] = 0x85;
2428  break;
2429 
2430  default:
2431  return INT_STATUS_NOT_SUPPORTED;
2432  }
2433 
2434  *(DWORD *)(instruction + 3) = WIN_KM_FIELD(Process, Flags);
2435 
2436  memcpy(pHandler->Code + offset, instruction, sizeof(instruction));
2437 
2438  return INT_STATUS_SUCCESS;
2439 }
2440 
2441 
2442 INTSTATUS
2444  _In_ QWORD FunctionAddress,
2445  _In_ void *Handler,
2446  _In_ void *Descriptor
2447  )
2457 {
2458  PAPI_HOOK_HANDLER pHandler = Handler;
2459  PAPI_HOOK_DESCRIPTOR pDescriptor = Descriptor;
2460  BYTE instruction[6] = { 0 };
2461  DWORD offset = 0x01;
2462 
2463  UNREFERENCED_PARAMETER(FunctionAddress);
2464 
2465  instruction[0] = 0x8b;
2466 
2467  switch (pDescriptor->Arguments.Argv[0])
2468  {
2469  case NDR_RSI:
2470  instruction[1] = 0x86;
2471  break;
2472 
2473  case NDR_RBX:
2474  instruction[1] = 0x83;
2475  break;
2476 
2477  case NDR_RDI:
2478  instruction[1] = 0x87;
2479  break;
2480 
2481  default:
2482  return INT_STATUS_NOT_SUPPORTED;
2483  }
2484 
2485  *(DWORD *)(instruction + 2) = WIN_KM_FIELD(Process, Flags);
2486 
2487  memcpy(pHandler->Code + offset, instruction, sizeof(instruction));
2488 
2489  return INT_STATUS_SUCCESS;
2490 }
2491 
2492 
2493 static WIN_PROCESS_OBJECT *
2495  _In_ QWORD NewEprocess,
2496  _In_ QWORD ParentEprocess,
2497  _In_ QWORD DebugHandle,
2498  _Out_ INTRO_ACTION *Action
2499  )
2517 {
2518  INTSTATUS status;
2519  IG_ARCH_REGS *pRegs = &gVcpu->Regs;
2520  DWORD pid = 0;
2521  QWORD cr3, realParentEproc;
2522  PBYTE eprocessBuffer = NULL;
2523  WIN_PROCESS_OBJECT *pProc, *pParent;
2525  BOOLEAN skipChecks = FALSE;
2526 
2527  pProc = pParent = NULL;
2528 
2529  status = IntWinProcMapEprocess(NewEprocess, &eprocessBuffer);
2530  if (!INT_SUCCESS(status))
2531  {
2532  ERROR("[ERROR] IntWinProcMapEprocess failed: 0x%08x\n", status);
2533  goto _set_action_and_leave;
2534  }
2535 
2536  pid = *(DWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Id));
2537 
2538  if (gGuest.Guest64)
2539  {
2540  cr3 = *(QWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Cr3));
2541  }
2542  else
2543  {
2544  cr3 = *(DWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Cr3));
2545  }
2546 
2547  // First, try to get the real parent (by current Cr3)
2548  pParent = IntWinProcFindObjectByCr3(pRegs->Cr3);
2549  if (NULL == pParent)
2550  {
2551  // In case this fails, try to get it by the eprocess that Windows considers the parent
2552  pParent = IntWinProcFindObjectByEprocess(ParentEprocess);
2553  if (__unlikely(NULL == pParent && 4 == pid))
2554  {
2555  // System process does not have a parent
2556  skipChecks = TRUE;
2557  }
2558  else if (NULL == pParent)
2559  {
2560  CRITICAL("[ERROR] Both the real parent (Cr3 = 0x%016llx) and the parent "
2561  "(eprocess = 0x%016llx) are NULL for pid %d!\n", pRegs->Cr3, ParentEprocess, pid);
2562 
2563  goto _cleanup_and_leave;
2564  }
2565  }
2566 
2567  realParentEproc = pParent ? pParent->EprocessAddress : 0;
2568 
2569  status = IntWinProcCreateProcessObject(&pProc, NewEprocess, eprocessBuffer, ParentEprocess,
2570  realParentEproc, cr3, pid, FALSE);
2571  if (!INT_SUCCESS(status))
2572  {
2573  ERROR("[ERROR] IntWinProcCreateProcessObject failed: 0x%08x\n", status);
2574  goto _cleanup_and_leave;
2575  }
2576 
2577  if (skipChecks)
2578  {
2579  INFO("[INFO] Process %s (%d/0x%016llx) doesn't have either parent or real parent, will skip all checks\n",
2580  pProc->Name, pProc->Pid, pProc->EprocessAddress);
2581  goto _cleanup_and_leave;
2582  }
2583 
2584  if (__likely(pParent->Pid != 4))
2585  {
2587 
2588  IntWinDpiGatherDpiInfo(pProc, pParent, DebugHandle);
2589 
2591  }
2592 
2594 
2595  action = IntWinDpiCheckCreation(pProc, pParent);
2596 
2598 
2599 _cleanup_and_leave:
2600  IntVirtMemUnmap(&eprocessBuffer);
2601 
2602 _set_action_and_leave:
2603  *Action = action;
2604 
2605  return pProc;
2606 }
2607 
2608 
2609 INTSTATUS
2611  _In_ void *Detour
2612  )
2624 {
2625  INTSTATUS status;
2626  QWORD args[3] = { 0 };
2627  QWORD eprocess, parentEproc;
2628  QWORD possibleDebugHandle;
2629  INTRO_ACTION action;
2630  WIN_PROCESS_OBJECT *newProc;
2631 
2632  status = IntDetGetArguments(Detour, ARRAYSIZE(args), args);
2633  if (!INT_SUCCESS(status))
2634  {
2635  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
2636  return INT_STATUS_SUCCESS;
2637  }
2638 
2639  eprocess = args[0];
2640  parentEproc = args[1];
2641  possibleDebugHandle = args[2];
2642 
2643  newProc = IntWinProcHandleCreateInternal(eprocess, parentEproc, possibleDebugHandle, &action);
2644  if (newProc == NULL)
2645  {
2646  ERROR("[ERROR] IntWinProcHandleCreateInternal failed for 0x%016llx\n", eprocess);
2647  return INT_STATUS_SUCCESS;
2648  }
2649 
2650  if (introGuestNotAllowed == action)
2651  {
2652  IG_ARCH_REGS *pRegs = &gVcpu->Regs;
2653 
2654  status = IntWinProcDeleteProcessObject(newProc->EprocessAddress, newProc->Cr3, newProc->Pid);
2655  if (!INT_SUCCESS(status))
2656  {
2657  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
2658  }
2659 
2660  // IntWinProcHandleCreate is the callback for when PspInsertProcess
2661  // is invoked. After the INT3 that causes the VmExit, there is a JMP
2662  // that sets the RIP to where the real PspInsertProcess call is - in case
2663  // the creation is allowed. On the other hand, blocking a process will be
2664  // done by incrementing the RIP (2 bytes) over the JMP (0xEB, 0x06), thus
2665  // setting the EAX to STATUS_ACCESS_DENIED and returning. For more information,
2666  // please consult "winhkhnd.c".
2667 
2668  pRegs->Rip += 0x02;
2669 
2670  status = IntSetGprs(gVcpu->Index, pRegs);
2671  if (!INT_SUCCESS(status))
2672  {
2673  ERROR("[ERROR] IntSetGprs failed: 0x%08x\n", status);
2674  }
2675  }
2676 
2677  return INT_STATUS_SUCCESS;
2678 }
2679 
2680 
2681 INTSTATUS
2683  _In_ void *Detour
2684  )
2696 {
2697  INTSTATUS status;
2698  DWORD pid;
2699  QWORD eprocess, pdbrBase;
2700 
2701  pid = 0;
2702  pdbrBase = 0;
2703 
2704  status = IntDetGetArgument(Detour, 0, NULL, 0, &eprocess);
2705  if (!INT_SUCCESS(status))
2706  {
2707  ERROR("[ERROR] IntDetGetArgument failed: 0x%08x\n", status);
2708  goto cleanup_and_exit;
2709  }
2710 
2711  status = IntKernVirtMemFetchDword(eprocess + WIN_KM_FIELD(Process, Id), &pid);
2712  if (!INT_SUCCESS(status))
2713  {
2714  ERROR("[ERROR] IntKernVirtMemFetchDword failed: 0x%08x\n", status);
2715  goto cleanup_and_exit;
2716  }
2717 
2718  // Get the PDBR base.
2719  status = IntKernVirtMemFetchQword(eprocess + WIN_KM_FIELD(Process, Cr3), &pdbrBase);
2720  if (!INT_SUCCESS(status))
2721  {
2722  ERROR("IntKernVirtMemFetchQword failed for 0x%016llx: 0x%08x\n",
2723  eprocess + WIN_KM_FIELD(Process, Cr3), status);
2724  goto cleanup_and_exit;
2725  }
2726 
2727  if (!gGuest.Guest64)
2728  {
2729  pdbrBase &= 0xFFFFFFFF;
2730  }
2731 
2732  status = IntWinProcDeleteProcessObject(eprocess, pdbrBase, pid);
2733  if (!INT_SUCCESS(status) && (INT_STATUS_NOT_FOUND != status))
2734  {
2735  ERROR("[ERROR] IntWinProcDeleteProcessObject failed for EPROCESS %llx, CR3 %llx, pid %d: 0x%08x\n",
2736  eprocess, pdbrBase, pid, status);
2737  }
2738 
2739 cleanup_and_exit:
2740 
2741  return status;
2742 }
2743 
2744 
2745 INTSTATUS
2747  _In_ QWORD FunctionAddress,
2748  _In_ void *Handler,
2749  _In_ void *Descriptor
2750  )
2765 {
2766  PAPI_HOOK_HANDLER pHandler = Handler;
2767 
2768  UNREFERENCED_PARAMETER(FunctionAddress);
2769  UNREFERENCED_PARAMETER(Descriptor);
2770 
2771  if (gGuest.Guest64)
2772  {
2773  *(DWORD *)(pHandler->Code + 0xD) = WIN_KM_FIELD(Process, Cr3);
2774 
2775  *(DWORD *)(pHandler->Code + 0x16) = WIN_KM_FIELD(Process, Spare);
2776  *(DWORD *)(pHandler->Code + 0x21) = WIN_KM_FIELD(Process, Spare);
2777 
2778  *(DWORD *)(pHandler->Code + 0x2c) = WIN_KM_FIELD(Process, Spare);
2779  *(DWORD *)(pHandler->Code + 0x36) = WIN_KM_FIELD(Process, Spare);
2780  }
2781  else
2782  {
2783  *(DWORD *)(pHandler->Code + 0x14) = WIN_KM_FIELD(Process, Cr3);
2784 
2785  *(DWORD *)(pHandler->Code + 0x1c) = WIN_KM_FIELD(Process, Spare);
2786  *(DWORD *)(pHandler->Code + 0x2f) = WIN_KM_FIELD(Process, Spare);
2787  }
2788 
2789  return INT_STATUS_SUCCESS;
2790 }
2791 
2792 
2793 static BOOLEAN
2795  _In_ QWORD SourceAddress,
2796  _In_ DWORD ReadSize,
2797  _In_ const WIN_PROCESS_OBJECT *Lsass,
2798  _Out_ WIN_PROCESS_MODULE **VictimModule
2799  )
2812 {
2813  QWORD srcEnd = SourceAddress + ReadSize - 1;
2814  LIST_ENTRY *list, *head;
2815  WIN_PROCESS_MODULE *pLsassMod = NULL;
2816 
2817  // LSASS will only exist in either 64 or 32 bit form, depending on the OS.
2818  if (Lsass->Subsystemx64)
2819  {
2820  head = &Lsass->Subsystemx64->ProcessModules;
2821  }
2822  else
2823  {
2824  head = &Lsass->Subsystemx86->ProcessModules;
2825  }
2826 
2827  // We assume one cannot read more than a single module at one time. If someone does that, we'll block it.
2828  list = head->Flink;
2829  while (list != head)
2830  {
2831  pLsassMod = CONTAINING_RECORD(list, WIN_PROCESS_MODULE, Link);
2832 
2833  list = list->Flink;
2834 
2835  // Ignore the MZ/PE headers.
2836  if (((SourceAddress >= pLsassMod->VirtualBase + PAGE_SIZE) &&
2837  (SourceAddress < pLsassMod->VirtualBase + pLsassMod->Size)) ||
2838  ((srcEnd >= pLsassMod->VirtualBase + PAGE_SIZE) &&
2839  (srcEnd < pLsassMod->VirtualBase + pLsassMod->Size)))
2840  {
2841  break;
2842  }
2843 
2844  pLsassMod = NULL;
2845  }
2846 
2847  *VictimModule = pLsassMod;
2848 
2849  if (NULL != pLsassMod)
2850  {
2851  // If this is ntdll or the main module, bail out.
2852  if (pLsassMod->Path->NameHash == NAMEHASH_NTDLL || pLsassMod->IsMainModule)
2853  {
2854  return TRUE;
2855  }
2856  }
2857  else
2858  {
2859  // Allow reads from everything that is not a module - a lot of legitimate reads are done from various heap
2860  // locations from lsass, and that can cause performance problems; blocking reads from modules is enough
2861  // for blocking credential stealing.
2862  return TRUE;
2863  }
2864 
2865  return FALSE;
2866 }
2867 
2868 
2869 INTSTATUS
2871  _In_ void *Detour
2872  )
2884 {
2885  INTSTATUS status;
2886  INTRO_ACTION action;
2887  INTRO_ACTION_REASON reason;
2888  PIG_ARCH_REGS pRegs;
2889  QWORD srcCr3, dstCr3;
2890  QWORD srcEproc, dstEproc;
2891  QWORD srcAddress, dstAddress;
2892  DWORD size;
2893  QWORD args[5];
2894  WIN_PROCESS_OBJECT *pSrcProc, *pDstProc;
2895  BOOLEAN isLsass, isRead;
2896  EXCEPTION_UM_ORIGINATOR originator;
2897  EXCEPTION_VICTIM_ZONE victim;
2898  PWIN_PROCESS_MODULE pLsassMod;
2899 
2900  action = introGuestAllowed;
2901  reason = introReasonUnknown;
2902  pSrcProc = pDstProc = NULL;
2903  isLsass = FALSE;
2904  pLsassMod = NULL;
2905 
2906  pRegs = &gVcpu->Regs;
2907 
2909 
2911  {
2912  status = INT_STATUS_SUCCESS;
2913  goto cleanup_and_exit;
2914  }
2915 
2916  status = IntDetGetArguments(Detour, 5, args);
2917  if (!INT_SUCCESS(status))
2918  {
2919  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
2920  goto cleanup_and_exit;
2921  }
2922 
2923  srcEproc = args[0];
2924  srcAddress = args[1];
2925  dstEproc = args[2];
2926  dstAddress = args[3];
2927  size = (DWORD)args[4];
2928 
2929  // If a write comes from the kernel, there's nothing we can do. We will simply allow it
2930  if (IS_KERNEL_POINTER_WIN(gGuest.Guest64, srcAddress))
2931  {
2932  goto cleanup_and_exit;
2933  }
2934 
2935  pDstProc = IntWinProcFindObjectByEprocess(dstEproc);
2936  if (NULL == pDstProc)
2937  {
2938  // If the process isn't found, than it has been terminated. We can safely leave.
2939  WARNING("[WARNING] IntWinProcFindObjectByEprocess failed for process 0x%016llx, "
2940  "current CR3 0x%016llx: 0x%08x\n",
2941  dstEproc, pRegs->Cr3, status);
2942 
2943  goto cleanup_and_exit;
2944  }
2945 
2946  pSrcProc = IntWinProcFindObjectByEprocess(srcEproc);
2947  if (NULL == pSrcProc)
2948  {
2949  goto cleanup_and_exit;
2950  }
2951 
2952  dstCr3 = pDstProc->Cr3;
2953 
2954  srcCr3 = pSrcProc->Cr3;
2955 
2956  // If source CR3 is the same as the destination CR3, then we have a ReadProcessMemory inside our own VA space,
2957  // which can be safely allowed.
2958  if (srcCr3 == dstCr3)
2959  {
2960  status = INT_STATUS_SUCCESS;
2961  goto cleanup_and_exit;
2962  }
2963 
2964  if (dstCr3 == pRegs->Cr3)
2965  {
2966  // We have a copy from p1 inside p2, and we are inside the context of p2 -> this is a read: p2 is
2967  // reading from p1.
2968  isRead = TRUE;
2969  }
2970  else
2971  {
2972  isRead = FALSE;
2973  }
2974 
2976 
2978  if (isRead && pDstProc->IsAgent)
2979  {
2980  action = introGuestAllowed;
2981  goto _stats_exit;
2982  }
2983 
2984  // Handle malicious process reads: check for processes attempting to read lsass.exe memory. We will ignore all
2985  // the other reads, as we're not interested in them.
2986  if (pSrcProc->Lsass && isRead)
2987  {
2988  isLsass = TRUE;
2989 
2990  if (IntWinProcHandleReadFromLsass(srcAddress, size, pSrcProc, &pLsassMod))
2991  {
2992  action = introGuestAllowed;
2993  goto _stats_exit;
2994  }
2995  }
2996  else
2997  {
2998  // We allow other process reads for now
2999  if (isRead)
3000  {
3001  status = INT_STATUS_SUCCESS;
3002  goto _stats_exit;
3003  }
3004 
3005  if (!pDstProc->Protected || !pDstProc->ProtWriteMem)
3006  {
3007  status = INT_STATUS_SUCCESS;
3008  goto _stats_exit;
3009  }
3010 
3011  // Mark the start of process initialization
3012  if (!pDstProc->StartInitializing && !pDstProc->Initialized)
3013  {
3014  if (0 == strcasecmp(pSrcProc->Name, "csrss.exe"))
3015  {
3016  pDstProc->StartInitializing = TRUE;
3017  }
3018  else
3019  {
3020  goto check_injection;
3021  }
3022  }
3023 
3024  // Allow every injection until the process starts to initialize (some come from kernel-mode,
3025  // and we have no way to except that)
3026  if (!pDstProc->StartInitializing && !pDstProc->Initialized)
3027  {
3028  status = INT_STATUS_SUCCESS;
3029  goto _stats_exit;
3030  }
3031  }
3032 
3033 check_injection:
3035 
3036  // If this is a read from lsass.exe, switch the source and the destination from now on, as we want to go through
3037  // the exceptions mechanism with the source of the attack being the destination process and the victim being
3038  // the source process (lsass.exe).
3039  if (isLsass)
3040  {
3041  void *auxproc;
3042  QWORD auxaddr;
3043 
3044  auxproc = pSrcProc;
3045  pSrcProc = pDstProc;
3046  pDstProc = auxproc;
3047 
3048  auxaddr = srcAddress;
3049  srcAddress = dstAddress;
3050  dstAddress = auxaddr;
3051  }
3052 
3053  memzero(&originator, sizeof(originator));
3054  memzero(&victim, sizeof(victim));
3055 
3057 
3058  status = IntExceptUserGetOriginator(pSrcProc, FALSE, srcAddress, NULL, &originator);
3059  if (!INT_SUCCESS(status))
3060  {
3061  reason = introReasonInternalError;
3062  action = introGuestNotAllowed;
3063 
3064  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
3065  goto _stop_count_and_notify;
3066  }
3067 
3068  status = IntExceptGetVictimProcess(pDstProc, dstAddress, size, isRead ? ZONE_READ : ZONE_WRITE, &victim);
3069  if (!INT_SUCCESS(status))
3070  {
3071  reason = introReasonInternalError;
3072  action = introGuestNotAllowed;
3073 
3074  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
3075  goto _stop_count_and_notify;
3076  }
3077 
3078  // The IntExceptGetVictimProcess either returns a valid VAD for the whole range, or NULL.
3079  // If there is no VAD (guest space was already scanned), we will still pass through exceptions and let the
3080  // guest handle the case (if allowed).
3081  if (NULL == victim.Object.Vad && pDstProc->MonitorVad)
3082  {
3083  WARNING("[WARNING] Injection (read: %d) from %s (%u) into %s "
3084  "(%u) for VA %llx with ""size %d (which has no VAD)!\n",
3085  isRead, pSrcProc->Name, pSrcProc->Pid, pDstProc->Name,
3086  pDstProc->Pid, dstAddress, size);
3087 
3088  for (QWORD currentDst = dstAddress; currentDst < dstAddress + size;)
3089  {
3090  VAD *pNewVad = IntWinVadFindAndUpdateIfNecessary(pDstProc, currentDst, 1);
3091  if (pNewVad)
3092  {
3093  WARNING("[WARNING] Vad-> [%llx -> %llx] (path: %s, stack: %d)\n",
3094  pNewVad->StartPage, pNewVad->EndPage,
3095  pNewVad->Path ? utf16_for_log(pNewVad->Path->Path) : "(none)", pNewVad->IsStack);
3096  currentDst += pNewVad->PageCount * PAGE_SIZE;
3097  }
3098  else
3099  {
3100  currentDst += PAGE_SIZE;
3101  }
3102  }
3103  }
3104 
3105  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventInjectionViolation);
3106 
3107 _stop_count_and_notify:
3109 
3110  STATS_ENTER(isRead ? statsCopyMemoryProtectedRead : statsCopyMemoryProtectedWrite);
3111 
3112  // Print lsass read details only if not allowed
3113  if (introGuestNotAllowed == action && isLsass && isRead && (NULL != pLsassMod))
3114  {
3115  LOG("[WINPROCESS] Suspicious read from lsass.exe: %s from process %s at address %llx:%d\n",
3116  utf16_for_log(pLsassMod->Path->Name), pSrcProc->Name, srcAddress, size);
3117  }
3118 
3119  if (IntPolicyProcTakeAction(PROC_OPT_PROT_WRITE_MEM, pDstProc, &action, &reason))
3120  {
3122 
3123  memzero(pInjEvent, sizeof(*pInjEvent));
3124 
3125  LOG("[ALERT] [INJECTION DETECTED] Injection took place from EPROCESS 0x%016llx with CR3 0x%016llx in " \
3126  "EPROCESS 0x%016llx with CR3 0x%016llx. CR3: 0x%016llx, IsRead: %s\n",
3127  srcEproc, srcCr3, dstEproc, dstCr3, pRegs->Cr3, isRead ? "yes" : "no");
3128 
3129  pInjEvent->Header.Action = action;
3130  pInjEvent->Header.Reason = reason;
3131 
3132  if (isRead && isLsass)
3133  {
3134  pInjEvent->Header.MitreID = idCredDump;
3135  }
3136  else
3137  {
3138  pInjEvent->Header.MitreID = idProcInject;
3139  }
3140 
3142  IntAlertFillWinProcess(pSrcProc, &pInjEvent->Originator.Process);
3143  IntAlertFillWinProcess(pDstProc, &pInjEvent->Victim.Process);
3145 
3146  if (victim.Object.Library.Module)
3147  {
3149  }
3150 
3151  if (victim.Object.Library.Export != NULL)
3152  {
3153  WIN_PROCESS_MODULE *pModule = victim.Object.Library.Module;
3154  WINUM_CACHE_EXPORT *pExport = victim.Object.Library.Export;
3155 
3156  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
3157  {
3158  strlcpy(pInjEvent->Export.Name[export], pExport->Names[export],
3159  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
3160 
3161  pInjEvent->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
3162  }
3163 
3164  strlcpy(pInjEvent->FunctionName,
3165  pExport->Names[0],
3166  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
3167 
3168  pInjEvent->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
3169 
3170  if (pModule != NULL)
3171  {
3172  pInjEvent->Export.Delta =
3173  (DWORD)(dstAddress - pModule->VirtualBase - victim.Object.Library.Export->Rva);
3174 
3175  pInjEvent->Delta =
3176  (DWORD)(dstAddress - pModule->VirtualBase - victim.Object.Library.Export->Rva);
3177  }
3178  }
3179 
3180  pInjEvent->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_WRITE_MEM, pDstProc, reason, 0);
3181 
3182  // If the the destination process is a system process, a flag will be set
3183  if (pDstProc->SystemProcess)
3184  {
3185  pInjEvent->Header.Flags |= ALERT_FLAG_SYSPROC;
3186  }
3187 
3188  // Injection violations are always from RING 3.
3189  pInjEvent->Header.Flags |= ALERT_FLAG_NOT_RING0;
3190 
3191  // Set the internal information
3192  pInjEvent->DestinationVirtualAddress = dstAddress;
3193  pInjEvent->SourceVirtualAddress = srcAddress;
3194  pInjEvent->CopySize = size;
3196 
3197  // read maximum 512 bytes form the source address into the alert. If this is a read, we won't include a buffer,
3198  // since we may end up sending sensitive info (see Mimikatz reading credentials from lsass memory).
3199  if (!isRead)
3200  {
3201  status = IntVirtMemRead(srcAddress,
3202  MIN(size, sizeof(pInjEvent->RawDump)),
3203  srcCr3,
3204  &pInjEvent->RawDump,
3205  NULL);
3206  if (INT_SUCCESS(status))
3207  {
3208  pInjEvent->DumpValid = TRUE;
3209  }
3210  }
3211 
3212  IntAlertFillVersionInfo(&pInjEvent->Header);
3213 
3214  status = IntNotifyIntroEvent(introEventInjectionViolation, pInjEvent, sizeof(*pInjEvent));
3215  if (!INT_SUCCESS(status))
3216  {
3217  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
3218  }
3219 
3220  status = INT_STATUS_SUCCESS;
3221  }
3222 
3223 _stats_exit:
3224  STATS_EXIT(isRead ? statsCopyMemoryRead : statsCopyMemoryWrite);
3225 
3226 cleanup_and_exit:
3228 
3229  if (pDstProc != NULL)
3230  {
3232  }
3233 
3234  status = IntDetSetReturnValue(Detour,
3235  pRegs,
3237  if (!INT_SUCCESS(status))
3238  {
3239  ERROR("[ERROR] IntDetSetReturnValue failed: 0x%08x\n", status);
3240  }
3241 
3242  return status;
3243 }
3244 
3245 
3246 INTSTATUS
3248  _In_ WIN_PROCESS_OBJECT *Process
3249  )
3258 {
3259  INTSTATUS status;
3260 
3261  if (NULL == Process)
3262  {
3264  }
3265 
3266  if (Process->Protected)
3267  {
3269  }
3270 
3271  Process->Context = 0;
3272 
3273  // Remove the protection.
3274  status = IntWinProcChangeProtectionFlags(Process, Process->ProtectionMask, 0);
3275  if (!INT_SUCCESS(status))
3276  {
3277  ERROR("[ERROR] IntWinProcChangeProtectionFlags failed: 0x%08x\n", status);
3278  }
3279 
3280  IntExceptInvCbCacheByCr3(Process->Cr3);
3281 
3282  return INT_STATUS_SUCCESS;
3283 }
3284 
3285 
3286 INTSTATUS
3288  _In_ WIN_PROCESS_OBJECT *Process
3289  )
3299 {
3300  INTSTATUS status;
3301 
3302  if (NULL == Process)
3303  {
3305  }
3306 
3307  if (!Process->Protected)
3308  {
3310  }
3311 
3312  // It is ok to do this here because if this function fails, it calls IntWinProcUnprotect which will decrement
3313  // the counter
3315 
3316  // Make sure enough memory is available.
3318  {
3319  WARNING("[WARNING] Not enough heap is available. Will NOT protect the process '%s'.\n", Process->Name);
3321  goto cleanup_and_exit;
3322  }
3323 
3324  TRACE("[PROCESS] Protecting process %s with CR3 0x%016llx, EPROC 0x%016llx, WOW64 %d, PEB at 0x%016llx," \
3325  "PEB32 at 0x%016llx, Parent 0x%016llx, ProtMask: 0x%08x, the process is %s.\n",
3326  Process->Name,
3327  Process->Cr3,
3328  Process->EprocessAddress,
3329  Process->Wow64Process,
3330  Process->Peb64Address,
3331  Process->Peb32Address,
3332  Process->ParentEprocess,
3333  Process->ProtectionMask,
3334  Process->StaticDetected ? "already created" : "being created");
3335 
3336  // Activate the protection.
3337  status = IntWinProcChangeProtectionFlags(Process, 0, Process->ProtectionMask);
3338  if (!INT_SUCCESS(status))
3339  {
3340  ERROR("[ERROR] IntWinProcChangeProtectionFlags failed: 0x%08x\n", status);
3341  goto cleanup_and_exit;
3342  }
3343 
3344  status = INT_STATUS_SUCCESS;
3345 
3346 cleanup_and_exit:
3347  if (!INT_SUCCESS(status))
3348  {
3349  INTSTATUS status2;
3350 
3351  status2 = IntWinProcUnprotect(Process);
3352  if (!INT_SUCCESS(status2))
3353  {
3354  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status2);
3355  }
3356 
3357  memset(&gErrorContext, 0, sizeof(gErrorContext));
3360 
3363  &gErrorContext);
3364  }
3365 
3366  return status;
3367 }
3368 
3369 
3372  void
3373  )
3382 {
3383  INTSTATUS status;
3384  WIN_PROCESS_OBJECT *pProc;
3385  VA_TRANSLATION tr;
3386  QWORD cr3;
3387  INTRO_ACTION action;
3388  INTRO_ACTION_REASON reason;
3389 
3391  {
3393  }
3394 
3395  if (!gGuest.GuestInitialized)
3396  {
3398  }
3399 
3401  {
3403  }
3404 
3405  cr3 = 0;
3406  action = introGuestNotAllowed;
3407  reason = introReasonUnknown;
3408 
3409  // Make sure we have at least one process.
3410  if (IsListEmpty(&gWinProcesses))
3411  {
3413  }
3414 
3415  // Get the System process, which is always the first one.
3416  pProc = (PWIN_PROCESS_OBJECT)gWinProcesses.Flink;
3417  if (4 != pProc->Pid)
3418  {
3419  ERROR("[ERROR] First process is not System: PID = %d\n", pProc->Pid);
3420  return INT_STATUS_NOT_FOUND;
3421  }
3422 
3423  // Translate the system EPROCESS to a physical address.
3424  status = IntTranslateVirtualAddressEx(pProc->EprocessAddress + WIN_KM_FIELD(Process, Cr3),
3426  TRFLG_PG_MODE,
3427  &tr);
3428  if (!INT_SUCCESS(status))
3429  {
3430  ERROR("[ERROR] IntTranslateVirtualAddressEx failed: 0x%08x\n", status);
3431  return status;
3432  }
3433 
3434  if (0 == (tr.Flags & PT_P))
3435  {
3437  }
3438 
3439  // Fetch the active PDBR for the System process.
3441  if (!INT_SUCCESS(status))
3442  {
3443  ERROR("[ERROR] IntGpaCacheFetchAndAdd failed: 0x%08x\n", status);
3444  return status;
3445  }
3446 
3447  if (!gGuest.Guest64)
3448  {
3449  // Note that CR3 is 32 bit wide in legacy paging mode and PAE mode.
3450  cr3 &= 0xFFFFFFFF;
3451  }
3452 
3453  if (cr3 != pProc->Cr3)
3454  {
3456 
3457  IntPauseVcpus();
3458 
3459  // Restore the original, if no BETA
3461  {
3462  action = introGuestNotAllowed;
3463  reason = introReasonNoException;
3464 
3465  status = IntVirtMemSafeWrite(0,
3466  pProc->EprocessAddress + WIN_KM_FIELD(Process, Cr3),
3467  gGuest.Guest64 ? sizeof(QWORD) : sizeof(DWORD),
3468  &pProc->Cr3,
3469  IG_CS_RING_0);
3470  if (!INT_SUCCESS(status))
3471  {
3472  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%x\n", status);
3473  }
3474  }
3475  else
3476  {
3477  // The action will be BETA detected, it will be allowed by default, so there is no use of
3478  // specifying it in the reason while the BETA flag is specified in the alert.
3479  action = introGuestAllowed;
3480  reason = introReasonAllowed;
3481  }
3482 
3483  pTrViol = &gAlert.Translation;
3484  memzero(pTrViol, sizeof(*pTrViol));
3485 
3486  pTrViol->Header.Flags = 0;
3487 
3488  pTrViol->Header.Flags |= ALERT_FLAG_ASYNC;
3490  {
3491  pTrViol->Header.Flags |= ALERT_FLAG_BETA;
3492  }
3493 
3494  pTrViol->Header.CpuContext.Valid = FALSE;
3495  pTrViol->Header.Action = action;
3496  pTrViol->Header.Reason = reason;
3497  pTrViol->Header.MitreID = idRootkit;
3498 
3500 
3501  // If VirtualAddress is -1, this means that we're dealing with an invalid CR3 modification. VirtualAddress
3502  // must be != -1 for all other types of translation violations.
3503  pTrViol->Victim.VirtualAddress = 0xFFFFFFFFFFFFFFFF;
3504  pTrViol->WriteInfo.OldValue[0] = pProc->Cr3;
3505  pTrViol->WriteInfo.NewValue[0] = cr3;
3506  pTrViol->WriteInfo.Size = sizeof(QWORD);
3508 
3509  IntAlertFillVersionInfo(&pTrViol->Header);
3510 
3511  status = IntNotifyIntroEvent(introEventTranslationViolation, pTrViol, sizeof(*pTrViol));
3512  if (!INT_SUCCESS(status))
3513  {
3514  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
3515  }
3516 
3517  IntResumeVcpus();
3518  }
3519 
3520  return INT_STATUS_SUCCESS;
3521 }
3522 
3523 
3524 static BOOLEAN
3526  _In_ const WCHAR *Path
3527  )
3534 {
3535  SIZE_T i = 0;
3536 
3537  while (Path[i] != 0)
3538  {
3539  if ((Path[i] == u'\\') || (Path[i] == u'/'))
3540  {
3541  return TRUE;
3542  }
3543 
3544  i++;
3545  }
3546 
3547  return FALSE;
3548 }
3549 
3550 
3551 static BOOLEAN
3553  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
3554  _In_ const WCHAR *FullPath,
3555  _In_ DWORD ProtectionMask,
3556  _In_ QWORD Context
3557  )
3572 {
3573  LIST_ENTRY *list, *pList;
3574 
3575  list = gWinProtectedProcesses.Flink;
3576  while (list != &gWinProtectedProcesses)
3577  {
3579 
3580  list = list->Flink;
3581 
3582  if ((0 == strcasecmp(pProc->ImageBaseNamePattern, BaseName)) &&
3583  (0 == wstrcasecmp(pProc->FullPathPattern, FullPath)) &&
3584  (pProc->Protection.Current == ProtectionMask))
3585  {
3586  // Change the context and bail out early on if the protection mask is the same
3587  if (pProc->Context != Context)
3588  {
3589  pProc->Context = Context;
3590 
3591  pList = gWinProcesses.Flink;
3592  while (pList != &gWinProcesses)
3593  {
3594  WIN_PROCESS_OBJECT *pProcObject = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
3595 
3596  pList = pList->Flink;
3597 
3598  if (!strcasecmp(pProcObject->Name, BaseName))
3599  {
3600  pProcObject->Context = Context;
3601  }
3602  }
3603  }
3604 
3605  return TRUE;
3606  }
3607  }
3608 
3609  return FALSE;
3610 }
3611 
3612 
3613 static INTSTATUS
3615  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
3616  _In_ const WCHAR *FullPath
3617  )
3629 {
3630  LIST_ENTRY *list;
3631 
3632  list = gWinProtectedProcesses.Flink;
3633  while (list != &gWinProtectedProcesses)
3634  {
3636 
3637  list = list->Flink;
3638 
3639  if ((0 == strcasecmp(pProc->ImageBaseNamePattern, BaseName)) &&
3640  (0 == wstrcasecmp(pProc->FullPathPattern, FullPath)))
3641  {
3642  memset(pProc->ImageBaseNamePattern, 0, IMAGE_BASE_NAME_LEN);
3643 
3645 
3646  RemoveEntryList(&pProc->Link);
3647 
3649  }
3650  }
3651 
3652  return INT_STATUS_SUCCESS;
3653 }
3654 
3655 
3656 void
3658  _In_ const void *Name,
3659  _In_ const CAMI_STRING_ENCODING Encoding,
3660  _In_ const CAMI_PROT_OPTIONS *Options
3661  )
3669 {
3670  LIST_ENTRY *list = gWinProtectedProcesses.Flink;
3671  while (list != &gWinProtectedProcesses)
3672  {
3674  BOOLEAN match = FALSE;
3675 
3676  list = list->Flink;
3677 
3678  switch (Encoding)
3679  {
3681  if (IntMatchPatternUtf8(Name, pProcess->ImageBaseNamePattern, 0))
3682  {
3683  match = TRUE;
3684  }
3685  break;
3687  if (IntMatchPatternUtf16(Name, pProcess->FullNamePattern, 0))
3688  {
3689  match = TRUE;
3690  }
3691  break;
3692  default:
3693  WARNING("[WARNING] Unsupported string encoding: %d\n", Encoding);
3694  }
3695 
3696  if (match)
3697  {
3698  pProcess->Protection.Current = pProcess->Protection.Original & ~(Options->ForceOff);
3699  pProcess->Protection.Beta = Options->ForceBeta;
3700  pProcess->Protection.Feedback = Options->ForceFeedback;
3701 
3702  TRACE("[CAMI] Protected process info updated '%s'. Original : 0x%x, "
3703  "Current : 0x%x, Beta : 0x%llx, Feedback : 0x%llx\n",
3704  pProcess->ImageBaseNamePattern, pProcess->Protection.Original,
3705  pProcess->Protection.Current, pProcess->Protection.Beta, pProcess->Protection.Feedback);
3706  }
3707  }
3708 }
3709 
3710 
3711 INTSTATUS
3713  _In_ const WCHAR *Path,
3714  _In_ DWORD ProtectionMask,
3715  _In_ QWORD Context
3716  )
3726 {
3727  INTSTATUS status;
3729  SIZE_T fplen;
3730  CHAR baseName[IMAGE_BASE_NAME_LEN] = { 0 };
3731  const WCHAR *fullName;
3732 
3733  if (NULL == Path)
3734  {
3736  }
3737 
3738  pProc = NULL;
3739 
3740  // Remove the drive name from the path.
3741  if ((Path[0] | 0x20) >= 'a' && (Path[0] | 0x20) <= 'z' && Path[1] == ':')
3742  {
3743  Path += 2;
3744  }
3745 
3746  fplen = wstrlen(Path);
3747  if ((0 == fplen) || (fplen >= 0x10000))
3748  {
3750  }
3751 
3752  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
3753 
3754  strlower_utf8(baseName, sizeof(baseName));
3755 
3756  // Check if an identical policy already exists. If so, bail out now.
3757  if (IntWinProcExistsProtectedProcess(baseName, Path, ProtectionMask, Context))
3758  {
3759  TRACE("[INFO] A policy for process '%s', base name '%s', flags 0x%08x already exits.\n",
3760  utf16_for_log(Path), baseName, ProtectionMask);
3762  }
3763 
3764  // First of all, remove any instance of this process from the protected list.
3766 
3767  // Now add a new one.
3768  pProc = HpAllocWithTag(sizeof(*pProc), IC_TAG_PPIF);
3769  if (NULL == pProc)
3770  {
3772  }
3773 
3774  pProc->FullPathPattern = HpAllocWithTag(fplen * sizeof(WCHAR) + 2, IC_TAG_PATH);
3775  if (NULL == pProc->FullPathPattern)
3776  {
3779  }
3780 
3781  pProc->Protection.Original = ProtectionMask;
3782  pProc->Protection.Current = ProtectionMask;
3783  pProc->Protection.Beta = 0;
3784  pProc->Protection.Feedback = 0;
3785 
3786  memcpy(pProc->ImageBaseNamePattern, baseName, IMAGE_BASE_NAME_LEN);
3787 
3788  memcpy(pProc->FullPathPattern, Path, fplen * sizeof(WCHAR));
3789  strlower_utf16(pProc->FullPathPattern, fplen);
3790 
3791  pProc->FullNamePattern = pProc->FullPathPattern + (fullName - Path);
3792 
3793  if (!IntWinProcIsFullPath(Path))
3794  {
3795  pProc->Flags |= PROT_PROC_FLAG_NO_PATH;
3796  }
3797  else
3798  {
3799  pProc->Flags = 0;
3800  }
3801 
3802  pProc->Context = Context;
3803 
3805 
3806  InsertTailList(&gWinProtectedProcesses, &pProc->Link);
3807 
3808  // UM introspection is not active, just leave.
3810  {
3811  return INT_STATUS_SUCCESS;
3812  }
3813 
3814  status = IntWinProcUpdateProtection();
3815  if (!INT_SUCCESS(status))
3816  {
3817  ERROR("[ERROR] IntWinProcUpdateProtection failed: 0x%08x\n", status);
3818  return status;
3819  }
3820 
3821  return status;
3822 }
3823 
3824 
3825 INTSTATUS
3827  _In_ const WCHAR *Path
3828  )
3836 {
3837  INTSTATUS status = INT_STATUS_SUCCESS;
3838  CHAR baseName[IMAGE_BASE_NAME_LEN] = {0};
3839  const WCHAR *fullName;
3840 
3841  if (NULL == Path)
3842  {
3844  }
3845 
3846  // Remove the drive name from the path.
3847  if ((Path[0] | 0x20) >= 'a' && (Path[0] | 0x20) <= 'z' && Path[1] == ':')
3848  {
3849  Path += 2;
3850  }
3851 
3852  if (0 == wstrlen(Path))
3853  {
3855  }
3856 
3857  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
3858 
3859  status = IntWinProcRemoveProtectedProcessInternal(baseName, Path);
3860  if (!INT_SUCCESS(status))
3861  {
3862  ERROR("[ERROR] IntWinProcRemoveProtectedProcessInternal failed: 0x%08x\n", status);
3863  goto cleanup_and_exit;
3864  }
3865 
3866  status = IntWinProcUpdateProtection();
3867  if (!INT_SUCCESS(status))
3868  {
3869  ERROR("[ERROR] IntWinProcUpdateProtection failed: 0x%08x\n", status);
3870  goto cleanup_and_exit;
3871  }
3872 
3873 cleanup_and_exit:
3874 
3875  return status;
3876 }
3877 
3878 
3879 INTSTATUS
3881  void
3882  )
3888 {
3889  LIST_ENTRY *list;
3890 
3891  list = gWinProtectedProcesses.Flink;
3892  while (list != &gWinProtectedProcesses)
3893  {
3895 
3896  list = list->Flink;
3897 
3898  memset(pProc->ImageBaseNamePattern, 0, IMAGE_BASE_NAME_LEN);
3899 
3901 
3902  RemoveEntryList(&pProc->Link);
3903 
3905  }
3906 
3907  return INT_STATUS_SUCCESS;
3908 }
3909 
3910 
3911 void
3913  void
3914  )
3918 {
3919  DWORD i = 0;
3920 
3921  for (LIST_ENTRY *list = gWinProtectedProcesses.Flink;
3922  list != &gWinProtectedProcesses;
3923  list = list->Flink)
3924  {
3926 
3927  LOG("# %04d %s, %08x, '%s':'%s'\n",
3928  i,
3929  pProc->ImageBaseNamePattern,
3930  pProc->Protection.Original,
3932  utf16_for_log(pProc->FullNamePattern));
3933 
3934  i++;
3935  }
3936 }
3937 
3938 
3939 void
3941  void
3942  )
3947 {
3948  LIST_ENTRY *list;
3949  INTSTATUS status;
3950 
3951  list = gWinProtectedProcesses.Flink;
3952  while (list != &gWinProtectedProcesses)
3953  {
3955 
3956  list = list->Flink;
3957 
3958  if (NULL != pTarget->FullPathPattern)
3959  {
3961  }
3962 
3963  RemoveEntryList(&pTarget->Link);
3964 
3965  HpFreeAndNullWithTag(&pTarget, IC_TAG_PPIF);
3966  }
3967 
3968  list = gWinProcesses.Flink;
3969  while (list != &gWinProcesses)
3970  {
3972 
3973  list = list->Flink;
3974 
3975  pProc->Terminating = TRUE;
3976 
3977  if (!gGuest.ShutDown && pProc->IsAgent)
3978  {
3979  IntWinProcMarkAgent(pProc, TRUE);
3980  }
3981 
3983 
3984  if (pProc->Protected)
3985  {
3986  status = IntWinProcUnprotect(pProc);
3987  if (!INT_SUCCESS(status))
3988  {
3989  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
3990  }
3991  }
3992 
3993  status = IntWinProcRemoveProcess(pProc);
3994  if (!INT_SUCCESS(status))
3995  {
3996  ERROR("[ERROR] IntWinProcRemoveProcess failed: 0x%08x\n", status);
3997  }
3998  }
3999 }
4000 
4001 
4002 INTSTATUS
4004  _In_ DWORD Pid,
4005  _Outptr_ WIN_PROCESS_OBJECT **Process
4006  )
4017 {
4018  LIST_ENTRY *list = NULL;
4019 
4020  if (NULL == Process)
4021  {
4023  }
4024 
4025  list = gWinProcesses.Flink;
4026  while (list != &gWinProcesses)
4027  {
4029 
4030  if (pProc->Pid == Pid)
4031  {
4032  *Process = pProc;
4033 
4034  return INT_STATUS_SUCCESS;
4035  }
4036 
4037  list = list->Flink;
4038  }
4039 
4040  return INT_STATUS_NOT_FOUND;
4041 }
4042 
4043 
4044 
4045 INTSTATUS
4047  _In_ WIN_PROCESS_OBJECT *Process,
4048  _In_ DWORD OldMask,
4049  _In_ DWORD NewMask
4050  )
4062 {
4063  INTSTATUS status;
4064  BOOLEAN vadWasMonitored;
4065 
4066  if (NULL == Process)
4067  {
4069  }
4070 
4071  if (OldMask == NewMask)
4072  {
4074  }
4075 
4076  vadWasMonitored = !!Process->MonitorVad;
4077 
4078  Process->ProtectionMask = NewMask;
4079  Process->Protected = NewMask != 0;
4080 
4081  if (!Process->Protected)
4082  {
4083  // Invalidate all the entries inside the ICACHE associated to this process,
4084  // since the CR3 will not be hooked anymore.
4085  status = IntIcFlushVaSpace(gGuest.InstructionCache, Process->Cr3);
4086  if (!INT_SUCCESS(status))
4087  {
4088  ERROR("[ERROR] IntIcFlushVaSpace failed: 0x%08x\n", status);
4089  }
4090  }
4091 
4092  // Set the BetaDetections policy
4093  if (Process->SystemProcess)
4094  {
4095  Process->BetaDetections = gGuest.SysprocBetaDetections;
4096  }
4097  else
4098  {
4099  Process->BetaDetections = !!(Process->ProtectionMask & PROC_OPT_BETA);
4100  }
4101 
4102  if (NewMask == 0)
4103  {
4104  Process->MonitorModules = FALSE;
4105  Process->MonitorVad = FALSE;
4106  }
4107  else
4108  {
4109  Process->MonitorModules = (!!(gGuest.CoreOptions.Current & INTRO_OPT_ENABLE_FULL_PATH) &&
4110  !Process->SystemProcess) ||
4111  (Process->ProtCoreModules || Process->ProtWsockModules || Process->ProtUnpack ||
4112  Process->Lsass || Process->ProtDoubleAgent);
4113 
4114  // Global per process flag that indicates if VAD is interesting for this process or not.
4115  Process->MonitorVad = (Process->MonitorModules || Process->ProtExploits);
4116  }
4117 
4118  // We must patch the in-guest protection indicator (used to be the first two characters in ImageName, now we use
4119  // some unused spare values) BEFORE actually trying to enable/disable protection. Otherwise, we may end up with a
4120  // process which has an altered spare value, which does not reflect the actual protection policy.
4121  status = IntWinProcPatchSpareValue(Process);
4122  if (!INT_SUCCESS(status))
4123  {
4124  ERROR("[ERROR] IntWinProcPatchSpareValue failed: 0x%08x\n", status);
4125  return status;
4126  }
4127 
4128  if ((OldMask & PROC_OPT_PROT_INJECTION) != (NewMask & PROC_OPT_PROT_INJECTION))
4129  {
4130  // we assume that if LateProtection and we must protect the injection, process is already initialized
4131  if ((NewMask & PROC_OPT_PROT_INJECTION) != 0 && Process->LateProtection)
4132  {
4133  Process->Initialized = TRUE;
4134  }
4135  }
4136 
4137  if ((OldMask & PROC_OPT_PROT_EXPLOIT) != (NewMask & PROC_OPT_PROT_EXPLOIT))
4138  {
4139  if (OldMask & PROC_OPT_PROT_EXPLOIT)
4140  {
4141  IntWinVadStopExploitMonitor(Process);
4142  }
4143  else
4144  {
4145  status = IntWinProcEnforceProcessDep(Process);
4146  if (!INT_SUCCESS(status))
4147  {
4148  ERROR("[ERROR] IntWinProcEnforceProcessDep failed: 0x%08x\n", status);
4149  return status;
4150  }
4151  }
4152  }
4153 
4156  {
4157  if (NULL != Process->Subsystemx86)
4158  {
4159  IntWinModulesChangeProtectionFlags(Process->Subsystemx86);
4160  }
4161 
4162  if (NULL != Process->Subsystemx64)
4163  {
4164  IntWinModulesChangeProtectionFlags(Process->Subsystemx64);
4165  }
4166  }
4167 
4168  if (vadWasMonitored && !Process->MonitorVad)
4169  {
4170  // We did VAD monitoring, but now we don't need to monitor the VAD - we can uninit the VAD tree.
4171  status = IntWinVadRemoveProcessTree(Process);
4172  if (!INT_SUCCESS(status))
4173  {
4174  ERROR("[ERROR] IntWinVadRemoveProcessTree failed: 0x%08x\n", status);
4175  return status;
4176  }
4177  }
4178  else if (!vadWasMonitored && Process->MonitorVad)
4179  {
4180  // VAD monitoring was off, but we need to turn it on, so read all the VADs from the guest space.
4181  status = IntWinVadImportProcessTree(Process);
4182  if (!INT_SUCCESS(status))
4183  {
4184  ERROR("[ERROR] IntWinVadImportProcessTree failed: 0x%08x\n", status);
4185  return status;
4186  }
4187  }
4188 
4189  // Remove or add hook on self map index
4190  if (Process->Protected && NULL == Process->SelfMapHook)
4191  {
4192  status = IntWinSelfMapProtectSelfMapIndex(Process);
4193  if (!INT_SUCCESS(status))
4194  {
4195  ERROR("[ERROR] IntWinProcProtectSelfMapIndex failed: 0x%08x\n", status);
4196  return status;
4197  }
4198  }
4199  else if (!Process->Protected && NULL != Process->SelfMapHook)
4200  {
4201  status = IntWinSelfMapUnprotectSelfMapIndex(Process);
4202  if (!INT_SUCCESS(status))
4203  {
4204  ERROR("[ERROR] IntWinProcUnprotectSelfMapIndex failed: 0x%08x\n", status);
4205  return status;
4206  }
4207  }
4208 
4209  return INT_STATUS_SUCCESS;
4210 }
4211 
4212 
4213 INTSTATUS
4215  _In_ void *Detour
4216  )
4236 {
4237  INTSTATUS status = INT_STATUS_SUCCESS;
4238  WIN_PROCESS_OBJECT *pProcess = NULL;
4239  QWORD eprocessAddr = 0;
4240  BYTE *pEprocessBuffer = NULL;
4241  QWORD eprocessParentAddr = 0;
4242  QWORD eprocessRealParentAddr = 0;
4243  QWORD cr3 = 0;
4244  DWORD pid = 0;
4245 
4246  status = IntDetGetArgument(Detour, 0, NULL, 0, &eprocessAddr);
4247  if (!INT_SUCCESS(status))
4248  {
4249  return status;
4250  }
4251 
4252  pProcess = IntWinProcFindObjectByEprocess(eprocessAddr);
4253  if (!pProcess)
4254  {
4255  ERROR("[ERROR] IntWinProcFindObjectByEprocess failed for Eprocess 0x%016llx with status: 0x%08x",
4256  eprocessAddr, status);
4257  return status;
4258  }
4259 
4260  if (!pProcess->Outswapped)
4261  {
4262  ERROR("[ERROR] Process '%s' swapped-in, but not swapped out!", pProcess->Name);
4264  }
4265 
4266  pProcess->Outswapped = FALSE;
4267 
4268  TRACE("[PROCESS-SWAP] Swapped in: '%s' (%08x), path %s, pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, "
4269  "UserCR3 0x%016llx, parent at 0x%016llx/0x%016llx; %s, %s\n",
4270  pProcess->Name, pProcess->NameHash, pProcess->Path ? utf16_for_log(pProcess->Path->Path) : "<invalid>",
4271  pProcess->Pid, pProcess->EprocessAddress, pProcess->Cr3, pProcess->UserCr3, pProcess->ParentEprocess, pProcess->RealParentEprocess,
4272  pProcess->SystemProcess ? "SYSTEM" : "not system", pProcess->IsAgent ? "AGENT" : "not agent");
4273 
4274  eprocessParentAddr = pProcess->ParentEprocess;
4275  eprocessRealParentAddr = pProcess->RealParentEprocess;
4276  pid = pProcess->Pid;
4277 
4278  status = IntWinProcDeleteProcessObject(pProcess->EprocessAddress, pProcess->Cr3, pProcess->Pid);
4279  if (!INT_SUCCESS(status))
4280  {
4281  ERROR("[ERROR] IntWinProcDeleteProcessObject failed with status: 0x%08x\n", status);
4282  }
4283 
4284  pProcess = NULL;
4285 
4286  status = IntWinProcMapEprocess(eprocessAddr, &pEprocessBuffer);
4287  if (!INT_SUCCESS(status))
4288  {
4289  ERROR("[ERROR] IntWinProcMapEprocess failed: 0x%08x\n", status);
4290  return status;
4291  }
4292 
4293  pid = *(DWORD *)(pEprocessBuffer + WIN_KM_FIELD(Process, Id));
4294 
4295  if (gGuest.Guest64)
4296  {
4297  cr3 = *(QWORD *)(pEprocessBuffer + WIN_KM_FIELD(Process, Cr3));
4298  }
4299  else
4300  {
4301  cr3 = *(DWORD *)(pEprocessBuffer + WIN_KM_FIELD(Process, Cr3));
4302  }
4303 
4304  status = IntWinProcCreateProcessObject(&pProcess, eprocessAddr, pEprocessBuffer, eprocessParentAddr,
4305  eprocessRealParentAddr, cr3, pid, TRUE);
4306  if (!INT_SUCCESS(status))
4307  {
4308  ERROR("[ERROR] IntWinProcCreateProcessObject failed with status: 0x%08x\n", status);
4309  }
4310 
4311  IntVirtMemUnmap(&pEprocessBuffer);
4312 
4313  return INT_STATUS_SUCCESS;
4314 }
4315 
4316 
4317 INTSTATUS
4319  _In_ void *Detour
4320  )
4337 {
4338  INTSTATUS status = INT_STATUS_SUCCESS;
4339  WIN_PROCESS_OBJECT *pProcess = NULL;
4340  QWORD eprocessAddr = 0;
4341 
4342  status = IntDetGetArgument(Detour, 0, NULL, 0, &eprocessAddr);
4343  if (!INT_SUCCESS(status))
4344  {
4345  return status;
4346  }
4347 
4348  pProcess = IntWinProcFindObjectByEprocess(eprocessAddr);
4349  if (!pProcess)
4350  {
4351  ERROR("[ERROR] IntWinProcFindObjectByEprocess failed for Eprocess 0x%016llx with status: 0x%08x",
4352  eprocessAddr, status);
4353  return status;
4354  }
4355 
4356  if (pProcess->Outswapped)
4357  {
4358  ERROR("[ERROR] Process '%s' already outswapped!", pProcess->Name);
4360  }
4361 
4362  pProcess->Outswapped = TRUE;
4363 
4364  status = IntWinProcUnlockCr3(pProcess);
4365  if (!INT_SUCCESS(status))
4366  {
4367  ERROR("[ERROR] IntWinProcUnlockCr3 failed for 0x%016llx with status: 0x%08x\n", pProcess->Cr3, status);
4368  }
4369 
4370  if (NULL != pProcess->CmdBufSwapHandle)
4371  {
4372  status = IntSwapMemRemoveTransaction(pProcess->CmdBufSwapHandle);
4373  if (!INT_SUCCESS(status))
4374  {
4375  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
4376  }
4377  else
4378  {
4379  pProcess->CmdBufSwapHandle = NULL;
4380  }
4381  }
4382 
4383  if (NULL != pProcess->ParamsSwapHandle)
4384  {
4385  status = IntSwapMemRemoveTransaction(pProcess->ParamsSwapHandle);
4386  if (!INT_SUCCESS(status))
4387  {
4388  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
4389  }
4390  else
4391  {
4392  pProcess->ParamsSwapHandle = NULL;
4393  }
4394  }
4395 
4396  if (NULL != pProcess->CmdLineSwapHandle)
4397  {
4398  status = IntSwapMemRemoveTransaction(pProcess->CmdLineSwapHandle);
4399  if (!INT_SUCCESS(status))
4400  {
4401  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
4402  }
4403  else
4404  {
4405  pProcess->CmdLineSwapHandle = NULL;
4406  }
4407  }
4408 
4409  status = IntWinProcUnprotect(pProcess);
4410  if (!INT_SUCCESS(status))
4411  {
4412  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
4413  }
4414 
4415  status = IntSwapMemRemoveTransactionsForVaSpace(pProcess->Cr3);
4416  if (!INT_SUCCESS(status))
4417  {
4418  ERROR("[ERROR] IntSwapMemRemoveTransactionsForVaSpace failed for CR3 0x%016llx with status: 0x%08x\n",
4419  pProcess->Cr3, status);
4420  }
4421 
4422  TRACE("[PROCESS-SWAP] Swapped out: '%s' (%08x), path %s, pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, "
4423  "UserCR3 0x%016llx, parent at 0x%016llx/0x%016llx; %s, %s\n",
4424  pProcess->Name, pProcess->NameHash, pProcess->Path ? utf16_for_log(pProcess->Path->Path) : "<invalid>",
4425  pProcess->Pid, pProcess->EprocessAddress, pProcess->Cr3, pProcess->UserCr3, pProcess->ParentEprocess, pProcess->RealParentEprocess,
4426  pProcess->SystemProcess ? "SYSTEM" : "not system", pProcess->IsAgent ? "AGENT" : "not agent");
4427 
4428  return INT_STATUS_SUCCESS;
4429 }
4430 
4431 
4432 INTSTATUS
4434  _In_ void *Detour
4435  )
4455 {
4456  WIN_PROCESS_OBJECT *pOrig;
4457  WIN_PROCESS_OBJECT *pVic;
4458 
4459  IG_ARCH_REGS *regs;
4460 
4461  QWORD rip;
4462 
4463  INTRO_ACTION action;
4464  INTRO_ACTION_REASON reason;
4465 
4466  EXCEPTION_UM_ORIGINATOR originator = { 0 };
4467  EXCEPTION_VICTIM_ZONE victim = { 0 };
4468 
4470 
4471  INTSTATUS status;
4472 
4473  union
4474  {
4475  struct
4476  {
4477  QWORD DstEproc;
4478  QWORD Class;
4479  QWORD Information;
4480  };
4481 
4482  QWORD Array[3];
4483  } args = { 0 };
4484 
4486 
4487  regs = &gVcpu->Regs;
4488 
4489  action = introGuestAllowed;
4490  reason = introReasonAllowed;
4491 
4492  rip = 0;
4493  pVic = NULL;
4494 
4495  status = IntDetGetArguments(Detour, ARRAYSIZE(args.Array), args.Array);
4496  if (!INT_SUCCESS(status))
4497  {
4498  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
4499  goto _cleanup_and_exit;
4500  }
4501 
4502  pOrig = IntWinProcFindObjectByCr3(regs->Cr3);
4503  if (NULL == pOrig)
4504  {
4505  ERROR("[ERROR] Failed to get source process by cr3 0x%016llx\n", regs->Cr3);
4506  status = INT_STATUS_NOT_FOUND;
4507  goto _cleanup_and_exit;
4508  }
4509 
4510  pVic = IntWinProcFindObjectByEprocess(args.DstEproc);
4511  if (NULL == pVic)
4512  {
4513  ERROR("[ERROR] Failed to get destination process by eprocess 0x%016llx\n", args.DstEproc);
4514  status = INT_STATUS_NOT_FOUND;
4515  goto _cleanup_and_exit;
4516  }
4517 
4518  // The structure passed to NtSetInformationProcess in order to place an instrumentation callback
4519  // seems to have a structure as follows:
4520  // WoW64: { VOID *Callback; ULONG Version; ULONG Reserved; }
4521  // Native: { ULONG Version; ULONG Reserved; VOID *Callback; }
4522  if (pVic->Wow64Process)
4523  {
4524  status = IntVirtMemFetchDword(args.Information, pOrig->Cr3, (DWORD *)&rip);
4525  }
4526  else
4527  {
4528  status = IntVirtMemFetchWordSize(args.Information + 8, pOrig->Cr3, &rip);
4529  }
4530  if (!INT_SUCCESS(status))
4531  {
4532  ERROR("[ERROR] IntVirtMemFetchWordSize failed: 0x%08x\n", status);
4533  goto _cleanup_and_exit;
4534  }
4535 
4537 
4538  status = IntExceptUserGetOriginator(pOrig, FALSE, 0, NULL, &originator);
4539  if (!INT_SUCCESS(status))
4540  {
4541  ERROR("[ERROR] IntExceptUserGetOriginator failed: 0x%08x\n", status);
4542  reason = introReasonInternalError;
4543  goto _send_notification;
4544  }
4545 
4546  status = IntExceptGetVictimProcess(pVic, rip, PAGE_SIZE, ZONE_PROC_INSTRUMENT | ZONE_WRITE, &victim);
4547  if (!INT_SUCCESS(status))
4548  {
4549  ERROR("[EROR] IntExceptGetVictimProcess failed: 0x%08x\n", status);
4550  reason = introReasonInternalError;
4551  goto _send_notification;
4552  }
4553 
4554  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventInjectionViolation);
4555 
4556 _send_notification:
4558 
4559  if (!IntPolicyProcTakeAction(PROC_OPT_PROT_INSTRUMENT, pVic, &action, &reason))
4560  {
4561  goto _cleanup_and_exit;
4562  }
4563 
4564  evt = &gAlert.Injection;
4565 
4566  memzero(evt, sizeof(*evt));
4567 
4568  LOG("[INSTRUMENTATION] From process '%s' into process '%s' to rip 0x%016llx\n", pOrig->Name, pVic->Name, rip);
4569 
4570  evt->Header.Action = action;
4571  evt->Header.Reason = reason;
4572  evt->Header.MitreID = idProcInject;
4573  evt->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_INSTRUMENT, pVic, reason, 0);
4574 
4575  status = IntVirtMemRead(rip & PAGE_MASK, sizeof(evt->RawDump), pVic->UserCr3, evt->RawDump, NULL);
4576  if (!INT_SUCCESS(status))
4577  {
4578  WARNING("[WARNING] IntVirtMemRead failed: 0x%08x\n", status);
4579  evt->DumpValid = FALSE;
4580  }
4581  else
4582  {
4583  evt->DumpValid = TRUE;
4584  evt->CopySize = sizeof(evt->RawDump);
4585  IntDumpBuffer(evt->RawDump, 0, sizeof(evt->RawDump), 16, 1, 0, 0);
4586  }
4587 
4590  IntAlertFillWinProcess(pVic, &evt->Victim.Process);
4591 
4592  evt->DestinationVirtualAddress = rip;
4594 
4596 
4597  status = IntNotifyIntroEvent(introEventInjectionViolation, evt, sizeof(*evt));
4598  if (!INT_SUCCESS(status))
4599  {
4600  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
4601  }
4602 
4603 _cleanup_and_exit:
4604  if (NULL != pVic)
4605  {
4607  }
4608 
4609  status = IntDetSetReturnValue(Detour, &gVcpu->Regs,
4611  if (!INT_SUCCESS(status))
4612  {
4613  ERROR("[ERROR] IntDetSetReturnValue failed: 0x%08x\n", status);
4614  }
4615 
4617 
4618  return status;
4619 }
4620 
4621 
4622 INTSTATUS
4624  _In_ QWORD FunctionAddress,
4625  _In_ void *Handler,
4626  _In_ void *Descriptor
4627  )
4641 {
4642  API_HOOK_HANDLER *h = Handler;
4643 
4644  struct
4645  {
4646  const char *Name;
4647  void *Addr;
4648  } exports[] =
4649  {
4650  { .Name = "PsProcessType", .Addr = &h->Code[gGuest.Guest64 ? 0x1f : 0x34] },
4651  { .Name = "ObReferenceObjectByHandle", .Addr = &h->Code[gGuest.Guest64 ? 0x3b : 0x3c] },
4652  { .Name = "ObDereferenceObject", .Addr = &h->Code[gGuest.Guest64 ? 0x86 : 0x65] },
4653  };
4654 
4655  UNREFERENCED_PARAMETER(FunctionAddress);
4656  UNREFERENCED_PARAMETER(Descriptor);
4657 
4658  for (size_t i = 0; i < ARRAYSIZE(exports); i++)
4659  {
4660  INTSTATUS status;
4661  QWORD addr;
4662 
4663  status = IntPeFindKernelExport(exports[i].Name, &addr);
4664  if (!INT_SUCCESS(status))
4665  {
4666  ERROR("[ERROR] IntPeFindKernelExport failed for %s: 0x%08x\n", exports[i].Name, status);
4667  return status;
4668  }
4669 
4670  TRACE("[INFO] Export %s found at gva 0x%016llx\n", exports[i].Name, addr);
4671 
4672  if (gGuest.Guest64)
4673  {
4674  *(QWORD *)(exports[i].Addr) = addr;
4675  }
4676  else
4677  {
4678  *(DWORD *)(exports[i].Addr) = (DWORD)addr;
4679  }
4680  }
4681 
4682  *(DWORD *)(void *)(&h->Code[gGuest.Guest64 ? 0x5e : 0x51]) = WIN_KM_FIELD(Process, Spare);
4683 
4684  return INT_STATUS_SUCCESS;
4685 }
4686 
WINUM_PATH * Path
Module path.
Definition: winummodule.h:62
DWORD CommandLineSize
Includes the NULL terminator.
Definition: winprocess.h:116
PCHAR CommandLine
The command line with which the process was created (can be NULL).
Definition: winprocess.h:114
static WIN_PROCESS_OBJECT * IntWinProcHandleCreateInternal(QWORD NewEprocess, QWORD ParentEprocess, QWORD DebugHandle, INTRO_ACTION *Action)
Handles process creation for Windows guests.
Definition: winprocess.c:2494
uint16_t * PWCHAR
Definition: intro_types.h:63
void * Module
The internal structure of a module.
Definition: exceptions.h:836
#define IC_TAG_VADP
VAD pages hash table.
Definition: memtags.h:77
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
Definition: introstatus.h:438
INTSTATUS IntWinProcRemoveProtectedProcess(const WCHAR *Path)
This function removed the provided process from the protected process list.
Definition: winprocess.c:3826
INTSTATUS IntPtiInjectPtFilter(void)
Inject the PT filter inside the guest.
Definition: ptfilter.c:1676
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
Definition: introcore.h:107
struct _EVENT_MEMCOPY_VIOLATION::@297 Originator
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
Credential Dumping.
Definition: intro_types.h:1143
PWIN_PROCESS_SUBSYSTEM Subsystemx64
The x64 subsystem. Note that a 32 bit process on a 64 bit OS may have both subsystems valid...
Definition: winprocess.h:312
#define __unlikely(x)
Definition: common.h:64
INTSTATUS IntWinProcHandleInstrument(void *Detour)
Handles an exit on NtSetInformationProcess calls where the InformationClass argument is 40 (instrumen...
Definition: winprocess.c:4433
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
static INTSTATUS IntWinProcCreateProcessSubsystem(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_SUBSYSTEM **Subsystem, BYTE SubsystemType)
Create a process subsystem for the given process.
Definition: winprocess.c:578
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
Exposes the types, constants and functions used to handle Windows processes events (creation...
static INTSTATUS IntWinProcLockCr3(WIN_PROCESS_OBJECT *Process)
Locks the kernel and user Cr3 of a process in memory.
Definition: winprocess.c:1376
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:904
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
char Name[ALERT_MAX_FUNCTIONS][ALERT_MAX_FUNCTION_NAME_LEN]
Array of all the extracted function names.
Definition: intro_types.h:1513
DWORD Size
The size of the access.
Definition: intro_types.h:982
DWORD Original
The original protection flags as received from GLUE_IFACE.AddRemoveProtectedProcessUtf16 or GLUE_IFAC...
Definition: winguest.h:38
INTRO_MODULE Module
The module which was written or read.
Definition: intro_types.h:1451
#define EX_FAST_REF_TO_PTR(is64, p)
Converts a _EX_FAST_REF value to a pointer.
Definition: wddefs.h:100
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
uint8_t BYTE
Definition: intro_types.h:47
The process was not protected due to an internal error.
Definition: intro_types.h:2446
void IntWinProcLstInsertProcess(WIN_PROCESS_OBJECT *Process)
Inserts a WIN_PROCESS_OBJECT structure into the process lists and trees.
Definition: winprocesshp.c:46
Describe the introcore protection options.
static BOOLEAN IntWinProcExistsProtectedProcess(CHAR BaseName[IMAGE_BASE_NAME_LEN], const WCHAR *FullPath, DWORD ProtectionMask, QWORD Context)
This function checks if the provided process is already protected with the given flags.
Definition: winprocess.c:3552
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
BOOLEAN Created
True if the process was created, False if it was terminated.
Definition: intro_types.h:1913
DWORD Index
The VCPU number.
Definition: guests.h:172
EVENT_EXCEPTION_EVENT Exception
Definition: alerts.h:28
This is the structure as documented in winternl.h.
Definition: wddefs.h:825
INTSTATUS IntSwapMemRemoveTransactionsForVaSpace(QWORD Cr3)
Remove all transactions initiated for a virtual address space.
Definition: swapmem.c:982
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
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
INTSTATUS IntPeFindKernelExport(const char *Name, QWORD *ExportGva)
Find an export inside the NT kernel image.
Definition: winpe.c:1748
static const char * gCmdLineProcesses[]
This is a list of processes for which we want to read the command line (not to be confused with PROC_...
Definition: winprocess.c:146
#define INTRO_OPT_PROT_KM_SYSTEM_CR3
Enable System process PDBR protection.
Definition: intro_types.h:415
QWORD RealParentEprocess
The active EPROCESS at the moment of creation.
Definition: winprocess.h:92
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:211
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
QWORD Context
The context supplied in the protection policy.
Definition: winguest.h:75
Event structure for process creation/termination.
Definition: intro_types.h:1910
INTRO_PROCESS Process
The process that attempted the access.
Definition: intro_types.h:1440
Measures user mode exceptions checks.
Definition: stats.h:50
QWORD NewValue[8]
The written value. Only the first Size bytes are valid.
Definition: intro_types.h:981
CHAR FunctionName[ALERT_MAX_FUNCTION_NAME_LEN]
The name of the accessed function, if any.
Definition: intro_types.h:1499
#define WIN_STATUS_SUCCESS
Equivalent to NTSTATUS STATUS_SUCCESS.
Definition: winprocess.h:24
#define CSTRLEN(String)
Definition: introdefs.h:105
INTSTATUS IntWinVadImportProcessTree(WIN_PROCESS_OBJECT *Process)
Scans the guest VAD tree and imports the nodes into our VAD tree.
Definition: winvad.c:2768
static INTSTATUS IntWinProcUnlockCr3(WIN_PROCESS_OBJECT *Process)
Unlocks the kernel and user Cr3 of a process in memory.
Definition: winprocess.c:1425
INTSTATUS IntWinTokenPrivsCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the privileges bitfields for the given process have been changed in a malicio...
Definition: wintoken.c:958
#define STATS_EXIT(id)
Definition: stats.h:160
CAMI_STRING_ENCODING
Describes the encoding of a string received from the CAMI file.
Definition: update_guests.h:52
void IntWinVadStopExploitMonitor(WIN_PROCESS_OBJECT *Process)
Disables the exploit monitoring for a process.
Definition: winvad.c:1811
void * ParamsSwapHandle
The swap memory handle for Process->Peb->ProcessParameters (used to read the command line of the proc...
Definition: winprocess.h:251
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
#define INTRO_OPT_ENABLE_FULL_PATH
Aggregates all the full path protection flags.
Definition: intro_types.h:594
INTSTATUS IntWinProcAddProtectedProcess(const WCHAR *Path, DWORD ProtectionMask, QWORD Context)
This function adds the provided process to the protected process list.
Definition: winprocess.c:3712
#define IC_TAG_POBJ
Process Object List Entry.
Definition: memtags.h:14
QWORD FeedbackMask
The protection mask in feedback mode.
Definition: winprocess.h:231
Exits caused by "MmCopyVirtualMemory".
Definition: winprocess.h:43
struct _UNICODE_STRING64 UNICODE_STRING64
The Windows UNICODE_STRING structure used for 64-bit guests.
User-mode exception.
Definition: exceptions.h:60
Described a detour handler.
Definition: detours.h:283
static INTSTATUS IntWinProcSendAgentEvent(WIN_PROCESS_OBJECT *Process, BOOLEAN Created)
Send a process creation/termination event that symbolizes an agent.
Definition: winprocess.c:401
INTSTATUS IntSwapMemReadData(QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle)
Reads a region of guest virtual memory, and calls the indicated callback when all the data is availab...
Definition: swapmem.c:417
struct _LIST_ENTRY * Flink
Definition: introlists.h:20
INTSTATUS IntWinVadRemoveProcessTree(WIN_PROCESS_OBJECT *Process)
Removes the VAD tree from a process.
Definition: winvad.c:1351
AGENT_EVENT_TYPE Event
The type of the agent.
Definition: intro_types.h:2347
INTRO_PROCESS Process
The process that could not be protected.
Definition: intro_types.h:2423
DWORD Lsass
TRUE if this is the lsass process.
Definition: winprocess.h:137
INTSTATUS IntWinVadProcImportMainModuleVad(WIN_PROCESS_OBJECT *Process)
Imports the VAD that describes the main module of a process.
Definition: winvad.c:3816
BOOLEAN SysprocBetaDetections
Definition: guests.h:304
TIMER_FRIENDLY INTSTATUS IntWinProcValidateSystemCr3(void)
This function checks if the system CR3 value was modified and if GUEST_STATE::KernelBetaDetections is...
Definition: winprocess.c:3371
DWORD NumberOfOffsets
Number of symbols pointing to the exported RVA.
Definition: winumcache.h:27
#define INTRO_OPT_PROT_KM_TOKEN_PTR
Enable process token protection (Windows only).
Definition: intro_types.h:416
INTSTATUS IntWinProcSwapOut(void *Detour)
Detour handler for the KiOutSwapProcess Windows kernel API.The detour on KiOutSwapProcess is set afte...
Definition: winprocess.c:4318
INTRO_ERROR_CONTEXT gErrorContext
Global storage for the error context used by GLUE_IFACE.NotifyIntrospectionErrorState.
Definition: introcore.c:43
BOOLEAN ShutDown
True if the system process protection is in beta (log-only) mode.
Definition: guests.h:313
struct _INTRO_ERROR_CONTEXT::@340 ProcessProtection
Process protection errors.
INTSTATUS IntWinProcReadCommandLine(WIN_PROCESS_OBJECT *Process)
Reads the command line of the given process using IntSwapMemReadData.
Definition: winprocess.c:900
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
RBTREE gWinProcTreeCr3
Tree of all the processes inside the guest, using the kernel CR3 as the key.
Definition: winprocesshp.c:13
static BOOLEAN IsListEmpty(const LIST_ENTRY *ListHead)
Definition: introlists.h:78
INTSTATUS IntDetSetReturnValue(DETOUR const *Detour, IG_ARCH_REGS *Registers, QWORD ReturnValue)
Sets the return value for a hooked guest function.
Definition: detours.c:1528
Process Injection.
Definition: intro_types.h:1146
The process was not protected because there is not enough memory available.
Definition: intro_types.h:2445
static void IntWinProcHandleDuplicate(QWORD Cr3, QWORD Eprocess)
Ensures that a newly created process does not exist already.
Definition: winprocess.c:1276
static INTSTATUS IntWinProcEnforceProcessDep(WIN_PROCESS_OBJECT *Process)
Enables DEP (Data Execution Prevention) for a certain process.
Definition: winprocess.c:224
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
#define PROC_OPT_PROT_WSOCK_HOOKS
Blocks hooks being set on Wininet user-mode DLLs (Windows only).
Definition: intro_types.h:350
BOOLEAN ProtectionActivated
Definition: guests.h:297
Mitigation flags.
Definition: wddefs.h:1759
static INTSTATUS IntWinGetPrcoCmdLineHandleUserParamsInMemory(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Called from within IntSwapMemReadData when the RTL_USER_PROCESS_PARAMETERS32 or RTL_USER_PROCESS_PARA...
Definition: winprocess.c:826
The action was not allowed because there was no reason to allow it.
Definition: intro_types.h:183
INTSTATUS IntWinProcSwapIn(void *Detour)
Detour handler for the MmInSwapProcess Windows kernel API.The detour on MmInSwapProcess is set inside...
Definition: winprocess.c:4214
#define ARRAYSIZE(A)
Definition: introdefs.h:101
QWORD Context
Context from integrator if the process is protected, 0 otherwise.
Definition: winprocess.h:266
BOOLEAN KernelBetaDetections
True if the kernel protection is in beta (log-only) mode.
Definition: guests.h:303
Event structure for agent injection and termination.
Definition: intro_types.h:2345
Measures the IntWinProcHandleCopyMemory detour handler.
Definition: stats.h:67
The agent process finished execution.
Definition: intro_types.h:2102
INTSTATUS IntWinProcMapEprocess(QWORD Eprocess, void **Ptr)
Maps a _EPROCESS structure.
BOOLEAN IntWinProcIsEnoughHeapAvailable(void)
Checks if enough heap is available in order to protect a new process.
Definition: winprocesshp.c:685
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1542
Windows process subsystem.
Definition: winprocess.h:54
DWORD Delta
The offset inside the affected function at which the access was made.
Definition: intro_types.h:1505
struct _EVENT_TRANSLATION_VIOLATION::@301 Victim
WORD OriginalSpareValue
We put in guest * and some flags in order to decide whether to raise a VM exit on a process...
Definition: winprocess.h:273
DWORD Current
The currently used protection flags.
Definition: winguest.h:44
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
INTSTATUS IntWinProcPatchSwapOut64(QWORD FunctionAddress, void *Handler, void *Descriptor)
This functions is responsible for patching the detour that handles the "KiOutSwapProcesses".
Definition: winprocess.c:2387
Exits caused by "NtQueueApcThreadEx".
Definition: winprocess.h:46
Describes a user-mode originator.
Definition: exceptions.h:994
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:675
static LIST_HEAD gWinProtectedProcesses
A list with all the protected processes (containing PROTECTED_PROCESS_INFO elements).
Definition: winprocess.c:62
#define CMDLINE_MAX_LEN
The maximum length (in bytes) of the data read from the guest when reading the command line of a proc...
Definition: winprocess.c:37
#define _Outptr_
Definition: intro_sal.h:19
QWORD Feedback
Flags that will be forced to feedback only mode.
Definition: winguest.h:58
INTSTATUS IntWinProcHandleTerminate(void *Detour)
This functions handles the termination of a Windows process.This function is invoked every time "MmCl...
Definition: winprocess.c:2682
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
INTSTATUS IntWinPfnRemoveLock(WIN_PFN_LOCK *PfnLock, BOOLEAN Force)
Removes a PFN lock.
Definition: winpfn.c:838
DWORD Buffer
The guest virtual address at which the wide-character string is located.
Definition: wddefs.h:129
int INTSTATUS
The status data type.
Definition: introstatus.h:24
static void IntWinProcFillSystemPath(WIN_PROCESS_SUBSYSTEM *Subsystem)
Fill the system directory path for the given subsystem.
Definition: winprocess.c:557
const WCHAR gSysWowPath[]
The syswow path (32 bit process on a 64 bit OS).
Definition: winprocess.c:77
INTSTATUS IntWinSelfMapGetAndCheckSelfMapEntry(WIN_PROCESS_OBJECT *Process)
Sets and validates the self map entry values for a process.
Definition: winselfmap.c:579
DWORD ExitStatus
The exit code of the process.
Definition: intro_types.h:1927
DWORD OSVersion
Os version.
Definition: guests.h:281
#define KEXEC_OPT_PERMANENT
Freezes the DEP settings for a process.
Definition: wddefs.h:1441
DWORD OneTimeInjectionDone
The one time injection already took place (exception).
Definition: winprocess.h:153
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
DWORD NameHash
Name hash, as used by the exceptions module.
Definition: winprocess.h:101
char * utf16tolowerutf8(char *Destination, const WCHAR *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:480
QWORD VirtualAddress
The Virtual Address whose translation is being modified.
Definition: intro_types.h:1552
BOOLEAN Continuable
True if the exception is considered to be continuable.
Definition: intro_types.h:1992
QWORD Peb64Address
PEB 64 address (on x86 OSes, this will be 0).
Definition: winprocess.h:103
Event structure for illegal paging-structures modifications.
Definition: intro_types.h:1540
static const PROTECTED_PROCESS_INFO * IntWinProcGetProtectedInfo(CHAR BaseName[IMAGE_BASE_NAME_LEN], BOOLEAN IsSystem)
Returns a pointer to the PROTECTED_PROCESS_INFO structure for the given process BaseName.
Definition: winprocess.c:1012
DWORD Flags
Flags that describe the protection mode.
Definition: winguest.h:64
BOOLEAN IntMatchPatternUtf8(const CHAR *Pattern, const CHAR *String, DWORD Flags)
Matches a pattern using glob match.
Definition: introcore.c:2454
#define ALERT_MAX_FUNCTION_NAME_LEN
The maximum size of a function name inside an alert structure.
Definition: intro_types.h:703
INTSTATUS IntWinSelfMapProtectSelfMapIndex(WIN_PROCESS_OBJECT *Process)
Protects the self map index of a process by placing an EPT write hook on it.
Definition: winselfmap.c:710
INTRO_PROCESS CurrentProcess
The agent process.
Definition: intro_types.h:2355
Rootkit.
Definition: intro_types.h:1144
Measures the process creation checks.
Definition: stats.h:84
INTSTATUS IntWinProcPrepareInstrument(QWORD FunctionAddress, void *Handler, void *Descriptor)
This function is responsible for patching the detour that handles "NtSetInformationProcess".
Definition: winprocess.c:4623
Sent for code/data injection alerts. See EVENT_MEMCOPY_VIOLATION.
Definition: intro_types.h:96
INTSTATUS IntWinProcUnprotect(WIN_PROCESS_OBJECT *Process)
Remove a process from protection.
Definition: winprocess.c:3247
#define IMAGE_BASE_NAME_LEN
The maximum length of a process name.
Definition: winguest.h:15
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
EVENT_TRANSLATION_VIOLATION Translation
Definition: alerts.h:22
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
QWORD VirtualBase
Guest virtual address of the loaded module.
Definition: winummodule.h:34
DWORD ErrorCode
The error code of the event. Success is 0.
Definition: intro_types.h:2349
#define MIN(a, b)
Definition: introdefs.h:146
QWORD MainModuleAddress
The address of the main module.
Definition: winprocess.h:106
#define IC_TAG_PATH
Object path.
Definition: memtags.h:55
INTSTATUS IntVirtMemFetchWordSize(QWORD GuestVirtualAddress, QWORD Cr3, void *Data)
Reads a guest pointer from the guest memory.
Definition: introcore.c:908
INTSTATUS IntWinSelfMapUnprotectSelfMapIndex(WIN_PROCESS_OBJECT *Process)
Removes the EPT protection for the self map entry index of a process.
Definition: winselfmap.c:802
INTSTATUS IntVirtMemFetchDword(QWORD GuestVirtualAddress, QWORD Cr3, DWORD *Data)
Reads 4 bytes from the guest memory.
Definition: introcore.c:887
QWORD ParentEprocess
The EPROCESS of the parent process.
Definition: winprocess.h:91
#define INTRO_MATCH_TRUNCATED
If set, matching functions like IntMatchPatternUtf8 will match up until the first wild char encounter...
Definition: introcore.h:13
#define INTRO_OPT_PROT_UM_SYS_PROCS
Enable user-mode system processes protection (injection only).
Definition: intro_types.h:437
Process subsystem type 32 bit.
Definition: winprocess.h:34
DWORD Protected
TRUE if this is a protected process. If this is FALSE, most of the above fields aren&#39;t used at all...
Definition: winprocess.h:130
BOOLEAN IntPolicyProcIsBeta(const void *Process, QWORD Flag)
Checks if a process protection policy is in log-only mode.
Definition: introcore.c:2569
#define LOG(fmt,...)
Definition: glue.h:61
Encapsulates a protected Windows process.
Definition: winguest.h:24
#define ZONE_PROC_INSTRUMENT
Used for exceptions for instrumentation callback.
Definition: exceptions.h:732
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
#define INTRO_OPT_EVENT_PROCESS_CRASH
Enable application crash events (generates introEventExceptionEvent).
Definition: intro_types.h:449
DWORD Wow64Process
TRUE if this is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:125
RBTREE gWinProcTreeUserCr3
Tree of all the processes inside the guest, using the user-mode CR3 as the key/.
Definition: winprocesshp.c:15
The Windows UNICODE_STRING structure used for 32-bit guests.
Definition: wddefs.h:120
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
void IntWinAgentCheckIfProcessAgentAndIncrement(CHAR *ImageName, BOOLEAN *IsAgent, DWORD *Tag)
Checks if a process is an agent or not, and increments the ref count of that name.
Definition: winagent.c:3028
BOOLEAN KptiActive
True if KPTI is enabled on this guest, False if it is not.
Definition: guests.h:291
INTSTATUS IntWinTokenPrivsProtectOnProcess(WIN_PROCESS_OBJECT *Process)
Updates the stored original Privileges bitfields (Present and Enabled) and hooks through EPT the Priv...
Definition: wintoken.c:1163
TRANS_VIOLATION_TYPE ViolationType
Definition: intro_types.h:1562
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
EXCEPTION_VICTIM_OBJECT Object
The modified object.
Definition: exceptions.h:895
void IntUDRemoveAllEntriesForCr3(const QWORD Cr3)
Remove all pending UD entries for a given virtual address space.
Definition: udlist.c:116
#define NAMEHASH_NTDLL
Definition: winummodule.h:11
#define INFO(fmt,...)
Definition: glue.h:59
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
#define ALERT_FLAG_BETA
If set, the alert is a BETA alert. No action was taken.
Definition: intro_types.h:671
MEMCOPY_VIOLATION_TYPE ViolationType
The type of the access.
Definition: intro_types.h:1480
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
void IntWinModulesChangeProtectionFlags(PWIN_PROCESS_SUBSYSTEM Subsystem)
Change the protection flags applied to the process modules that are currently loaded.
Definition: winummodule.c:2138
DWORD LateProtection
TRUE if the protection was not activated right from start.
Definition: winprocess.h:154
static INTSTATUS IntWinProcRemoveProcess(WIN_PROCESS_OBJECT *Process)
Used to free the memory allocations and swap memory transactions used by a PWIN_PROCESS_OBJECT.
Definition: winprocess.c:2031
#define _Inout_
Definition: intro_sal.h:20
QWORD CreationTime
The creation time of the process, as stored inside the EPROCESS.
Definition: winprocess.h:95
INTSTATUS IntWinProcPatchCopyMemoryDetour(QWORD FunctionAddress, void *Handler, void *Descriptor)
This functions is responsible for patching the detour that handles the "MmCopyVirtualMemory".This function is invoked every time "MmCopyVirtualMemory" is called (a process is writing/reading another process) but before the actual handler IntWinProcHandleCopyMemory, its purpose being to modify the hook code (see winhkhnd.c).
Definition: winprocess.c:2746
QWORD StartPage
Definition: winvad.h:102
INTSTATUS IntSwapMemRemoveTransaction(void *Transaction)
Remove a transaction.
Definition: swapmem.c:942
WINUM_PATH * Path
Will point inside the loaded modules list to the full process path.
Definition: winprocess.h:111
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
Definition: introcore.c:829
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1436
DETOUR_ARGS Arguments
Encoding of the arguments needed by introcore from the hooked function.
Definition: detours.h:379
INTSTATUS IntCamiUpdateProcessProtectionInfo(void *ProtectedProcess)
Update a process&#39; protection flags using the ones from CAMI.
EVENT_MEMCOPY_VIOLATION Injection
Definition: alerts.h:21
static void IntWinProcMarkAsSystemProcess(WIN_PROCESS_OBJECT *Process, const WIN_PROCESS_OBJECT *Parent)
Mark the process as being a system process.
Definition: winprocess.c:1468
#define CMDLINE_LEN_NO_SCAN
The maximum length (in bytes) of the data read from the guest when reading the command line of a proc...
Definition: winprocess.c:29
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
BOOLEAN IntPolicyProcTakeAction(QWORD Flag, void const *Process, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a process protection option.
Definition: introcore.c:2732
DWORD CopySize
The size of the access.
Definition: intro_types.h:1477
size_t wstrlen(const WCHAR *str)
Definition: introcrt.c:1080
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
Definition: introcore.c:811
EVENT_PROCESS_EVENT Process
Definition: alerts.h:25
struct _PROTECTED_PROCESS_INFO::@211 Protection
The protection flags used for this process.
The CR3 of a process was changed.
Definition: intro_types.h:1530
#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
uint8_t * PBYTE
Definition: intro_types.h:47
DWORD Argv[DET_ARGS_MAX]
Argument encoding. See DET_ARG_REGS and DET_ARG_ON_STACK.
Definition: detours.h:111
DWORD IsPreviousAgent
TRUE if this is an agent injected in a previous session.
Definition: winprocess.h:164
#define INTRO_OPT_EVENT_PROCESSES
Enable process creation and termination events (generates introEventProcessEvent events).
Definition: intro_types.h:443
BOOLEAN IntMatchPatternUtf16(const WCHAR *Pattern, const WCHAR *String, DWORD Flags)
Matches a pattern using glob match.
Definition: introcore.c:2491
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
static INTSTATUS IntWinProcPatchSpareValue(WIN_PROCESS_OBJECT *Process)
Saves the process protection info within an EPROCESS spare field.
Definition: winprocess.c:291
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
RBTREE gWinProcTreeEprocess
Tree of all the processes inside the guest, using the _EPROCESS address as the key.
Definition: winprocesshp.c:18
#define memzero(a, s)
Definition: introcrt.h:35
#define INTRO_OPT_PROT_UM_MISC_PROCS
Definition: intro_types.h:435
#define PT_P
Definition: pgtable.h:83
LIST_ENTRY Link
Entry inside the gWinProtectedProcesses list.
Definition: winguest.h:78
INTSTATUS IntGpaCacheFetchAndAdd(PGPA_CACHE Cache, QWORD Gpa, DWORD Size, PBYTE Buffer)
Fetch data from a cached entry, or add it to the cache, of not already present.
Definition: gpacache.c:508
UINT16 Length
The length, in bytes, of the string in Buffer, not including the NULL terminator, if any...
Definition: wddefs.h:123
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
#define WIN_BUILD_10_TH1
Definition: wddefs.h:52
unsigned long long QWORD
Definition: intro_types.h:53
INTSTATUS IntAgentEnableInjection(void)
Enable Windows or Linux agent injection.
Definition: agent.c:152
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
QWORD Current
The currently used options.
Definition: guests.h:236
Exits caused by "NtSetInformationProcess".
Definition: winprocess.h:47
INTRO_PROCESS CurrentProcess
The currently active process.
Definition: intro_types.h:1930
BYTE Code[DETOUR_MAX_HANDLER_SIZE]
The code of the detour handler. Only CodeLength bytes are valid.
Definition: detours.h:298
WINUM_PATH * Path
Definition: winvad.h:144
BOOLEAN HasNaClEnabled
Only valid for chromium-based browsers; TRUE if this is a NaCl process.
Definition: winprocess.h:187
QWORD UserCr3
Process user PDBR. Includes PCID.
Definition: winprocess.h:99
CHAR ImageBaseNamePattern[IMAGE_BASE_NAME_LEN]
Process name pattern.
Definition: winguest.h:29
Informational event sent when the remediation tool is injected or terminated. See EVENT_AGENT_EVENT...
Definition: intro_types.h:104
INTRO_PROCESS Child
The process that is being created or terminated.
Definition: intro_types.h:1933
Measures the handling of memory reads in which a write protection policy exists.
Definition: stats.h:74
DWORD Terminating
TRUE if the process is terminating (cleanup pending).
Definition: winprocess.h:126
int strlower_utf16(WCHAR *buf, size_t len)
Definition: introcrt.c:28
void * GpaCache
The currently used GPA cache.
Definition: guests.h:403
#define KEXEC_OPT_EXEC_ENABLE
Enables execution rights for memory that contains data. Disables DEP.
Definition: wddefs.h:1435
#define TRUE
Definition: intro_types.h:30
QWORD Beta
Flags that were forced to beta (log-only) mode.
Definition: winguest.h:51
#define IC_TAG_PCMD
Process command line.
Definition: memtags.h:78
DWORD Hash[ALERT_MAX_FUNCTIONS]
Array of all the extracted function hashes.Export.Hash[i] is the hash for Export.Name[i].
Definition: intro_types.h:1516
INTRO_WRITE_INFO WriteInfo
The original and new address to which VirtualAddress translates.
Definition: intro_types.h:1560
DWORD StartInitializing
TRUE if the process actually started initializing (there is a time windows from the moment we add the...
Definition: winprocess.h:151
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
#define PROT_PROC_FLAG_NO_PATH
Flag used to represent internally that a process is protected by name, not by path.
Definition: winguest.h:21
DWORD ProtectionMask
Protection mask: tells us what level of protection will be activated for this process.
Definition: winprocess.h:200
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
Definition: guests.h:293
This is a classic code injection attempt that simply modifies the memory of the victim process...
Definition: intro_types.h:1411
TIMER_FRIENDLY void IntDumpBuffer(const void *Buffer, QWORD Gva, DWORD Length, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given buffer in a user friendly format.
Definition: dumper.c:48
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
PWIN_PROCESS_OBJECT IntWinProcFindObjectByCr3(QWORD Cr3)
Finds a process by its kernel CR3.
Definition: winprocesshp.c:195
DWORD ExitStatus
The exit status of the process (used when sending the process terminated event).
Definition: winprocess.h:192
This represents an attempt to set an instrument callback inside the victim process.
Definition: intro_types.h:1423
#define INT_STATUS_INVALID_PARAMETER_5
Definition: introstatus.h:74
A PFN lock.
Definition: winpfn.h:19
Sent for virtual address translation alerts. See EVENT_TRANSLATION_VIOLATION.
Definition: intro_types.h:94
Memory access violations that cross a process boundary.
Definition: intro_types.h:1434
DWORD AgentTag
Unique agent tag. See INTRO_DEP_AG_TAGS.
Definition: intro_types.h:2348
BOOLEAN DumpValid
True if the contents of RawDump are valid, False if not.
Definition: intro_types.h:1483
Exits caused by "MiCommitExistingVad".
Definition: winprocess.h:42
#define TIMER_FRIENDLY
Definition: introdefs.h:83
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
struct _UNICODE_STRING32 UNICODE_STRING32
The Windows UNICODE_STRING structure used for 32-bit guests.
void IntAlertFillWinProcessCurrent(INTRO_PROCESS *EventProcess)
Saves information about the current Windows process inside an alert.
Definition: alerts.c:781
struct _WIN_PROCESS_OBJECT * Process
The process object related to this subsystem.
Definition: winprocess.h:56
Informational event sent when a process is created or terminated by the guest. See EVENT_PROCESS_EVEN...
Definition: intro_types.h:102
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:367
BOOLEAN Protected
True if the process is protected.
Definition: intro_types.h:1915
String will be encoded in utf-8.
Definition: update_guests.h:54
#define PROC_OPT_PROT_SCAN_CMD_LINE
Uses third party engines to scan the command line of a process.
Definition: intro_types.h:364
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:135
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
static BOOLEAN IntWinProcIsExploitGuardEnabled(QWORD EprocessAddress, BYTE *Eprocess)
Checks if the exploit guard is enabled for a certain process.
Definition: winprocess.c:185
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
char * PCHAR
Definition: intro_types.h:56
QWORD BetaMask
The protection mask in beta mode.
Definition: winprocess.h:230
INTSTATUS IntDetGetArgument(void const *Detour, DWORD Index, BYTE const *StackBuffer, DWORD StackBufferSize, QWORD *Value)
Reads the specified argument for a detour.
Definition: detours.c:2237
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Definition: introstatus.h:323
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:100
INTSTATUS IntWinTokenPtrCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the security token of a given process has been stone from another process...
Definition: wintoken.c:719
Process subsystem type 64 bit.
Definition: winprocess.h:33
static void IntWinProcSetUserCr3(WIN_PROCESS_OBJECT *Process, const BYTE *EprocessBuffer)
Sets the User CR3 value for a newly created process.
Definition: winprocess.c:1327
PWCHAR FullPathPattern
Full application path pattern.
Definition: winguest.h:66
#define INTRO_OPT_FULL_PATH
Enable full-path protection of processes.
Definition: intro_types.h:456
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.
void IntWinProcLstRemoveProcess(WIN_PROCESS_OBJECT *Process)
Removes a WIN_PROCESS_OBJECT structure from the process lists and trees.
Definition: winprocesshp.c:73
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:674
static INTSTATUS IntWinProcRemoveProtectedProcessInternal(CHAR BaseName[IMAGE_BASE_NAME_LEN], const WCHAR *FullPath)
This function removes the protection for the given process.
Definition: winprocess.c:3614
static void InitializeListHead(LIST_ENTRY *ListHead)
Definition: introlists.h:69
#define INTRO_OPT_ENABLE_UM_PROTECTION
Aggregates all the user mode protection flags.
Definition: intro_types.h:561
#define PAGE_SIZE
Definition: common.h:70
INTSTATUS IntVirtMemSafeWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, void *Buffer, DWORD Ring)
Safely modify guest memory.
Definition: kernvm.c:498
The Windows UNICODE_STRING structure used for 64-bit guests.
Definition: wddefs.h:136
Describes the modified zone.
Definition: exceptions.h:893
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
#define PROC_OPT_PROT_EXPLOIT
Blocks malicious execution attempts.
Definition: intro_types.h:352
#define TRFLG_PG_MODE
Obtains the translation mode flag for the currently used paging mode.
Definition: introcore.h:92
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
Definition: winumpath.h:23
void * InstructionCache
The currently used instructions cache.
Definition: guests.h:404
DWORD BetaDetections
TRUE if BETA is enabled for this particular process.
Definition: winprocess.h:135
INTSTATUS IntWinTokenPrivsUnprotectOnProcess(WIN_PROCESS_OBJECT *Process)
Definition: wintoken.c:1224
DWORD Rva
The RVA of this export.
Definition: winumcache.h:23
uint16_t WCHAR
Definition: intro_types.h:63
QWORD ExceptionCode
The code of the exception.
Definition: intro_types.h:1988
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:740
EVENT_AGENT_EVENT Agent
Definition: alerts.h:29
QWORD Peb32Address
PEB 32 address (on pure x64 processes, this will be 0).
Definition: winprocess.h:104
static BOOLEAN IntWinProcIsFullPath(const WCHAR *Path)
This function checks if the provided path is a full path.
Definition: winprocess.c:3525
uint32_t DWORD
Definition: intro_types.h:49
const WCHAR gSystemPath[]
The system path.
Definition: winprocess.c:72
#define PROC_OPT_PROT_CORE_HOOKS
Blocks hooks being set on core user-mode DLLs.
Definition: intro_types.h:344
INTSTATUS IntDetGetArguments(void const *Detour, DWORD Argc, QWORD *Argv)
Reads multiple arguments from a detour.
Definition: detours.c:2296
QWORD OriginalTokenPtr
Original Token pointer inside EPROCESS (should never change).
Definition: winprocess.h:247
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:965
LIST_ENTRY Link
List entry element.
Definition: winummodule.h:32
static DWORD gTotalProtectedProcs
The total number of protected processes.
Definition: winprocess.c:67
INTSTATUS IntWinProcRemoveAllProtectedProcesses(void)
This function removed all the processes from the protected process list.
Definition: winprocess.c:3880
enum _INTRO_ACTION INTRO_ACTION
Event actions.
BOOLEAN IntPolicyProcForceBetaIfNeeded(QWORD Flag, void *Process, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the process log-only mode is active.
Definition: introcore.c:2773
#define _In_reads_bytes_(expr)
Definition: intro_sal.h:25
QWORD OldValue[8]
The original value. Only the first Size bytes are valid.
Definition: intro_types.h:980
Definition: rbtree.h:84
Measures IntWinProcHandleCopyMemory invocations done for memory reads.
Definition: stats.h:69
INTSTATUS IntWinProcGetObjectByPid(DWORD Pid, WIN_PROCESS_OBJECT **Process)
This function looks for a process with the given PID inside gWinProcesses and returns its WIN_PROCESS...
Definition: winprocess.c:4003
INTRO_PROCESS CurrentProcess
The process in which the exception was triggered.
Definition: intro_types.h:1995
void IntWinVadDestroyObject(VAD **Vad)
Frees a VAD and all the resources held by it.
Definition: winvad.c:285
INTSTATUS IntSetGprs(DWORD CpuNumber, PIG_ARCH_REGS Regs)
Sets the values of the guest GPRs.
Definition: introcpu.c:905
#define WIN_STATUS_ACCESS_DENIED
Equivalent to NTSTATUS STATUS_ACCESS_DENIED.
Definition: winprocess.h:23
WCHAR * Name
The name of the module contained in the path.
Definition: winumpath.h:18
LIST_HEAD ProcessModules
List of process modules.
Definition: winprocess.h:70
void IntExceptInvCbCacheByCr3(QWORD Cr3)
Invalidate the cache used for code blocks for a given CR3.
Definition: exceptions.c:102
static BOOLEAN IntWinProcHandleReadFromLsass(QWORD SourceAddress, DWORD ReadSize, const WIN_PROCESS_OBJECT *Lsass, WIN_PROCESS_MODULE **VictimModule)
Handles reads from lsass.exe.
Definition: winprocess.c:2794
Event structure for process exceptions.
Definition: intro_types.h:1983
DWORD NameLens[MAX_OFFSETS_PER_NAME]
Length of each name pointing to this RVA.
Definition: winumcache.h:25
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:970
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:374
void * CmdBufSwapHandle
The swap memory handle for the command line buffer.
Definition: winprocess.h:257
DWORD ExploitGuardEnabled
TRUE if any Exploit Guard mitigation option is set for this process.
Definition: winprocess.h:167
INTSTATUS IntWinProcHandleCopyMemory(void *Detour)
This functions is responsible handling process read/write operations.This function is invoked every t...
Definition: winprocess.c:2870
DWORD ProtWriteMem
Protect the the memory against writes.
Definition: winprocess.h:207
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:90
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:673
struct _EVENT_MEMCOPY_VIOLATION::@299 Export
All the names used to export the modified function.
DWORD ParentWow64
TRUE if the parent is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:146
DWORD FunctionNameHash
The hash of the FunctionName. It is the same as Export.Hash[0].
Definition: intro_types.h:1502
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:136
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
static INTSTATUS IntWinProcMarkAgent(WIN_PROCESS_OBJECT *Process, BOOLEAN Mark)
Mark the given process as being an agent.
Definition: winprocess.c:364
static INTSTATUS IntWinProcDeleteProcessObject(QWORD EprocessAddress, QWORD Cr3, DWORD Pid)
Used to delete the process from the Introcore internal structures.
Definition: winprocess.c:2171
void * CmdLineSwapHandle
The swap memory handle for the UNICODE_STRING containing the command line of the a process...
Definition: winprocess.h:255
VAD * IntWinVadFindAndUpdateIfNecessary(WIN_PROCESS_OBJECT *Process, QWORD StartHint, QWORD LengthHint)
Searches for a VAD in the Introcore VAD tree. If no VAD is found, or if the found one does not fully ...
Definition: winvad.c:2122
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
Definition: introcore.c:627
BYTE RawDump[ALERT_MAX_INJ_DUMP_SIZE]
The source buffer contents.
Definition: intro_types.h:1492
This is the structure as documented in winternl.h.
Definition: wddefs.h:753
#define INT_STATUS_INVALID_DATA_TYPE
Definition: introstatus.h:139
DWORD Count
The number of currently protected processes.
Definition: intro_types.h:2424
INTSTATUS IntExceptGetVictimProcess(void *Process, QWORD DestinationGva, DWORD Length, QWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim process for injection violations...
static void IntWinProcGetImageBaseNameFromPath(const WCHAR *FullPath, CHAR *BaseName, const WCHAR **FullName)
Get the BaseName and FullName of an image from the FullPath.
Definition: winprocess.c:957
void IntWinAgentCheckIfProcessAgentAndDecrement(CHAR *ImageName, BOOLEAN *IsAgent, DWORD *Tag, BOOLEAN *Removed)
Checks if a process is an agent or not, and decrements the ref count of that name.
Definition: winagent.c:3084
INTSTATUS IntWinProcPatchPspInsertProcess86(QWORD FunctionAddress, void *Handler, void *Descriptor)
This functions is responsible for patching the detour that handles the "PspInsertProcess".
Definition: winprocess.c:2346
INTSTATUS IntWinProcHandleCreate(void *Detour)
Detour handler for the PspInsertProcess Windows kernel API.The actual process creation is handled by ...
Definition: winprocess.c:2610
#define PROC_OPT_PROT_INJECTION
Aggregates all the flags that will generate introEventInjectionViolation events.
Definition: intro_types.h:379
struct _EVENT_MEMCOPY_VIOLATION::@298 Victim
#define STATIC_ASSERT(Cond, Msg)
Definition: introdefs.h:50
INTSTATUS IntWinPfnLockGpa(QWORD Gpa, WIN_PFN_LOCK **PfnLock)
Locks a guest physical address.
Definition: winpfn.c:820
INTSTATUS IntWinSDProtectSecDesc(WIN_PROCESS_OBJECT *Process)
This function saves the security descriptor address and ACLs into the WIN_PROCESS_OBJECT structure...
Definition: winsecdesc.c:750
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:96
INTSTATUS IntWinProcChangeProtectionFlags(WIN_PROCESS_OBJECT *Process, DWORD OldMask, DWORD NewMask)
This function changes the protection flags for the given process.
Definition: winprocess.c:4046
#define FIELD_OFFSET(type, field)
Definition: introdefs.h:239
WIN_SUBSYTEM_TYPE SubsystemType
Process subsystem type.
Definition: winprocess.h:57
BOOLEAN GlueIsScanEnginesApiAvailable(void)
Checks if the third party memory scanning engines are present.
Definition: glue.c:1284
QWORD PebAddress
The Process Environment Block of this subsystem.
Definition: winprocess.h:59
#define PROC_OPT_BETA
Process is monitored, but in log-only mode so no actions will be blocked.
Definition: intro_types.h:376
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
#define NACL_CMD_LINE
#define PROC_OPT_PROT_WRITE_MEM
Blocks foreign write inside the target process.
Definition: intro_types.h:348
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:735
QWORD PageCount
The number of 4K pages in the VAD.
Definition: winvad.h:110
DWORD MonitorVad
TRUE if we need to handle VAD events for this process.
Definition: winprocess.h:162
#define PROC_OPT_PROT_UNPACK
Identifies unpacking/decryption attempts in the main executable.
Definition: intro_types.h:346
DWORD StaticDetected
TRUE if the process was detected using a static scan (during static init).
Definition: winprocess.h:140
QWORD Rip
The RIP at which the exception was triggered.
Definition: intro_types.h:1990
#define LIST_HEAD_INIT(Name)
Definition: introlists.h:39
#define _Out_writes_z_(expr)
Definition: intro_sal.h:37
Measures the handling of memory reads in which a read protection policy exists.
Definition: stats.h:72
PCHAR Names[MAX_OFFSETS_PER_NAME]
The names pointing to this RVA. Each name will point inside the Names structure inside WINUM_CACHE_EX...
Definition: winumcache.h:31
#define IC_TAG_SUBS
Process subsystem structure.
Definition: memtags.h:65
WORD Length
The length, in bytes, of the string in Buffer, not including the NULL terminator, if any...
Definition: wddefs.h:139
#define INT_STATUS_NOT_INITIALIZED_HINT
Definition: introstatus.h:320
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
#define __likely(x)
Definition: common.h:63
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
Definition: introcore.c:2845
static INTSTATUS IntWinProcSendProcessEvent(WIN_PROCESS_OBJECT *Process, BOOLEAN Created, BOOLEAN Crashed)
Send a process creation/termination event.
Definition: winprocess.c:448
#define PROC_OPT_PROT_INSTRUMENT
Blocks foreing processes from setting instrumentation callbacks inside the target process (Windows on...
Definition: intro_types.h:366
Measures the information gathering for the DPI mechanism.
Definition: stats.h:83
INTSTATUS IntWinProcPatchSwapOut32(QWORD FunctionAddress, void *Handler, void *Descriptor)
This functions is responsible for patching the detour that handles the "KiOutSwapProcesses".
Definition: winprocess.c:2443
void IntWinProcDumpProtected(void)
Log all the protected processes.
Definition: winprocess.c:3912
EXCEPTION_VICTIM_MODULE Library
The victim module of the modified library.
Definition: exceptions.h:877
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
LIST_HEAD gWinProcesses
The list of all the processes inside the guest.
Definition: winprocesshp.c:11
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
#define IC_TAG_PPIF
Protected process info.
Definition: memtags.h:81
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
#define INTRO_OPT_PROT_KM_TOKEN_PRIVS
Enable protection over Token Privileges bitmaps.
Definition: intro_types.h:505
BOOLEAN Crashed
True if the process crashed.
Definition: intro_types.h:1921
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
DWORD IsAgent
TRUE if this is an injected agent.
Definition: winprocess.h:131
INTSTATUS IntNotifyIntroErrorState(INTRO_ERROR_STATE State, INTRO_ERROR_CONTEXT *Context)
Definition: glue.c:989
INTSTATUS IntWinInspectCommandLine(PWIN_PROCESS_OBJECT Process)
Send a command line scan request to the scan engines.
Definition: wincmdline.c:24
void IntAlertFillWinUmModule(const WIN_PROCESS_MODULE *Module, INTRO_MODULE *EventModule)
Fills information about a user mode module inside an alert.
Definition: alerts.c:653
DWORD Outswapped
TRUE if the process is outswapped.
Definition: winprocess.h:169
DWORD Crc32String(const char *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated utf-8 string.
Definition: crc32.c:200
INTSTATUS IntIcFlushVaSpace(PINS_CACHE Cache, QWORD Cr3)
Flush an entire virtual address space.
Definition: icache.c:797
The agent process started execution.
Definition: intro_types.h:2101
static INTSTATUS IntWinProcSendProcessExceptionEvent(WIN_PROCESS_OBJECT *Process)
Send a process exception event.
Definition: winprocess.c:507
This is the structure as documented in winternl.h.
Definition: wddefs.h:851
VAD * Vad
The internal structure of the modified VAD.
Definition: exceptions.h:876
const PROTECTED_PROCESS_INFO gSystemProcesses[]
This is a list with system processes and their default protection mask.
Definition: winprocess.c:82
#define CRITICAL(fmt,...)
Definition: glue.h:63
const PROTECTED_PROCESS_INFO gWinForcedProtectedProcesses[]
This is a list with non system processes that have a default protection mask.
Definition: winprocess.c:131
Holds register state.
Definition: glueiface.h:30
Measures exits on NtSetInformationProcess.
Definition: stats.h:100
INTSTATUS IntWinModRemoveModule(PWIN_PROCESS_MODULE Module)
Removes a Windows module.
Definition: winummodule.c:2043
Exits caused by "MmCopyVirtualMemory".
Definition: winprocess.h:44
Exits caused by "PspSetContextThreadInternal".
Definition: winprocess.h:45
void IntWinProcUpdateProtectedProcess(const void *Name, const CAMI_STRING_ENCODING Encoding, const CAMI_PROT_OPTIONS *Options)
This function updates the protection for the given process.
Definition: winprocess.c:3657
Informational event sent when a hardware exception is triggered by a guest process. See EVENT_EXCEPTION_EVENT.
Definition: intro_types.h:111
INTRO_PROCESS Parent
The parent of the process.
Definition: intro_types.h:1935
const PROTECTED_PROCESS_INFO * IntWinProcGetProtectedInfoEx(PWCHAR Path, BOOLEAN IsSystem)
Returns a pointer to the PROTECTED_PROCESS_INFO structure for the given process Path.
Definition: winprocess.c:1070
QWORD SourceVirtualAddress
The virtual address of the source buffer.
Definition: intro_types.h:1464
INTSTATUS IntWinGuestFindDriversNamespace(void)
Runs the driver object namespace search.
Definition: winobj.c:1855
QWORD EndPage
Definition: winvad.h:106
QWORD DestinationVirtualAddress
The virtual address of the destination buffer.
Definition: intro_types.h:1474
void IntWinProcUninit(void)
This function removes all process objects from the list, and registers the calls the cleanup function...
Definition: winprocess.c:3940
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
Definition: guests.h:328
char CHAR
Definition: intro_types.h:56
#define INTRO_OPT_IN_GUEST_PT_FILTER
Enable in-guest page-table filtering (64-bit Windows only).
Definition: intro_types.h:461
#define KEXEC_OPT_EXEC_DISABLE
Disables execution rights for memory that contains data. Enables DEP.
Definition: wddefs.h:1431
static INTSTATUS IntWinGetProcCmdLineHandleBufferInMemory(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Called from within IntSwapMemReadData when the command line buffer of a process has been fully read...
Definition: winprocess.c:655
PWCHAR FullNamePattern
Full application name pattern.
Definition: winguest.h:70
This represents a read done from another process.
Definition: intro_types.h:1414
PWIN_PROCESS_SUBSYSTEM Subsystemx86
The x86 subsystem. Note that a 32 bit process on a 64 bit OS may have both subsystems valid...
Definition: winprocess.h:308
void IntWinVadProcessInit(WIN_PROCESS_OBJECT *Process)
Initializes a WIN_PROCESS_OBJECT.VadTree.
Definition: winvad.c:462
struct _WIN_PROCESS_OBJECT * PWIN_PROCESS_OBJECT
Definition: windpi.h:17
This is the structure as documented in winternl.h.
Definition: wddefs.h:764
INTSTATUS IntWinModUnHookModule(PWIN_PROCESS_MODULE Module)
Remove the protection from the indicated module.
Definition: winummodule.c:1205
String will be encoded in utf-16.
Definition: update_guests.h:55
static INTSTATUS IntWinGetPrcoCmdLineHandleCmdLineInMemory(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Called from within IntSwapMemReadData when the UNICODE_STRING32 or UNICODE_STRING64 structure that co...
Definition: winprocess.c:749
Exposes the functions responsible for DPI (Deep Process Inspection) information gathering (used to de...
DWORD AgentTag
If IsAgent is TRUE, this will be the agent tag.
Definition: winprocess.h:233
INTSTATUS IntWinProcCreateProcessObject(WIN_PROCESS_OBJECT **Process, QWORD EprocessAddress, PBYTE EprocessBuffer, QWORD ParentEprocess, QWORD RealParentEprocess, QWORD Cr3, DWORD Pid, BOOLEAN StaticScan)
Allocates a WIN_PROCESS_OBJECT structure for the given process.
Definition: winprocess.c:1544
A representation of a Windows VAD structure.
Definition: winvad.h:80
DWORD IsMainModule
TRUE if this is the main module.
Definition: winummodule.h:47
#define PAGE_MASK
Definition: pgtable.h:35
INTSTATUS IntWinProcProtect(WIN_PROCESS_OBJECT *Process)
Protects a new process.
Definition: winprocess.c:3287
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
QWORD Buffer
The guest virtual address at which the wide-character string is located.
Definition: wddefs.h:146
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:271
DWORD Size
Virtual size of the module.
Definition: winummodule.h:35
DWORD IsStack
Set if the memory range represented by this VAD is a stack.
Definition: winvad.h:154
WINUM_CACHE_EXPORT * Export
The export cache for the modified module.
Definition: exceptions.h:843
Describes a function to be hooked.
Definition: detours.h:329
int strlower_utf8(char *buf, size_t len)
Definition: introcrt.c:57
#define SWAPMEM_OPT_UM_FAULT
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory...
Definition: swapmem.h:21
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 IntWinProcUpdateProtection(void)
Iterates trough the global process list (gWinProcesses) in order to update the protection state for e...
Definition: winprocess.c:1162
Exposes the functions used to schedule an asynchronous command line scan and receives its result...
size_t SIZE_T
Definition: intro_types.h:60
#define FALSE
Definition: intro_types.h:34
static INTSTATUS IntWinProcRemoveSubsystem(WIN_PROCESS_SUBSYSTEM *Subsystem)
Removes a process subsystem.
Definition: winprocess.c:614
This structure describes a running process inside the guest.
Definition: winprocess.h:83
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68
WCHAR * Path
The string which represents the user-mode module path.
Definition: winumpath.h:17