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 
27 #define CMDLINE_LEN_NO_SCAN ALERT_CMDLINE_MAX_LEN
28 
35 #define CMDLINE_MAX_LEN (WORD_MAX - 1)
36 
38 extern RBTREE gWinProcTreeCr3;
41 
55 
56 
60 static LIST_HEAD gWinProtectedProcesses = LIST_HEAD_INIT(gWinProtectedProcesses);
61 
66 
70 const WCHAR gSystemPath[] = u"\\windows\\system32\\";
71 
75 const WCHAR gSysWowPath[] = u"\\windows\\syswow64\\";
76 
81 {
82  {
83  .ImageBaseNamePattern = "smss.exe",
84  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
85  .FullPathPattern = u"c:\\windows\\system32\\smss.exe",
86  .FullNamePattern = u"smss.exe"
87  },
88 
89  {
90  .ImageBaseNamePattern = "csrss.exe",
91  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
92  .FullPathPattern = u"c:\\windows\\system32\\csrss.exe",
93  .FullNamePattern = u"csrss.exe"
94  },
95 
96  {
97  .ImageBaseNamePattern = "wininit.exe",
98  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
99  .FullPathPattern = u"c:\\windows\\system32\\wininit.exe",
100  .FullNamePattern = u"wininit.exe"
101  },
102 
103  {
104  .ImageBaseNamePattern = "winlogon.exe",
105  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
106  .FullPathPattern = u"c:\\windows\\system32\\winlogon.exe",
107  .FullNamePattern = u"winlogon.exe"
108  },
109 
110  {
111  .ImageBaseNamePattern = "lsass.EXE",
112  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
113  .FullPathPattern = u"c:\\windows\\system32\\lsass.EXE",
114  .FullNamePattern = u"lsass.exe"
115  },
116 
117  {
118  .ImageBaseNamePattern = "services.EXE",
119  .Protection = { .Original = PROC_OPT_PROT_INJECTION, .Current = PROC_OPT_PROT_INJECTION },
120  .FullPathPattern = u"c:\\windows\\system32\\services.EXE",
121  .FullNamePattern = u"services.exe"
122  },
123 };
124 
125 
130 {
131  {
132  .ImageBaseNamePattern = "powershell.exe",
133  .Protection = { .Original = PROC_OPT_PROT_SCAN_CMD_LINE, .Current = PROC_OPT_PROT_SCAN_CMD_LINE },
134  .FullPathPattern = u"c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe",
135  .FullNamePattern = u"powershell.exe"
136  },
137 };
138 
139 
144 static const char *gCmdLineProcesses[] =
145 {
146  "svchost.exe",
147  "chrome.exe", // Needed in order to detect NaCl instances
148 
149  // these are rather generic processes that host external code which may generate alerts (especially injections)
150  "rundll32.exe",
151  "dllhost.exe",
152 
153  "winword.exe",
154  "excel.exe",
155  "powerpnt.exe",
156 
157  "wscript.exe",
158  "mshta.exe",
159 };
160 
161 
162 static INTSTATUS
164  _In_ QWORD EprocessAddress,
165  _In_ QWORD Cr3,
166  _In_ DWORD Pid
167  );
168 
169 static INTSTATUS
171  _In_ WIN_PROCESS_OBJECT *Process
172  );
173 
174 static INTSTATUS
176  _In_ WIN_PROCESS_OBJECT *Process,
177  _Out_ WIN_PROCESS_SUBSYSTEM **Subsystem,
178  _In_ BYTE SubsystemType
179  );
180 
181 
182 static BOOLEAN
184  _In_ QWORD EprocessAddress,
185  _In_ BYTE *Eprocess
186  )
196 {
197  WIN_MITIGATION_FLAGS2 flags2 = { 0 };
198 
199  // If older than Windows 10 Redstone 3
200  if (gGuest.OSVersion < 16299)
201  {
202  return FALSE;
203  }
204 
205  if (0 == WIN_KM_FIELD(Process, MitigationFlags2))
206  {
207  WARNING("[WARNING] MitigationFlags2 Offset in Eprocess is not known for Windows version %d!\n",
208  gGuest.OSVersion);
209 
210  return FALSE;
211  }
212 
213  memcpy(&flags2, Eprocess + WIN_KM_FIELD(Process, MitigationFlags2), sizeof(flags2));
214 
215  TRACE("[WINPROC] Process @ 0x%016llx has Mitigation Flags 2 = 0x%08x\n", EprocessAddress, flags2.Flags);
216 
217  return flags2.Flags != 0;
218 }
219 
220 
221 static INTSTATUS
223  _In_ WIN_PROCESS_OBJECT *Process
224  )
232 {
233  INTSTATUS status;
234  DWORD offset;
235  BYTE execopts;
236 
237  // Assume that DEP is not enforced
238  Process->EnforcedDep = FALSE;
239 
240  // Not protected against exploits, leave it be.
241  if (!Process->ProtExploits)
242  {
244  }
245 
246  // If the process flags enable beta detections, don't do the DEP enforcement as it will crash the application.
247  if (IntPolicyProcIsBeta(Process, 0))
248  {
250  }
251 
252  // There is no way to not have DEP for a 64-bit process, so there's nothing left for us to do
253  if (gGuest.Guest64 && !Process->Wow64Process)
254  {
256  }
257 
258  offset = WIN_KM_FIELD(Process, KexecOptions);
259  if (0 == offset)
260  {
262  }
263 
264  status = IntKernVirtMemRead(Process->EprocessAddress + offset, 1, &execopts, NULL);
265  if (!INT_SUCCESS(status))
266  {
267  ERROR("[ERROR] Failed fetching the _KEXECUTE_OPTIONS from %llx: 0x%08x\n", Process->EprocessAddress, status);
268  return status;
269  }
270 
271  // Make sure we clear ExecuteEnable and set ExecuteDisable and Permanent flags.
272  execopts &= ~KEXEC_OPT_EXEC_ENABLE;
274 
275  status = IntVirtMemSafeWrite(gGuest.Mm.SystemCr3, Process->EprocessAddress + offset, 1, &execopts, IG_CS_RING_0);
276  if (!INT_SUCCESS(status))
277  {
278  ERROR("[ERROR] Failed patching the _KEXECUTE_OPTIONS at %llx: 0x%08x\n", Process->EprocessAddress, status);
279  return status;
280  }
281 
282  Process->EnforcedDep = TRUE;
283 
284  return INT_STATUS_SUCCESS;
285 }
286 
287 
288 static INTSTATUS
290  _In_ WIN_PROCESS_OBJECT *Process
291  )
302 {
303  INTSTATUS status;
304  char c[2];
305 
306  if (!Process->Protected)
307  {
308  memcpy(c, &Process->OriginalSpareValue, 2);
309  }
310  else
311  {
312  c[0] = '*';
313  c[1] = 0;
314 
315  if (Process->MonitorVad)
316  {
317  c[1] |= winProcExitVad;
318  }
319 
320  if (Process->ProtWriteMem)
321  {
322  c[1] |= winProcExitWriteMemory;
323 
324  if (Process->Lsass)
325  {
326  c[1] |= winProcExitReadMemory;
327  }
328  }
329 
330  if (Process->ProtThreadCtx)
331  {
332  c[1] |= winProcExitThreadCtx;
333  }
334 
335  if (Process->ProtQueueApc)
336  {
337  c[1] |= winProcExitQueueApc;
338  }
339  }
340 
342  Process->EprocessAddress + WIN_KM_FIELD(Process, Spare),
343  sizeof(c),
344  &c,
345  IG_CS_RING_0);
346  if (!INT_SUCCESS(status))
347  {
348  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
349  return status;
350  }
351 
352  return INT_STATUS_SUCCESS;
353 }
354 
355 
356 static INTSTATUS
358  _In_ WIN_PROCESS_OBJECT *Process,
359  _In_ BOOLEAN Mark
360  )
372 {
373  INTSTATUS status;
374  CHAR c;
375 
376  c = Mark ? '?' : '\0';
377 
379  Process->EprocessAddress + WIN_KM_FIELD(Process, Name) + 14,
380  1,
381  &c,
382  IG_CS_RING_0);
383  if (!INT_SUCCESS(status))
384  {
385  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
386  return status;
387  }
388 
389  return INT_STATUS_SUCCESS;
390 }
391 
392 
393 static INTSTATUS
395  _In_ WIN_PROCESS_OBJECT *Process,
396  _In_ BOOLEAN Created
397  )
408 {
409  INTSTATUS status;
410  PEVENT_AGENT_EVENT pAgentEvent;
411 
412  if (!Process->IsAgent)
413  {
415  }
416 
417  pAgentEvent = &gAlert.Agent;
418  memzero(pAgentEvent, sizeof(*pAgentEvent));
419 
420  pAgentEvent->Event = Created ? agentStarted : agentTerminated;
421  pAgentEvent->AgentTag = Process->AgentTag;
422 
423  if (!Created)
424  {
425  pAgentEvent->ErrorCode = Process->ExitStatus;
426  }
427 
429 
430  status = IntNotifyIntroEvent(introEventAgentEvent, pAgentEvent, sizeof(*pAgentEvent));
431  if (!INT_SUCCESS(status))
432  {
433  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
434  }
435 
436  return INT_STATUS_SUCCESS;
437 }
438 
439 
440 static INTSTATUS
442  _In_ WIN_PROCESS_OBJECT *Process,
443  _In_ BOOLEAN Created,
444  _In_ BOOLEAN Crashed
445  )
457 {
458  INTSTATUS status;
459  PEVENT_PROCESS_EVENT pProcEvent;
460  WIN_PROCESS_OBJECT *pParent;
461 
463  {
465  }
466 
467  pProcEvent = &gAlert.Process;
468  memzero(pProcEvent, sizeof(*pProcEvent));
469 
470  pProcEvent->Created = Created;
471  pProcEvent->Protected = Process->Protected ? TRUE : FALSE;
472  pProcEvent->Crashed = Crashed;
473  pProcEvent->ExitStatus = Process->ExitStatus;
474 
476 
477  IntAlertFillWinProcess(Process, &pProcEvent->Child);
478 
479  pParent = IntWinProcFindObjectByEprocess(Process->ParentEprocess);
480  if (NULL != pParent)
481  {
482  IntAlertFillWinProcess(pParent, &pProcEvent->Parent);
483  }
484  else
485  {
486  pProcEvent->Parent.Valid = FALSE;
487  }
488 
489  status = IntNotifyIntroEvent(introEventProcessEvent, pProcEvent, sizeof(*pProcEvent));
490  if (!INT_SUCCESS(status))
491  {
492  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
493  }
494 
495  return status;
496 }
497 
498 
499 static INTSTATUS
501  _In_ WIN_PROCESS_OBJECT *Process
502  )
513 {
514  INTSTATUS status;
515  PEVENT_EXCEPTION_EVENT pExceptionEvent;
516 
518  {
520  }
521 
522  if (0 == Process->LastException)
523  {
525  }
526 
527  LOG("[PROCESS] Last exception encountered in %s: 0x%08x @ RIP 0x%016llx\n",
528  Process->Name, Process->LastException, Process->LastExceptionRip);
529 
530  pExceptionEvent = &gAlert.Exception;
531  memzero(pExceptionEvent, sizeof(*pExceptionEvent));
532 
533  pExceptionEvent->Continuable = Process->LastExceptionContinuable;
534  pExceptionEvent->ExceptionCode = Process->LastException;
535  pExceptionEvent->Rip = Process->LastExceptionRip;
536 
537  IntAlertFillWinProcess(Process, &pExceptionEvent->CurrentProcess);
538 
539  status = IntNotifyIntroEvent(introEventExceptionEvent, pExceptionEvent, sizeof(*pExceptionEvent));
540  if (!INT_SUCCESS(status))
541  {
542  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
543  }
544 
545  return INT_STATUS_SUCCESS;
546 }
547 
548 
549 static void
551  _In_ WIN_PROCESS_SUBSYSTEM *Subsystem
552  )
558 {
559  if (gGuest.Guest64 && (winSubsys32Bit == Subsystem->SubsystemType))
560  {
561  Subsystem->SystemDirPath = gSysWowPath;
562  }
563  else
564  {
565  Subsystem->SystemDirPath = gSystemPath;
566  }
567 }
568 
569 
570 INTSTATUS
572  _In_ WIN_PROCESS_OBJECT *Process,
573  _Out_ WIN_PROCESS_SUBSYSTEM **Subsystem,
574  _In_ BYTE SubsystemType
575  )
586 {
587  WIN_PROCESS_SUBSYSTEM *pSubs = HpAllocWithTag(sizeof(*pSubs), IC_TAG_SUBS);
588  if (NULL == pSubs)
589  {
591  }
592 
593  pSubs->Process = Process;
594  pSubs->SubsystemType = SubsystemType;
595 
597 
599 
600  *Subsystem = pSubs;
601 
602  return INT_STATUS_SUCCESS;
603 }
604 
605 
606 static INTSTATUS
608  _In_ WIN_PROCESS_SUBSYSTEM *Subsystem
609  )
618 {
619  LIST_ENTRY *listMod;
620  PWIN_PROCESS_MODULE pMod;
621 
622  if (NULL == Subsystem)
623  {
625  }
626 
627  listMod = Subsystem->ProcessModules.Flink;
628  while (listMod != &Subsystem->ProcessModules)
629  {
630  pMod = CONTAINING_RECORD(listMod, WIN_PROCESS_MODULE, Link);
631 
632  listMod = listMod->Flink;
633 
634  RemoveEntryList(&pMod->Link);
635 
636  IntWinModUnHookModule(pMod);
637 
638  IntWinModRemoveModule(pMod);
639  }
640 
641  HpFreeAndNullWithTag(&Subsystem, IC_TAG_SUBS);
642 
643  return INT_STATUS_SUCCESS;
644 }
645 
646 
647 static INTSTATUS
649  _In_ void *Context,
650  _In_ QWORD Cr3,
651  _In_ QWORD VirtualAddress,
652  _In_ QWORD PhysicalAddress,
653  _In_reads_bytes_(DataSize) void *Data,
654  _In_ DWORD DataSize,
655  _In_ DWORD Flags
656  )
673 {
674  INTSTATUS status = INT_STATUS_SUCCESS;
675  WIN_PROCESS_OBJECT *pProcess = NULL;
676  PCHAR pCmdLine = NULL;
677 
679  UNREFERENCED_PARAMETER(VirtualAddress);
680  UNREFERENCED_PARAMETER(PhysicalAddress);
681  UNREFERENCED_PARAMETER(Flags);
682 
683  if (NULL == Context)
684  {
686  }
687 
688  if (NULL == Data)
689  {
691  }
692 
693  pProcess = (PWIN_PROCESS_OBJECT)Context;
694 
695  pProcess->CmdBufSwapHandle = NULL;
696 
697  // The command line is a WCHAR buffer that is not necessarily NULL-terminated. Introcore saves it as a
698  // NULL-terminated CHAR buffer, so allocate half the size + 1 extra CHAR for the NULL-terminator;
699  // there's no need to explicitly add the NULL-terminator at the end, as the allocator already gives
700  // as a 0-filled buffer.
701  pProcess->CommandLineSize = DataSize / sizeof(WCHAR) + 1;
702 
703  pCmdLine = HpAllocWithTag(pProcess->CommandLineSize, IC_TAG_PCMD);
704  if (NULL == pCmdLine)
705  {
707  }
708 
709  // It is ok to pass CommandLineSize here as the function will stop at CommandLineSize - 1
710  pProcess->CommandLine = utf16tolowerutf8(pCmdLine, Data, pProcess->CommandLineSize);
711 
712  TRACE("[PROCESS] Process `%s` with PID %d and EPROCESS `0x%016llx` started with command line `%s`\n",
713  pProcess->Name, pProcess->Pid, pProcess->EprocessAddress, pProcess->CommandLine);
714 
715  // For chrome.exe, check if this is a NaCl instance
716  if (0 == strcasecmp(pProcess->Name, "chrome.exe"))
717  {
718 #define NACL_CMD_LINE "--type=nacl-loader" // NaCl processes have this switch in the command line
719 
720  if (strstr(pProcess->CommandLine, NACL_CMD_LINE))
721  {
722  LOG("[WINPROC] Process `%s` (%d) with command line `%s` has NaCl enabled!\n",
723  pProcess->Name, pProcess->Pid, pProcess->CommandLine);
724  pProcess->HasNaClEnabled = TRUE;
725  }
726  }
727 
729  {
730  status = IntWinInspectCommandLine(pProcess);
731  if (!INT_SUCCESS(status))
732  {
733  ERROR("[ERROR] IntWinPsInspectCommandLine failed: 0x%x\n", status);
734  }
735  }
736 
737  return status;
738 }
739 
740 
741 static INTSTATUS
743  _In_ void *Context,
744  _In_ QWORD Cr3,
745  _In_ QWORD VirtualAddress,
746  _In_ QWORD PhysicalAddress,
747  _In_reads_bytes_(DataSize) void *Data,
748  _In_ DWORD DataSize,
749  _In_ DWORD Flags
750  )
765 {
766  INTSTATUS status = INT_STATUS_SUCCESS;
767  WIN_PROCESS_OBJECT *pProcess = Context;
768  DWORD readLength;
769  QWORD gva;
770 
772  UNREFERENCED_PARAMETER(VirtualAddress);
773  UNREFERENCED_PARAMETER(PhysicalAddress);
774  UNREFERENCED_PARAMETER(DataSize);
775  UNREFERENCED_PARAMETER(Flags);
776 
777  if (NULL == Context)
778  {
780  }
781 
782  if (NULL == Data)
783  {
785  }
786 
787  pProcess->CmdLineSwapHandle = NULL;
788 
789  readLength = (pProcess->ProtectionMask & PROC_OPT_PROT_SCAN_CMD_LINE) ?
791 
792  if ((gGuest.Guest64 && pProcess->Wow64Process) || (!gGuest.Guest64))
793  {
794  UNICODE_STRING32 *pUsCmdLine = (UNICODE_STRING32 *)Data;
795 
796  readLength = MIN(readLength, pUsCmdLine->Length);
797  gva = pUsCmdLine->Buffer;
798  }
799  else
800  {
801  UNICODE_STRING64 *pUsCmdLine = (UNICODE_STRING64 *)Data;
802 
803  readLength = MIN(readLength, pUsCmdLine->Length);
804  gva = pUsCmdLine->Buffer;
805  }
806 
807  status = IntSwapMemReadData(pProcess->Cr3, gva, readLength, SWAPMEM_OPT_UM_FAULT, Context, 0,
809  if (!INT_SUCCESS(status))
810  {
811  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
812  }
813 
814  return status;
815 }
816 
817 
818 static INTSTATUS
820  _In_ void *Context,
821  _In_ QWORD Cr3,
822  _In_ QWORD VirtualAddress,
823  _In_ QWORD PhysicalAddress,
824  _In_reads_bytes_(DataSize) void *Data,
825  _In_ DWORD DataSize,
826  _In_ DWORD Flags
827  )
842 {
843  INTSTATUS status;
844  WIN_PROCESS_OBJECT *pProcess = Context;
845  DWORD readSize;
846  QWORD usersParamsGva;
847 
849  UNREFERENCED_PARAMETER(VirtualAddress);
850  UNREFERENCED_PARAMETER(PhysicalAddress);
851  UNREFERENCED_PARAMETER(DataSize);
852  UNREFERENCED_PARAMETER(Flags);
853 
854  if (NULL == Context)
855  {
857  }
858 
859  if (NULL == Data)
860  {
862  }
863 
864  pProcess->ParamsSwapHandle = NULL;
865 
866  if ((gGuest.Guest64 && pProcess->Wow64Process) || (!gGuest.Guest64))
867  {
868  usersParamsGva = *(DWORD *)Data;
869  usersParamsGva += FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS32, CommandLine);
870  readSize = sizeof(UNICODE_STRING32);
871  }
872  else
873  {
874  usersParamsGva = *(QWORD *)Data;
875  usersParamsGva += FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS64, CommandLine);
876 
877  readSize = sizeof(UNICODE_STRING64);
878  }
879 
880  // read UserParameters.CommandLine
881  status = IntSwapMemReadData(pProcess->Cr3, usersParamsGva, readSize, SWAPMEM_OPT_UM_FAULT, Context,
883  if (!INT_SUCCESS(status))
884  {
885  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
886  }
887 
888  return status;
889 }
890 
891 
892 INTSTATUS
894  _In_ WIN_PROCESS_OBJECT *Process
895  )
903 {
904  INTSTATUS status;
905  QWORD gva;
906  DWORD readSize;
907 
908  if (NULL == Process)
909  {
911  }
912 
913  if ((gGuest.Guest64 && Process->Wow64Process) || (!gGuest.Guest64))
914  {
915  if (0 == Process->Peb32Address)
916  {
917  WARNING("[WARNING] Peb32 is NULL!\n");
919  }
920 
921  gva = Process->Peb32Address + FIELD_OFFSET(PEB32, ProcessParameters);
922  readSize = sizeof(DWORD);
923  }
924  else
925  {
926  if (0 == Process->Peb64Address)
927  {
928  WARNING("[WARNING] Peb64 is NULL!\n");
930  }
931 
932  gva = Process->Peb64Address + FIELD_OFFSET(PEB64, ProcessParameters);
933 
934  readSize = sizeof(QWORD);
935  }
936 
937  // Read Peb.RtlUserProcessParameters
938  status = IntSwapMemReadData(Process->Cr3, gva, readSize, SWAPMEM_OPT_UM_FAULT, Process, 0,
939  IntWinGetPrcoCmdLineHandleUserParamsInMemory, NULL, &Process->ParamsSwapHandle);
940  if (!INT_SUCCESS(status))
941  {
942  ERROR("[ERROR] IntSwapMemReadData failed: 0x%x\n", status);
943  }
944 
945  return status;
946 }
947 
948 
949 static void
951  _In_ const WCHAR *FullPath,
953  _Out_ const WCHAR **FullName
954  )
962 {
963  SIZE_T fplen, len;
964  DWORD i;
965  const WCHAR *pivot;
966 
967  len = 0;
968  fplen = wstrlen(FullPath);
969 
970  // copy the base name locally.
971  pivot = FullPath + fplen;
972 
973  do
974  {
975  pivot--;
976  } while ((pivot >= FullPath) && (*pivot != u'\\'));
977 
978  pivot++;
979 
980  *FullName = pivot;
981 
982  for (i = 0; (i < 15) && (pivot[i] != 0); i++)
983  {
984  BaseName[i] = (CHAR)pivot[i]; // This is what the kernel does internally, so we're safe.
985  }
986 
987  BaseName[i] = 0;
988 
989  while ((len < IMAGE_BASE_NAME_LEN) && (BaseName[len] != 0))
990  {
991  len++;
992  }
993 
994  // Fill in the end of the name with NULLs.
995  if (len < IMAGE_BASE_NAME_LEN)
996  {
997  memset(BaseName + len, 0, IMAGE_BASE_NAME_LEN - len);
998  }
999 
1000  BaseName[14] = 0;
1001 }
1002 
1003 
1004 static const PROTECTED_PROCESS_INFO *
1006  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
1007  _In_ BOOLEAN IsSystem
1008  )
1018 {
1019  LIST_ENTRY *list;
1020 
1022  {
1023  for (DWORD i = 0; i < ARRAYSIZE(gWinForcedProtectedProcesses); i++)
1024  {
1025  if (IntMatchPatternUtf8(gWinForcedProtectedProcesses[i].ImageBaseNamePattern,
1026  BaseName,
1028  {
1029  return &gWinForcedProtectedProcesses[i];
1030  }
1031  }
1032 
1033  list = gWinProtectedProcesses.Flink;
1034  while (list != &gWinProtectedProcesses)
1035  {
1037 
1038  list = list->Flink;
1039 
1041  {
1042  return pProc;
1043  }
1044  }
1045  }
1046 
1047  if (0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_UM_SYS_PROCS) && IsSystem)
1048  {
1049  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1050  {
1051  if (IntMatchPatternUtf8(gSystemProcesses[i].ImageBaseNamePattern, BaseName, INTRO_MATCH_TRUNCATED))
1052  {
1053  return &gSystemProcesses[i];
1054  }
1055  }
1056  }
1057 
1058  return NULL;
1059 }
1060 
1061 
1062 const PROTECTED_PROCESS_INFO *
1064  _In_ PWCHAR Path,
1065  _In_ BOOLEAN IsSystem
1066  )
1076 {
1077  LIST_ENTRY *list;
1078  CHAR baseName[16];
1079  const WCHAR *fullName;
1080  BOOLEAN match;
1081 
1082  fullName = NULL;
1083 
1084  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
1085 
1086  // Search the misc process list.
1088  {
1089  for (DWORD i = 0; i < ARRAYSIZE(gWinForcedProtectedProcesses); i++)
1090  {
1091  // Make sure the image base name matches.
1092  match = IntMatchPatternUtf8(gWinForcedProtectedProcesses[i].ImageBaseNamePattern,
1093  baseName,
1095 
1096  // Make sure the full name matches.
1097  match = match && IntMatchPatternUtf16(gWinForcedProtectedProcesses[i].FullNamePattern, fullName, 0);
1098 
1099  if (match)
1100  {
1101  return &gWinForcedProtectedProcesses[i];
1102  }
1103  }
1104 
1105  list = gWinProtectedProcesses.Flink;
1106  while (list != &gWinProtectedProcesses)
1107  {
1109 
1110  list = list->Flink;
1111 
1112  // Make sure the image base name matches.
1114 
1115  // Make sure the full name matches.
1116  match = match && IntMatchPatternUtf16(pProc->FullNamePattern, fullName, 0);
1117 
1118  // Make sure the full path matches, if present.
1119  if ((0 != (gGuest.CoreOptions.Current & INTRO_OPT_FULL_PATH)) &&
1120  (0 == (pProc->Flags & PROT_PROC_FLAG_NO_PATH)))
1121  {
1122  match = match && IntMatchPatternUtf16(pProc->FullPathPattern, Path, 0);
1123  }
1124 
1125  if (match)
1126  {
1127  return pProc;
1128  }
1129  }
1130  }
1131 
1132  // Search the system process list,
1133  if (0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_UM_SYS_PROCS) && IsSystem)
1134  {
1135  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1136  {
1137  // Make sure the image base name matches.
1138  match = IntMatchPatternUtf8(gSystemProcesses[i].ImageBaseNamePattern, baseName, INTRO_MATCH_TRUNCATED);
1139 
1140  // Make sure the full name matches.
1141  match = match && IntMatchPatternUtf16(gSystemProcesses[i].FullNamePattern, fullName, 0);
1142 
1143  if (match)
1144  {
1145  return &gSystemProcesses[i];
1146  }
1147  }
1148  }
1149 
1150  return NULL;
1151 }
1152 
1153 
1154 INTSTATUS
1156  void
1157  )
1164 {
1165  LIST_ENTRY *pList = gWinProcesses.Flink;
1166  while (pList != &gWinProcesses)
1167  {
1168  INTSTATUS status;
1170  const PROTECTED_PROCESS_INFO *pProtInfo;
1171 
1172  pList = pList->Flink;
1173 
1174  if (pProc->SystemProcess && pProc->Protected)
1175  {
1177  }
1178 
1179  // Check if the process is protected or not.
1180  if (NULL != pProc->Path)
1181  {
1182  pProtInfo = IntWinProcGetProtectedInfoEx(pProc->Path->Path, !!pProc->SystemProcess);
1183  }
1184  else
1185  {
1186  pProtInfo = IntWinProcGetProtectedInfo(pProc->Name, !!pProc->SystemProcess);
1187  }
1188 
1189  if (NULL != pProtInfo)
1190  {
1191  // We can end up with an inconsistent state if we attempt to re-protect a process (we could deactivate
1192  // the protection and then re-activate it with the new flags).
1193  // Note that the next time a process with the given name will start, the flags provided now will be used
1194  // to protect it.
1195  if (pProc->Context != pProtInfo->Context)
1196  {
1197  pProc->Context = pProtInfo->Context;
1198  }
1199 
1200  pProc->FeedbackMask = pProtInfo->Protection.Feedback;
1201  pProc->BetaMask = pProtInfo->Protection.Beta;
1202 
1203  if (pProc->Protected && (pProtInfo->Protection.Current != pProc->ProtectionMask))
1204  {
1205  // Process is already protected, but with other flags.
1206  LOG("[PROCESS] Changing protection flags for process %s (Eprocess %llx): 0x%x -> 0x%x\n",
1207  pProc->Name, pProc->EprocessAddress, pProc->ProtectionMask, pProtInfo->Protection.Original);
1208 
1209  status = IntWinProcChangeProtectionFlags(pProc, pProc->ProtectionMask, pProtInfo->Protection.Original);
1210  if (!INT_SUCCESS(status))
1211  {
1212  INTSTATUS status2;
1213 
1214  status2 = IntWinProcUnprotect(pProc);
1215  if (!INT_SUCCESS(status2))
1216  {
1217  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status2);
1218  }
1219 
1220  memset(&gErrorContext, 0, sizeof(gErrorContext));
1223 
1226  &gErrorContext);
1227  }
1228  }
1229  else if (!pProc->Protected)
1230  {
1231  LOG("[PROCESS] Process %s (Eprocess %llx) has already started, will activate static protection\n",
1232  pProc->Name, pProc->EprocessAddress);
1233 
1234  pProc->LateProtection = TRUE;
1235  pProc->ProtectionMask = pProtInfo->Protection.Current;
1236 
1237  pProc->Protected = TRUE;
1238  pProc->Context = pProtInfo->Context;
1239 
1240  status = IntWinProcProtect(pProc);
1241  if (!INT_SUCCESS(status))
1242  {
1243  ERROR("[ERROR] IntWinProcActivateProtection failed: 0x%x\n", status);
1244  }
1245  }
1246  }
1247  else
1248  {
1249  if (pProc->Protected)
1250  {
1251  LOG("[PROCESS] Deactivating protection for process %s (Pid %d, Cr3 0x%016llx)\n",
1252  pProc->Name, pProc->Pid, pProc->Cr3);
1253 
1254  status = IntWinProcUnprotect(pProc);
1255  if (!INT_SUCCESS(status))
1256  {
1257  ERROR("[ERROR] IntWinProcUnhookProcess failed for 0x%016llx (Cr3 0x%016llx): 0x%08x\n",
1258  pProc->EprocessAddress, pProc->Cr3, status);
1259  }
1260  }
1261  }
1262  }
1263 
1264  return INT_STATUS_SUCCESS;
1265 }
1266 
1267 
1268 static void
1270  _In_ QWORD Cr3,
1271  _In_ QWORD Eprocess
1272  )
1286 {
1287  WIN_PROCESS_OBJECT *duplicate;
1288 
1289  duplicate = IntWinProcFindObjectByCr3(Cr3);
1290  if (NULL != duplicate)
1291  {
1292  INTSTATUS status;
1293 
1294  ERROR("[ERROR] Duplicate process for CR3 0x%016llx: '%s', will remove it.\n", Cr3, duplicate->Name);
1295 
1296  status = IntWinProcDeleteProcessObject(duplicate->EprocessAddress, Cr3, duplicate->Pid);
1297  if (!INT_SUCCESS(status))
1298  {
1299  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
1300  }
1301  }
1302 
1303  duplicate = IntWinProcFindObjectByEprocess(Eprocess);
1304  if (NULL != duplicate)
1305  {
1306  INTSTATUS status;
1307 
1308  ERROR("[ERROR] Duplicate process for EPROCESS 0x%016llx: '%s', will remove it.\n", Eprocess, duplicate->Name);
1309 
1310  status = IntWinProcDeleteProcessObject(Eprocess, duplicate->Cr3, duplicate->Pid);
1311  if (!INT_SUCCESS(status))
1312  {
1313  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
1314  }
1315  }
1316 }
1317 
1318 
1319 static void
1321  _Inout_ WIN_PROCESS_OBJECT *Process,
1322  _In_ const BYTE *EprocessBuffer
1323  )
1337 {
1338  if (gGuest.KptiActive)
1339  {
1340  if (gGuest.Guest64)
1341  {
1342  Process->UserCr3 = *(QWORD const *)(EprocessBuffer + WIN_KM_FIELD(Process, UserCr3));
1343 
1344  if (Process->UserCr3 < PAGE_SIZE)
1345  {
1346  Process->UserCr3 = Process->Cr3;
1347  }
1348  }
1349  else
1350  {
1351  if (Process->Pid != 4)
1352  {
1353  Process->UserCr3 = Process->Cr3 | 0x20;
1354  }
1355  else
1356  {
1357  Process->UserCr3 = Process->Cr3;
1358  }
1359  }
1360  }
1361  else
1362  {
1363  Process->UserCr3 = Process->Cr3;
1364  }
1365 }
1366 
1367 
1368 static INTSTATUS
1370  _In_ WIN_PROCESS_OBJECT *Process
1371  )
1385 {
1386  INTSTATUS status;
1387 
1388  status = IntWinPfnLockGpa(Process->Cr3, (WIN_PFN_LOCK **)&Process->Cr3PageLockObject);
1389  if (!INT_SUCCESS(status))
1390  {
1391  ERROR("[ERROR] IntWinPfnLockGpa failed for process '%s', eprocess %llx, cr3 %llx: 0x%08x\n",
1392  Process->Name, Process->EprocessAddress, Process->Cr3, status);
1393 
1395 
1396  return status;
1397  }
1398 
1399  if ((Process->UserCr3 != Process->Cr3) && (Process->UserCr3 >= PAGE_SIZE))
1400  {
1401  status = IntWinPfnLockGpa(Process->UserCr3, (PWIN_PFN_LOCK *)&Process->UserCr3PageLockObject);
1402  if (!INT_SUCCESS(status))
1403  {
1404  ERROR("[ERROR] IntWinPfnLockGpa failed for process '%s', eprocess %llx, user cr3 %llx: 0x%08x\n",
1405  Process->Name, Process->EprocessAddress, Process->UserCr3, status);
1406 
1408 
1409  return status;
1410  }
1411  }
1412 
1413  return INT_STATUS_SUCCESS;
1414 }
1415 
1416 
1417 static void
1419  _Inout_ WIN_PROCESS_OBJECT *Process,
1420  _In_ const WIN_PROCESS_OBJECT *Parent
1421  )
1435 {
1436  for (DWORD i = 0; i < ARRAYSIZE(gSystemProcesses); i++)
1437  {
1438  if (0 == strcasecmp(Process->Name, gSystemProcesses[i].ImageBaseNamePattern))
1439  {
1440  // We've found a system process name. Make sure it was started by another system process.
1441  // Special case is services.exe, which although is flagged as system, can't spawn other system processes.
1442  // If it could, it would be trivial to register a service 'c:\csrss.exe', which would be started by
1443  // services.exe, and would be flagged as system.
1444  if ((NULL != Parent) && (Parent->SystemProcess))
1445  {
1446  if (0 == strcasecmp("services.exe", Parent->Name))
1447  {
1448  WARNING("[WARNING] Process '%s' is started by services.exe! Will not be flagged as system!\n",
1449  Process->Name);
1450  }
1451  else
1452  {
1453  Process->SystemProcess = TRUE;
1454  }
1455  }
1456  else if (NULL == Parent && 0 == Process->ParentEprocess)
1457  {
1458  // This is an important thing: if we are being initialized from within the OS or after hibernation,
1459  // we CAN'T safely determine if a process is system or not. Therefore, we will do a hack: whenever
1460  // a process with a system name is created, and that process is not in fact a system process, we will
1461  // slightly patch it's name, so that it won't match anymore on resume from hibernation.
1462  // Right here we assume that all processes that have a system name are actually legitimate. If we're
1463  // being started from within the OS, we can assume anything - the system may well be very infected
1464  // already. Note that we will have a parent when we monitor process creation, but we don't have the
1465  // parent when getting the already created list of processes. In that case, the parent will be 0.
1466  Process->SystemProcess = TRUE;
1467  }
1468 
1469  // We had name match, but the process isn't in fact system. We have to patch the name.
1470  if (!Process->SystemProcess)
1471  {
1472  BYTE c = '!';
1473  INTSTATUS status;
1474 
1475  WARNING("[WARNING] Process '%s' is not in fact system; parent is 0x%016llx\n",
1476  Process->Name, Process->ParentEprocess);
1477 
1478  // Scramble the name inside the EPROCESS.
1479  status = IntVirtMemSafeWrite(0, Process->EprocessAddress + WIN_KM_FIELD(Process, Name),
1480  1, &c, IG_CS_RING_0);
1481  if (!INT_SUCCESS(status))
1482  {
1483  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
1484  }
1485  }
1486 
1487  break;
1488  }
1489  }
1490 }
1491 
1492 
1493 INTSTATUS
1495  _Out_ WIN_PROCESS_OBJECT **Process,
1496  _In_ QWORD EprocessAddress,
1497  _In_ PBYTE EprocessBuffer,
1498  _In_ QWORD ParentEprocess,
1499  _In_ QWORD RealParentEprocess,
1500  _In_ QWORD Cr3,
1501  _In_ DWORD Pid,
1502  _In_ BOOLEAN StaticScan
1503  )
1523 {
1524  INTSTATUS status;
1525  BOOLEAN isAgent;
1526  WIN_PROCESS_OBJECT *pProc, *pParent, *pRealParent;
1527  const BOOLEAN protTokenPtr = 0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_KM_TOKEN_PTR);
1528  const BOOLEAN protTokenPrivs = 0 != (gGuest.CoreOptions.Current & INTRO_OPT_PROT_KM_TOKEN_PRIVS);
1529 
1530  if (NULL == Process)
1531  {
1533  }
1534 
1535  if (0 == EprocessAddress)
1536  {
1538  }
1539 
1540  if (NULL == EprocessBuffer)
1541  {
1543  }
1544 
1545  IntWinProcHandleDuplicate(Cr3, EprocessAddress);
1546 
1547  pProc = HpAllocWithTag(sizeof(*pProc), IC_TAG_POBJ);
1548  if (NULL == pProc)
1549  {
1551  }
1552 
1553  // Now we can actually initialize the process.
1554  STATIC_ASSERT(IMAGE_BASE_NAME_LEN == 2 * sizeof(QWORD), "QWORD by QWORD copy of process name will fail");
1555 
1556  *(QWORD *)(pProc->Name) = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Name));
1557  *(QWORD *)(pProc->Name + sizeof(QWORD)) = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Name) + sizeof(QWORD));
1558 
1559  pProc->Name[CSTRLEN(pProc->Name)] = 0;
1560 
1561  // Workaround for system process, which doesn't have a ImageName
1562  if ((pProc->Name[0] == 0) && (4 == Pid))
1563  {
1564  strlcpy(pProc->Name, "system", sizeof(pProc->Name));
1565  }
1566 
1567  IntWinVadProcessInit(pProc);
1568 
1569  strlower_utf8(pProc->Name, strlen(pProc->Name));
1570 
1571  pProc->NameHash = Crc32String(pProc->Name, INITIAL_CRC_VALUE);
1572  pProc->Cr3 = Cr3;
1573  pProc->Pid = Pid;
1574  pProc->EprocessAddress = EprocessAddress;
1575  pProc->ParentEprocess = ParentEprocess;
1576  pProc->RealParentEprocess = RealParentEprocess;
1577  pProc->StaticDetected = StaticScan;
1578  pProc->LateProtection = StaticScan;
1579 
1580  IntWinProcSetUserCr3(pProc, EprocessBuffer);
1581 
1582  // Lock the CR3 of this process in memory. We don't want the OS to mangle with the CR3, since it is used
1583  // for exceptions.
1584  // NOTE: This is a hard-error, we disable Introcore if this fails.
1585  status = IntWinProcLockCr3(pProc);
1586  if (!INT_SUCCESS(status))
1587  {
1588  goto cleanup_and_exit;
1589  }
1590 
1591  if (4 != Pid)
1592  {
1593  pProc->CreationTime = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, CreateTime));
1594  }
1595  else
1596  {
1597  // Workaround for the System process: when the System process is originally created, it has
1598  // CreationTime 0. Sometimes after that, the kernel will modify it to reflect the actual creation
1599  // time, but it's too late for us. In order to ensure that we will always have the same uuid for the
1600  // System process, we force the Creationtime to 0.
1601  pProc->CreationTime = 0;
1602  }
1603 
1604  if (gGuest.Guest64)
1605  {
1606  if (0 != WIN_KM_FIELD(Process, SectionBase))
1607  {
1608  pProc->MainModuleAddress = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, SectionBase));
1609  }
1610 
1611  pProc->OriginalTokenPtr = EX_FAST_REF_TO_PTR(TRUE, *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Token)));
1612 
1613  if (4 != Pid)
1614  {
1615  pProc->Peb64Address = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Peb));
1616  pProc->Peb32Address = *(QWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, WoW64));
1617 
1618  // Starting with Windows 10, build > 10240 (TH1), WoW64Process doesn't point directly to the
1619  // PEB32, but instead to a _EWOW64PROCESS, which contains the PEB address (first 8 bytes) and the
1620  // machine type (next 2 bytes).
1622  {
1623  status = IntKernVirtMemFetchQword(pProc->Peb32Address, &pProc->Peb32Address);
1624  if (!INT_SUCCESS(status))
1625  {
1626  ERROR("[ERROR] IntKernVirtMemFetchQword failed for %llx (EWOW64): 0x%08x\n",
1627  pProc->Peb32Address,
1628  status);
1629 
1630  goto cleanup_and_exit;
1631  }
1632  }
1633 
1634  if (0 != pProc->Peb32Address && gGuest.Guest64)
1635  {
1636  pProc->Wow64Process = TRUE;
1637  }
1638  }
1639  }
1640  else
1641  {
1642  if (0 != WIN_KM_FIELD(Process, SectionBase))
1643  {
1644  pProc->MainModuleAddress = *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, SectionBase));
1645  }
1646 
1647  pProc->OriginalTokenPtr = EX_FAST_REF_TO_PTR(FALSE, *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Token)));
1648 
1649  if (4 != Pid)
1650  {
1651  pProc->Peb64Address = *(DWORD *)(EprocessBuffer + WIN_KM_FIELD(Process, Peb));
1652  pProc->Peb32Address = pProc->Peb64Address;
1653 
1654  pProc->Wow64Process = FALSE;
1655  }
1656  }
1657 
1658  // Protect the token privileges, if needed.
1659  status = IntWinTokenPrivsProtectOnProcess(pProc);
1660  if (!INT_SUCCESS(status))
1661  {
1662  ERROR("[ERROR] IntWinTokenPrivsProtectOnProcess failed: 0x%08x\n", status);
1663  }
1664 
1665  // Get the original spare value. Applying the protection will overwrite the Spare field
1666  // in in-guest EPROCESS so we should save it before.
1667  status = IntKernVirtMemRead(pProc->EprocessAddress + WIN_KM_FIELD(Process, Spare),
1668  sizeof(pProc->OriginalSpareValue), &pProc->OriginalSpareValue, NULL);
1669  if (!INT_SUCCESS(status))
1670  {
1671  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
1672  goto cleanup_and_exit;
1673  }
1674 
1675  if (0 != pProc->OriginalSpareValue)
1676  {
1677  WARNING("[WARNING] Spare value for eprocess 0x%016llx at offset %x is not 0! (0x%04x)\n",
1678  pProc->EprocessAddress, WIN_KM_FIELD(Process, Spare), pProc->OriginalSpareValue);
1679  }
1680 
1681  // pParent and pRealParent will be NULL if ParentEprocess, or RealParentEprocess are 0
1683  pRealParent = IntWinProcFindObjectByEprocess(pProc->RealParentEprocess);
1684 
1685  if (protTokenPtr && !StaticScan)
1686  {
1687  if (pParent != NULL)
1688  {
1689  status = IntWinTokenPtrCheckIntegrityOnProcess(pParent);
1690  if (!INT_SUCCESS(status))
1691  {
1692  WARNING("[WARNING] IntWinTokenPtrCheckIntegrityOnProcess failed for parent 0x%016llx: 0x%x\n",
1693  pParent->EprocessAddress, status);
1694  }
1695  }
1696 
1697  if (pRealParent != NULL)
1698  {
1699  status = IntWinTokenPtrCheckIntegrityOnProcess(pRealParent);
1700  if (!INT_SUCCESS(status))
1701  {
1702  WARNING("[WARNING] IntWinTokenPtrCheckIntegrityOnProcess failed for real parent 0x%016llx: 0x%x\n",
1703  pRealParent->EprocessAddress, status);
1704  }
1705  }
1706  }
1707 
1708  if (protTokenPrivs && !StaticScan)
1709  {
1710  if (pParent != NULL)
1711  {
1712  status = IntWinTokenPrivsCheckIntegrityOnProcess(pParent);
1713  if (!INT_SUCCESS(status))
1714  {
1715  WARNING("[WARNING] IntWinTokenPrivsCheckIntegrityOnProcess failed for parent 0x%016llx: 0x%x\n",
1716  pParent->EprocessAddress, status);
1717  }
1718  }
1719 
1720  if (pRealParent != NULL)
1721  {
1722  status = IntWinTokenPrivsCheckIntegrityOnProcess(pRealParent);
1723  if (!INT_SUCCESS(status))
1724  {
1725  WARNING("[WARNING] IntWinTokenPrivsCheckIntegrityOnProcess failed for real parent 0x%016llx: 0x%x\n",
1726  pRealParent->EprocessAddress, status);
1727  }
1728  }
1729  }
1730 
1731  if (4 == Pid)
1732  {
1733  // The initial System process is always marked as system.
1734  pProc->SystemProcess = TRUE;
1735 
1736  if (pProc->Cr3 != gGuest.Mm.SystemCr3)
1737  {
1738  WARNING("[WARNING] Possible System CR3 (0x%016llx) mismatch: "
1739  "System process (0x%016llx) has CR3 0x%016llx\n",
1740  gGuest.Mm.SystemCr3, pProc->EprocessAddress, pProc->Cr3);
1741  }
1742  }
1743 
1744  IntWinProcMarkAsSystemProcess(pProc, pParent);
1745 
1746  // If this is the "services.exe" process, than this means the we can now safely inject remediation agents.
1747  if (0 == strcasecmp(pProc->Name, "services.exe"))
1748  {
1749  status = IntAgentEnableInjection();
1750  if (!INT_SUCCESS(status))
1751  {
1752  ERROR("[ERROR] IntAgentEnableInjection failed: 0x%08x\n", status);
1753  }
1754 
1756  if (!INT_SUCCESS(status))
1757  {
1758  ERROR("[ERROR] IntWinGuestFindDriversNamespace: 0x%08x\n", status);
1759  }
1760 
1762  {
1764  }
1765  }
1766 
1767  if (0 == strcasecmp(pProc->Name, "lsass.exe"))
1768  {
1769  pProc->Lsass = 1;
1770  }
1771 
1772  IntWinAgentCheckIfProcessAgentAndIncrement(pProc->Name, &isAgent, &pProc->AgentTag);
1773 
1774  pProc->IsAgent = isAgent;
1775 
1776  if (gGuest.Guest64)
1777  {
1778  // If we're on 64 bit windows than we will surely have 64 bit subsystem.
1780  if (!INT_SUCCESS(status))
1781  {
1782  ERROR("[ERROR] IntWinProcCreateProcessSubsystem failed: 0x%08x\n", status);
1783  goto cleanup_and_exit;
1784  }
1785 
1786  pProc->Subsystemx64->PebAddress = pProc->Peb64Address;
1787 
1788  if (NULL != pParent && pParent->Wow64Process)
1789  {
1790  if (!pProc->Wow64Process)
1791  {
1792  TRACE("------------> Special case %s (0x%016llx) / 32 -> %s (0x%016llx) / 64\n",
1793  pParent->Name, pParent->EprocessAddress, pProc->Name, pProc->EprocessAddress);
1794  }
1795 
1796  pProc->ParentWow64 = TRUE;
1797  }
1798  }
1799 
1800  if (!gGuest.Guest64 || pProc->Wow64Process)
1801  {
1802  // 32 bit guests and Wow64 processes also have a 32 bit subsystem.
1804  if (!INT_SUCCESS(status))
1805  {
1806  ERROR("[ERROR] IntWinProcCreateProcessSubsystem failed: 0x%08x\n", status);
1807  goto cleanup_and_exit;
1808  }
1809 
1810  pProc->Subsystemx86->PebAddress = pProc->Peb32Address;
1811  }
1812 
1813  // Determine if the process will be protected or not. A process will be protected if:
1814  // 1. It is inside the list of protected processes.
1815  // 2. It is a system process
1816  // 3. The flag INTRO_OPT_ENABLE_PROTECTION_ALL was used at creation.
1817  // Note: we don't care about static protection; that must be enabled & used by default from now on!
1819  {
1820  const PROTECTED_PROCESS_INFO *pProtInfo = IntWinProcGetProtectedInfo(pProc->Name, !!pProc->SystemProcess);
1821  if (NULL != pProtInfo)
1822  {
1823  pProc->Protected = TRUE;
1824  pProc->ProtectionMask = pProtInfo->Protection.Current;
1825  pProc->BetaMask = pProtInfo->Protection.Beta;
1826  pProc->FeedbackMask = pProtInfo->Protection.Feedback;
1827  pProc->Context = pProtInfo->Context;
1828  }
1829  }
1830 
1831  // If we are running on Napoca, we don`t want to obtain the entire command line for multiple reasons:
1832  // 1) Napoca does not support the scan engines, so they can not call our callback function
1833  // (resulting in a memory leak since the callback function is used to free the command line buffer).
1834  // 2) Reading the command line using #PF can bring an unnecessary performance penalty.
1836  {
1837  status = IntWinProcReadCommandLine(pProc);
1838  if (!INT_SUCCESS(status))
1839  {
1840  ERROR("[ERROR] IntWinProcReadCommandLine failed: 0x%x\n", status);
1841  }
1842  }
1843  else
1844  {
1845  for (DWORD i = 0; i < ARRAYSIZE(gCmdLineProcesses); i++)
1846  {
1847  if (0 == strncmp(pProc->Name, gCmdLineProcesses[i], strlen(pProc->Name)))
1848  {
1849  status = IntWinProcReadCommandLine(pProc);
1850  if (!INT_SUCCESS(status))
1851  {
1852  ERROR("[ERROR] IntWinProcReadCommandLine failed: 0x%x\n", status);
1853  }
1854 
1855  break;
1856  }
1857  }
1858  }
1859 
1860  if (pProc->LateProtection || pProc->StaticDetected || pProc->SystemProcess)
1861  {
1862  pProc->StartInitializing = TRUE;
1863  pProc->Initialized = TRUE;
1864 
1865  // don't allow one time exceptions for static detected processes
1866  pProc->OneTimeInjectionDone = TRUE;
1867  }
1868 
1869  if (pProc->Protected)
1870  {
1871  pProc->ExploitGuardEnabled = IntWinProcIsExploitGuardEnabled(EprocessAddress, EprocessBuffer);
1872  TRACE("[WINPROC] Process `%s` has Exploit Guard %s\n",
1873  pProc->Name, pProc->ExploitGuardEnabled ? "Enabled" : "Disabled");
1874  }
1875 
1876  InsertTailList(&gWinProcesses, &pProc->Link);
1877 
1878  // Note: we cannot have errors here, because:
1879  // 1. we supply valid arguments (so no STATUS_INVALID_PARAMETER can occur)
1880  // 2. at the beginning of the function, we check for duplicates by searching for both the CR3 and EPROCESS (so
1881  // we cannot have STATUS_KEY_ALREADY_PRESENT either).
1882  RbInsertNode(&gWinProcTreeCr3, &pProc->NodeCr3);
1883 
1884  RbInsertNode(&gWinProcTreeUserCr3, &pProc->NodeUserCr3);
1885 
1886  RbInsertNode(&gWinProcTreeEprocess, &pProc->NodeEproc);
1887 
1888  if (pProc->StaticDetected && !pProc->IsAgent)
1889  {
1890  pProc->IsAgent = pProc->IsPreviousAgent = '?' == pProc->Name[14];
1891  }
1892 
1893  status = IntWinSelfMapGetAndCheckSelfMapEntry(pProc);
1894  if (!INT_SUCCESS(status))
1895  {
1896  ERROR("[ERROR] IntWinProcGetAndCheckSelfMapEntry failed: 0x%08x\n", status);
1897  }
1898 
1899  if (__unlikely(4 == pProc->Pid))
1900  {
1901  status = IntWinSelfMapProtectSelfMapIndex(pProc);
1902  if (!INT_SUCCESS(status))
1903  {
1904  ERROR("[ERROR] IntWinProcProtectSelfMapIndex failed: 0x%08x\n", status);
1905  }
1906  }
1907 
1908  status = IntWinProcProtect(pProc);
1909  if (!INT_SUCCESS(status))
1910  {
1911  ERROR("[ERROR] IntWinProcProtect failed: 0x%08x\n", status);
1912  }
1913 
1914  if (!pProc->MonitorVad)
1915  {
1916  status = IntWinVadProcImportMainModuleVad(pProc);
1917  if (!INT_SUCCESS(status))
1918  {
1919  ERROR("[ERROR] IntWinProcImportMainModuleVad failed: 0x%08x\n", status);
1920  }
1921  }
1922 
1923  status = IntWinProcSendProcessEvent(pProc, TRUE, FALSE);
1924  if (!INT_SUCCESS(status))
1925  {
1926  ERROR("[ERROR] IntWinProcSendProcessEvent failed: 0x%08x\n", status);
1927  }
1928 
1929  status = IntWinProcSendAgentEvent(pProc, TRUE);
1930  if (!INT_SUCCESS(status))
1931  {
1932  ERROR("[ERROR] IntWinProcSendAgentEvent failed: 0x%08x\n", status);
1933  }
1934 
1935  TRACE("[PROCESS] '%s' (%08x), path %s, pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, "
1936  "UserCR3 0x%016llx, parent at 0x%016llx/0x%016llx; %s, %s.\n",
1937  pProc->Name, pProc->NameHash, pProc->Path ? utf16_for_log(pProc->Path->Path) : "<invalid>",
1938  Pid, pProc->EprocessAddress, pProc->Cr3, pProc->UserCr3, ParentEprocess, RealParentEprocess,
1939  pProc->SystemProcess ? "SYSTEM" : "not system", pProc->IsAgent ? "AGENT" : "not agent");
1940 
1941  *Process = pProc;
1942 
1943  return INT_STATUS_SUCCESS;
1944 
1945 cleanup_and_exit:
1946  if (NULL != pProc)
1947  {
1948  IntWinProcRemoveProcess(pProc);
1949  }
1950 
1951  return status;
1952 }
1953 
1954 
1955 static INTSTATUS
1957  _In_ WIN_PROCESS_OBJECT *Process
1958  )
1969 {
1970  INTSTATUS status;
1971 
1972  if (NULL != Process->Cr3PageLockObject)
1973  {
1974  status = IntWinPfnRemoveLock(Process->Cr3PageLockObject, FALSE);
1975  if (!INT_SUCCESS(status))
1976  {
1977  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
1978  }
1979 
1980  Process->Cr3PageLockObject = NULL;
1981  }
1982 
1983  if (NULL != Process->UserCr3PageLockObject)
1984  {
1985  status = IntWinPfnRemoveLock(Process->UserCr3PageLockObject, FALSE);
1986  if (!INT_SUCCESS(status))
1987  {
1988  ERROR("[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
1989  }
1990 
1991  Process->UserCr3PageLockObject = NULL;
1992  }
1993 
1994  // Restore the first two letters in the spare
1996  Process->EprocessAddress + WIN_KM_FIELD(Process, Spare),
1997  2,
1998  &Process->OriginalSpareValue,
1999  IG_CS_RING_0);
2000  if (!INT_SUCCESS(status))
2001  {
2002  ERROR("[ERROR] IntKernVirtMemWrite failed: 0x%08x\n", status);
2003  }
2004 
2005  // Remove the command line swap handle.
2006  if (NULL != Process->CmdBufSwapHandle)
2007  {
2008  status = IntSwapMemRemoveTransaction(Process->CmdBufSwapHandle);
2009  if (!INT_SUCCESS(status))
2010  {
2011  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2012  }
2013 
2014  Process->CmdBufSwapHandle = NULL;
2015  }
2016 
2017  if (NULL != Process->CmdLineSwapHandle)
2018  {
2019  status = IntSwapMemRemoveTransaction(Process->CmdLineSwapHandle);
2020  if (!INT_SUCCESS(status))
2021  {
2022  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2023  }
2024 
2025  Process->CmdLineSwapHandle = NULL;
2026  }
2027 
2028  if (NULL != Process->ParamsSwapHandle)
2029  {
2030  status = IntSwapMemRemoveTransaction(Process->ParamsSwapHandle);
2031  if (!INT_SUCCESS(status))
2032  {
2033  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2034  }
2035 
2036  Process->ParamsSwapHandle = NULL;
2037  }
2038 
2039  if (NULL != Process->Subsystemx64)
2040  {
2041  status = IntWinProcRemoveSubsystem(Process->Subsystemx64);
2042  if (!INT_SUCCESS(status))
2043  {
2044  ERROR("[ERROR] IntWinProcRemoveSubsystem failed: 0x%08x\n", status);
2045  }
2046 
2047  Process->Subsystemx64 = NULL;
2048  }
2049 
2050  if (NULL != Process->Subsystemx86)
2051  {
2052  status = IntWinProcRemoveSubsystem(Process->Subsystemx86);
2053  if (!INT_SUCCESS(status))
2054  {
2055  ERROR("[ERROR] IntWinProcRemoveSubsystem failed: 0x%08x\n", status);
2056  }
2057 
2058  Process->Subsystemx86 = NULL;
2059  }
2060 
2061  if (NULL != Process->MainModuleVad)
2062  {
2063  IntWinVadDestroyObject((VAD **)&Process->MainModuleVad);
2064  }
2065 
2067 
2068  // This must be the last thing done - we must call this AFTER removing all the other transactions
2069  // (those with handle) otherwise we may cause a use-after-free. Also, this must be done for TIB swaps - on
2070  // suspicious page executions, sometimes we need to swap in the TIB; there is no way to cleanly save handles for
2071  // those, since a page may be executed in the context of multiple threads, which would mean that it could be
2072  // possible to request multiple TIB swaps for the same page.
2073  status = IntSwapMemRemoveTransactionsForVaSpace(Process->Cr3);
2074  if (!INT_SUCCESS(status))
2075  {
2076  ERROR("[ERROR] IntSwapMemRemoveTransactionsForVaSpace failed: 0x%08x\n", status);
2077  }
2078 
2079  if (NULL != Process->VadPages)
2080  {
2081  HpFreeAndNullWithTag(&Process->VadPages, IC_TAG_VADP);
2082  }
2083 
2084  if (NULL != Process->CommandLine)
2085  {
2086  HpFreeAndNullWithTag(&Process->CommandLine, IC_TAG_PCMD);
2087  }
2088 
2089  HpFreeAndNullWithTag(&Process, IC_TAG_POBJ);
2090 
2091  return INT_STATUS_SUCCESS;
2092 }
2093 
2094 
2095 static INTSTATUS
2097  _In_ QWORD EprocessAddress,
2098  _In_ QWORD Cr3,
2099  _In_ DWORD Pid
2100  )
2115 {
2116  INTSTATUS status = INT_STATUS_SUCCESS;
2117  BOOLEAN bFound = FALSE;
2118  BOOLEAN isAgent = FALSE;
2119 
2120  LIST_ENTRY *list = gWinProcesses.Flink;
2121  while (list != &gWinProcesses)
2122  {
2124 
2125  list = list->Flink;
2126 
2127  // Reset the parent EPROCESS for every process that has the terminated process as a parent.
2128  if (pProc->ParentEprocess == EprocessAddress)
2129  {
2130  pProc->ParentEprocess = 0;
2131  }
2132 
2133  if (pProc->RealParentEprocess == EprocessAddress)
2134  {
2135  pProc->RealParentEprocess = 0;
2136  }
2137 
2138  if ((pProc->Pid == Pid) && (pProc->EprocessAddress == EprocessAddress) && (pProc->Cr3 == Cr3))
2139  {
2140  BOOLEAN bCrashed = FALSE;
2141  BOOLEAN lastAgent = FALSE;
2142 
2143  bFound = TRUE;
2144  pProc->Terminating = TRUE;
2145 
2146  // Get the crashed flag from the EPROCESS.
2147  if (0 != WIN_KM_FIELD(Process, Flags3))
2148  {
2149  DWORD flags3 = 0;
2150 
2151  status = IntKernVirtMemFetchDword(pProc->EprocessAddress + WIN_KM_FIELD(Process, Flags3), &flags3);
2152  if (!INT_SUCCESS(status))
2153  {
2154  ERROR("[ERROR] IntKernVirtMemFetchDword failed for 0x%016llx: 0x%08x\n",
2155  pProc->EprocessAddress + WIN_KM_FIELD(Process, Flags3), status);
2156  }
2157  else
2158  {
2159  bCrashed = 0 != (WIN_KM_FIELD(EprocessFlags, 3Crashed) & flags3);
2160  }
2161  }
2162 
2163  if (0 != WIN_KM_FIELD(Process, ExitStatus))
2164  {
2165  status = IntKernVirtMemFetchDword(EprocessAddress + WIN_KM_FIELD(Process, ExitStatus),
2166  &pProc->ExitStatus);
2167  if (!INT_SUCCESS(status))
2168  {
2169  ERROR("[ERROR] IntKernVirtMemFetchDword failed for 0x%016llx: 0x%08x\n",
2170  EprocessAddress + WIN_KM_FIELD(Process, ExitStatus), status);
2171  }
2172  }
2173 
2174  if (bCrashed)
2175  {
2176  TRACE("[PROCESS] Process `%d` with Eprocess at 0x%016llx and Cr3 0x%016llx crashed.\n",
2177  pProc->Pid, pProc->EprocessAddress, pProc->Cr3);
2178  }
2179 
2180  IntWinAgentCheckIfProcessAgentAndDecrement(pProc->Name, &isAgent, &pProc->AgentTag, &lastAgent);
2181  pProc->IsAgent = isAgent;
2182 
2183  TRACE("[PROCESS] '%s', pid %d, EPROCESS 0x%016llx, CR3 0x%016llx, UserCR3 0x%016llx just terminated\n",
2184  pProc->Name, pProc->Pid, pProc->EprocessAddress, pProc->Cr3, pProc->UserCr3);
2185 
2186  status = IntWinProcSendProcessExceptionEvent(pProc);
2187  if (!INT_SUCCESS(status))
2188  {
2189  ERROR("[ERROR] IntWinProcSendProcessExceptionEvent failed: 0x%08x\n", status);
2190  }
2191 
2192  status = IntWinProcSendProcessEvent(pProc, FALSE, bCrashed);
2193  if (!INT_SUCCESS(status))
2194  {
2195  ERROR("[ERROR] IntWinProcSendProcessEvent failed: 0x%08x\n", status);
2196  }
2197 
2198  if (lastAgent)
2199  {
2200  status = IntWinProcSendAgentEvent(pProc, FALSE);
2201  if (!INT_SUCCESS(status))
2202  {
2203  ERROR("[ERROR] IntWinProcSendAgentEvent failed: 0x%08x\n", status);
2204  }
2205  }
2206 
2207  RemoveEntryList(&pProc->Link);
2208 
2209  RbDeleteNode(&gWinProcTreeCr3, &pProc->NodeCr3);
2210 
2211  RbDeleteNode(&gWinProcTreeUserCr3, &pProc->NodeUserCr3);
2212 
2213  RbDeleteNode(&gWinProcTreeEprocess, &pProc->NodeEproc);
2214 
2215  status = IntWinSelfMapUnprotectSelfMapIndex(pProc);
2216  if (!INT_SUCCESS(status))
2217  {
2218  ERROR("[ERROR] IntWinProcUnprotectSelfMapIndex failed: 0x%08x\n", status);
2219  }
2220 
2221  if (pProc->Protected)
2222  {
2223  status = IntWinProcUnprotect(pProc);
2224  if (!INT_SUCCESS(status))
2225  {
2226  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
2227  }
2228  }
2229 
2230  // validate one last time the token privileges
2232  {
2234  if (!INT_SUCCESS(status) && (INT_STATUS_PAGE_NOT_PRESENT != status))
2235  {
2236  ERROR("[ERROR] IntWinTokenPrivsCheckIntegrityOnProcess failed: 0x%08x\n", status);
2237  }
2238  }
2239 
2240  // Validate one last time token and self map integrity
2242  {
2243  status = IntWinTokenPtrCheckIntegrityOnProcess(pProc);
2244  if (!INT_SUCCESS(status) && (INT_STATUS_PAGE_NOT_PRESENT != status))
2245  {
2246  ERROR("[ERROR] IntWinProcTokenCheckIntegrityInternal failed: 0x%08x\n", status);
2247  }
2248  }
2249 
2250  status = IntWinSelfMapGetAndCheckSelfMapEntry(pProc);
2251  if (!INT_SUCCESS(status))
2252  {
2253  ERROR("[ERROR] IntWinSelfMapGetAndCheckSelfMapEntry failed: 0x%08x\n", status);
2254  }
2255 
2256  status = IntWinProcRemoveProcess(pProc);
2257  if (!INT_SUCCESS(status))
2258  {
2259  ERROR("[ERROR] IntWinProcRemoveProcess failed: 0x%08x\n", status);
2260  }
2261  }
2262  }
2263 
2264  // Remove this process's entries from the list of pending UDs as this process terminated
2266 
2267  if (!bFound)
2268  {
2269  return INT_STATUS_NOT_FOUND;
2270  }
2271 
2272  return status;
2273 }
2274 
2275 
2276 INTSTATUS
2278  _In_ QWORD FunctionAddress,
2279  _In_ void *Handler,
2280  _In_ QWORD HandlerAddress
2281  )
2296 {
2297  PAPI_HOOK_HANDLER pHandler = Handler;
2298  DWORD offsetRetn = 0x09;
2299 
2300  UNREFERENCED_PARAMETER(FunctionAddress);
2301  UNREFERENCED_PARAMETER(HandlerAddress);
2302 
2303  if (gGuest.OSVersion == 7600 || gGuest.OSVersion == 9200)
2304  {
2305  pHandler->Code[offsetRetn] = 0x1C;
2306  }
2307 
2308  if (gGuest.OSVersion == 7601 || gGuest.OSVersion == 7602)
2309  {
2310  pHandler->Code[offsetRetn] = 0x20;
2311  }
2312 
2313  return INT_STATUS_SUCCESS;
2314 }
2315 
2316 
2317 static WIN_PROCESS_OBJECT *
2319  _In_ QWORD NewEprocess,
2320  _In_ QWORD ParentEprocess,
2321  _In_ QWORD DebugHandle,
2322  _Out_ INTRO_ACTION *Action
2323  )
2341 {
2342  INTSTATUS status;
2343  IG_ARCH_REGS *pRegs = &gVcpu->Regs;
2344  DWORD pid = 0;
2345  QWORD cr3, realParentEproc;
2346  PBYTE eprocessBuffer = NULL;
2347  WIN_PROCESS_OBJECT *pProc, *pParent;
2349  BOOLEAN skipChecks = FALSE;
2350 
2351  pProc = pParent = NULL;
2352 
2353  status = IntWinProcMapEprocess(NewEprocess, &eprocessBuffer);
2354  if (!INT_SUCCESS(status))
2355  {
2356  ERROR("[ERROR] IntWinProcMapEprocess failed: 0x%08x\n", status);
2357  goto _set_action_and_leave;
2358  }
2359 
2360  pid = *(DWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Id));
2361 
2362  if (gGuest.Guest64)
2363  {
2364  cr3 = *(QWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Cr3));
2365  }
2366  else
2367  {
2368  cr3 = *(DWORD *)(eprocessBuffer + WIN_KM_FIELD(Process, Cr3));
2369  }
2370 
2371  // First, try to get the real parent (by current Cr3)
2372  pParent = IntWinProcFindObjectByCr3(pRegs->Cr3);
2373  if (NULL == pParent)
2374  {
2375  // In case this fails, try to get it by the eprocess that Windows considers the parent
2376  pParent = IntWinProcFindObjectByEprocess(ParentEprocess);
2377  if (__unlikely(NULL == pParent && 4 == pid))
2378  {
2379  // System process does not have a parent
2380  skipChecks = TRUE;
2381  }
2382  else if (NULL == pParent)
2383  {
2384  CRITICAL("[ERROR] Both the real parent (Cr3 = 0x%016llx) and the parent "
2385  "(eprocess = 0x%016llx) are NULL for pid %d!\n", pRegs->Cr3, ParentEprocess, pid);
2386 
2387  goto _cleanup_and_leave;
2388  }
2389  }
2390 
2391  realParentEproc = pParent ? pParent->EprocessAddress : 0;
2392 
2393  status = IntWinProcCreateProcessObject(&pProc, NewEprocess, eprocessBuffer, ParentEprocess,
2394  realParentEproc, cr3, pid, FALSE);
2395  if (!INT_SUCCESS(status))
2396  {
2397  ERROR("[ERROR] IntWinProcCreateProcessObject failed: 0x%08x\n", status);
2398  goto _cleanup_and_leave;
2399  }
2400 
2401  if (skipChecks)
2402  {
2403  INFO("[INFO] Process %s (%d/0x%016llx) doesn't have either parent or real parent, will skip all checks\n",
2404  pProc->Name, pProc->Pid, pProc->EprocessAddress);
2405  goto _cleanup_and_leave;
2406  }
2407 
2408  if (__likely(pParent->Pid != 4))
2409  {
2411 
2412  IntWinDpiGatherDpiInfo(pProc, pParent, DebugHandle);
2413 
2415  }
2416 
2418 
2419  action = IntWinDpiCheckCreation(pProc, pParent);
2420 
2422 
2423 _cleanup_and_leave:
2424  IntVirtMemUnmap(&eprocessBuffer);
2425 
2426 _set_action_and_leave:
2427  *Action = action;
2428 
2429  return pProc;
2430 }
2431 
2432 
2433 INTSTATUS
2435  _In_ void *Detour
2436  )
2448 {
2449  INTSTATUS status;
2450  QWORD args[3] = { 0 };
2451  QWORD eprocess, parentEproc;
2452  QWORD possibleDebugHandle;
2453  INTRO_ACTION action;
2454  WIN_PROCESS_OBJECT *newProc;
2455 
2456  status = IntDetGetArguments(Detour, ARRAYSIZE(args), args);
2457  if (!INT_SUCCESS(status))
2458  {
2459  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
2460  return INT_STATUS_SUCCESS;
2461  }
2462 
2463  eprocess = args[0];
2464  parentEproc = args[1];
2465  possibleDebugHandle = args[2];
2466 
2467  newProc = IntWinProcHandleCreateInternal(eprocess, parentEproc, possibleDebugHandle, &action);
2468  if (newProc == NULL)
2469  {
2470  ERROR("[ERROR] IntWinProcHandleCreateInternal failed for 0x%016llx\n", eprocess);
2471  return INT_STATUS_SUCCESS;
2472  }
2473 
2474  if (introGuestNotAllowed == action)
2475  {
2476  IG_ARCH_REGS *pRegs = &gVcpu->Regs;
2477 
2478  status = IntWinProcDeleteProcessObject(newProc->EprocessAddress, newProc->Cr3, newProc->Pid);
2479  if (!INT_SUCCESS(status))
2480  {
2481  ERROR("[ERROR] IntWinProcDeleteProcessObject failed: 0x%08x\n", status);
2482  }
2483 
2484  // IntWinProcHandleCreate is the callback for when PspInsertProcess
2485  // is invoked. After the INT3 that causes the VmExit, there is a JMP
2486  // that sets the RIP to where the real PspInsertProcess call is - in case
2487  // the creation is allowed. On the other hand, blocking a process will be
2488  // done by incrementing the RIP (2 bytes) over the JMP (0xEB, 0x06), thus
2489  // setting the EAX to STATUS_ACCESS_DENIED and returning. For more information,
2490  // please consult "winhkhnd.c".
2491 
2492  pRegs->Rip += 0x02;
2493 
2494  status = IntSetGprs(gVcpu->Index, pRegs);
2495  if (!INT_SUCCESS(status))
2496  {
2497  ERROR("[ERROR] IntSetGprs failed: 0x%08x\n", status);
2498  }
2499  }
2500 
2501  return INT_STATUS_SUCCESS;
2502 }
2503 
2504 
2505 INTSTATUS
2507  _In_ void *Detour
2508  )
2520 {
2521  INTSTATUS status;
2522  DWORD pid;
2523  QWORD eprocess, pdbrBase;
2524 
2525  pid = 0;
2526  pdbrBase = 0;
2527 
2528  status = IntDetGetArgument(Detour, 0, NULL, 0, &eprocess);
2529  if (!INT_SUCCESS(status))
2530  {
2531  ERROR("[ERROR] IntDetGetArgument failed: 0x%08x\n", status);
2532  goto cleanup_and_exit;
2533  }
2534 
2535  status = IntKernVirtMemFetchDword(eprocess + WIN_KM_FIELD(Process, Id), &pid);
2536  if (!INT_SUCCESS(status))
2537  {
2538  ERROR("[ERROR] IntKernVirtMemFetchDword failed: 0x%08x\n", status);
2539  goto cleanup_and_exit;
2540  }
2541 
2542  // Get the PDBR base.
2543  status = IntKernVirtMemFetchQword(eprocess + WIN_KM_FIELD(Process, Cr3), &pdbrBase);
2544  if (!INT_SUCCESS(status))
2545  {
2546  ERROR("IntKernVirtMemFetchQword failed for 0x%016llx: 0x%08x\n",
2547  eprocess + WIN_KM_FIELD(Process, Cr3), status);
2548  goto cleanup_and_exit;
2549  }
2550 
2551  if (!gGuest.Guest64)
2552  {
2553  pdbrBase &= 0xFFFFFFFF;
2554  }
2555 
2556  status = IntWinProcDeleteProcessObject(eprocess, pdbrBase, pid);
2557  if (!INT_SUCCESS(status) && (INT_STATUS_NOT_FOUND != status))
2558  {
2559  ERROR("[ERROR] IntWinProcDeleteProcessObject failed for EPROCESS %llx, CR3 %llx, pid %d: 0x%08x\n",
2560  eprocess, pdbrBase, pid, status);
2561  }
2562 
2563 cleanup_and_exit:
2564 
2565  return status;
2566 }
2567 
2568 
2569 INTSTATUS
2571  _In_ QWORD FunctionAddress,
2572  _In_ void *Handler,
2573  _In_ QWORD HandlerAddress
2574  )
2589 {
2590  PAPI_HOOK_HANDLER pHandler = Handler;
2591 
2592  UNREFERENCED_PARAMETER(FunctionAddress);
2593  UNREFERENCED_PARAMETER(HandlerAddress);
2594 
2595  if (gGuest.Guest64)
2596  {
2597  *(DWORD *)(pHandler->Code + 0xD) = WIN_KM_FIELD(Process, Cr3);
2598 
2599  *(DWORD *)(pHandler->Code + 0x16) = WIN_KM_FIELD(Process, Spare);
2600  *(DWORD *)(pHandler->Code + 0x21) = WIN_KM_FIELD(Process, Spare);
2601 
2602  *(DWORD *)(pHandler->Code + 0x2c) = WIN_KM_FIELD(Process, Spare);
2603  *(DWORD *)(pHandler->Code + 0x36) = WIN_KM_FIELD(Process, Spare);
2604  }
2605  else
2606  {
2607  *(DWORD *)(pHandler->Code + 0x14) = WIN_KM_FIELD(Process, Cr3);
2608 
2609  *(DWORD *)(pHandler->Code + 0x1c) = WIN_KM_FIELD(Process, Spare);
2610  *(DWORD *)(pHandler->Code + 0x2f) = WIN_KM_FIELD(Process, Spare);
2611  }
2612 
2613  return INT_STATUS_SUCCESS;
2614 }
2615 
2616 
2617 static BOOLEAN
2619  _In_ QWORD SourceAddress,
2620  _In_ DWORD ReadSize,
2621  _In_ const WIN_PROCESS_OBJECT *Lsass,
2622  _Out_ WIN_PROCESS_MODULE **VictimModule
2623  )
2636 {
2637  QWORD srcEnd = SourceAddress + ReadSize - 1;
2638  LIST_ENTRY *list, *head;
2639  WIN_PROCESS_MODULE *pLsassMod = NULL;
2640 
2641  // LSASS will only exist in either 64 or 32 bit form, depending on the OS.
2642  if (Lsass->Subsystemx64)
2643  {
2644  head = &Lsass->Subsystemx64->ProcessModules;
2645  }
2646  else
2647  {
2648  head = &Lsass->Subsystemx86->ProcessModules;
2649  }
2650 
2651  // We assume one cannot read more than a single module at one time. If someone does that, we'll block it.
2652  list = head->Flink;
2653  while (list != head)
2654  {
2655  pLsassMod = CONTAINING_RECORD(list, WIN_PROCESS_MODULE, Link);
2656 
2657  list = list->Flink;
2658 
2659  // Ignore the MZ/PE headers.
2660  if (((SourceAddress >= pLsassMod->VirtualBase + PAGE_SIZE) &&
2661  (SourceAddress < pLsassMod->VirtualBase + pLsassMod->Size)) ||
2662  ((srcEnd >= pLsassMod->VirtualBase + PAGE_SIZE) &&
2663  (srcEnd < pLsassMod->VirtualBase + pLsassMod->Size)))
2664  {
2665  break;
2666  }
2667 
2668  pLsassMod = NULL;
2669  }
2670 
2671  *VictimModule = pLsassMod;
2672 
2673  if (NULL != pLsassMod)
2674  {
2675  // If this is ntdll or the main module, bail out.
2676  if (pLsassMod->Path->NameHash == NAMEHASH_NTDLL || pLsassMod->IsMainModule)
2677  {
2678  return TRUE;
2679  }
2680  }
2681  else
2682  {
2683  // Allow reads from everything that is not a module - a lot of legitimate reads are done from various heap
2684  // locations from lsass, and that can cause performance problems; blocking reads from modules is enough
2685  // for blocking credential stealing.
2686  return TRUE;
2687  }
2688 
2689  return FALSE;
2690 }
2691 
2692 
2693 INTSTATUS
2695  _In_ void *Detour
2696  )
2708 {
2709  INTSTATUS status;
2710  INTRO_ACTION action;
2711  INTRO_ACTION_REASON reason;
2712  PIG_ARCH_REGS pRegs;
2713  QWORD srcCr3, dstCr3;
2714  QWORD srcEproc, dstEproc;
2715  QWORD srcAddress, dstAddress;
2716  DWORD size;
2717  QWORD args[5];
2718  WIN_PROCESS_OBJECT *pSrcProc, *pDstProc;
2719  BOOLEAN isLsass, isRead;
2720  EXCEPTION_UM_ORIGINATOR originator;
2721  EXCEPTION_VICTIM_ZONE victim;
2722  PWIN_PROCESS_MODULE pLsassMod;
2723 
2724  action = introGuestAllowed;
2725  reason = introReasonUnknown;
2726  pSrcProc = pDstProc = NULL;
2727  isLsass = FALSE;
2728  pLsassMod = NULL;
2729 
2730  pRegs = &gVcpu->Regs;
2731 
2733 
2735  {
2736  status = INT_STATUS_SUCCESS;
2737  goto cleanup_and_exit;
2738  }
2739 
2740  status = IntDetGetArguments(Detour, 5, args);
2741  if (!INT_SUCCESS(status))
2742  {
2743  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
2744  goto cleanup_and_exit;
2745  }
2746 
2747  srcEproc = args[0];
2748  srcAddress = args[1];
2749  dstEproc = args[2];
2750  dstAddress = args[3];
2751  size = (DWORD)args[4];
2752 
2753  // If a write comes from the kernel, there's nothing we can do. We will simply allow it
2754  if (IS_KERNEL_POINTER_WIN(gGuest.Guest64, srcAddress))
2755  {
2756  goto cleanup_and_exit;
2757  }
2758 
2759  pDstProc = IntWinProcFindObjectByEprocess(dstEproc);
2760  if (NULL == pDstProc)
2761  {
2762  // If the process isn't found, than it has been terminated. We can safely leave.
2763  WARNING("[WARNING] IntWinProcFindObjectByEprocess failed for process 0x%016llx, "
2764  "current CR3 0x%016llx: 0x%08x\n",
2765  dstEproc, pRegs->Cr3, status);
2766 
2767  goto cleanup_and_exit;
2768  }
2769 
2770  pSrcProc = IntWinProcFindObjectByEprocess(srcEproc);
2771  if (NULL == pSrcProc)
2772  {
2773  goto cleanup_and_exit;
2774  }
2775 
2776  dstCr3 = pDstProc->Cr3;
2777 
2778  srcCr3 = pSrcProc->Cr3;
2779 
2780  // If source CR3 is the same as the destination CR3, then we have a ReadProcessMemory inside our own VA space,
2781  // which can be safely allowed.
2782  if (srcCr3 == dstCr3)
2783  {
2784  status = INT_STATUS_SUCCESS;
2785  goto cleanup_and_exit;
2786  }
2787 
2788  if (dstCr3 == pRegs->Cr3)
2789  {
2790  // We have a copy from p1 inside p2, and we are inside the context of p2 -> this is a read: p2 is
2791  // reading from p1.
2792  isRead = TRUE;
2793  }
2794  else
2795  {
2796  isRead = FALSE;
2797  }
2798 
2800 
2802  if (isRead && pDstProc->IsAgent)
2803  {
2804  action = introGuestAllowed;
2805  goto _stats_exit;
2806  }
2807 
2808  // Handle malicious process reads: check for processes attempting to read lsass.exe memory. We will ignore all
2809  // the other reads, as we're not interested in them.
2810  if (pSrcProc->Lsass && isRead)
2811  {
2812  isLsass = TRUE;
2813 
2814  if (IntWinProcHandleReadFromLsass(srcAddress, size, pSrcProc, &pLsassMod))
2815  {
2816  action = introGuestAllowed;
2817  goto _stats_exit;
2818  }
2819  }
2820  else
2821  {
2822  // We allow other process reads for now
2823  if (isRead)
2824  {
2825  status = INT_STATUS_SUCCESS;
2826  goto _stats_exit;
2827  }
2828 
2829  if (!pDstProc->Protected || !pDstProc->ProtWriteMem)
2830  {
2831  status = INT_STATUS_SUCCESS;
2832  goto _stats_exit;
2833  }
2834 
2835  // Mark the start of process initialization
2836  if (!pDstProc->StartInitializing && !pDstProc->Initialized)
2837  {
2838  if (0 == strcasecmp(pSrcProc->Name, "csrss.exe"))
2839  {
2840  pDstProc->StartInitializing = TRUE;
2841  }
2842  else
2843  {
2844  goto check_injection;
2845  }
2846  }
2847 
2848  // Allow every injection until the process starts to initialize (some come from kernel-mode,
2849  // and we have no way to except that)
2850  if (!pDstProc->StartInitializing && !pDstProc->Initialized)
2851  {
2852  status = INT_STATUS_SUCCESS;
2853  goto _stats_exit;
2854  }
2855  }
2856 
2857 check_injection:
2859 
2860  // If this is a read from lsass.exe, switch the source and the destination from now on, as we want to go through
2861  // the exceptions mechanism with the source of the attack being the destination process and the victim being
2862  // the source process (lsass.exe).
2863  if (isLsass)
2864  {
2865  void *auxproc;
2866  QWORD auxaddr;
2867 
2868  auxproc = pSrcProc;
2869  pSrcProc = pDstProc;
2870  pDstProc = auxproc;
2871 
2872  auxaddr = srcAddress;
2873  srcAddress = dstAddress;
2874  dstAddress = auxaddr;
2875  }
2876 
2877  memzero(&originator, sizeof(originator));
2878  memzero(&victim, sizeof(victim));
2879 
2881 
2882  status = IntExceptUserGetOriginator(pSrcProc, FALSE, srcAddress, NULL, &originator);
2883  if (!INT_SUCCESS(status))
2884  {
2885  reason = introReasonInternalError;
2886  action = introGuestNotAllowed;
2887 
2888  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
2889  goto _stop_count_and_notify;
2890  }
2891 
2892  status = IntExceptGetVictimProcess(pDstProc, dstAddress, size, isRead ? ZONE_READ : ZONE_WRITE, &victim);
2893  if (!INT_SUCCESS(status))
2894  {
2895  reason = introReasonInternalError;
2896  action = introGuestNotAllowed;
2897 
2898  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
2899  goto _stop_count_and_notify;
2900  }
2901 
2902  // The IntExceptGetVictimProcess either returns a valid VAD for the whole range, or NULL.
2903  // If there is no VAD (guest space was already scanned), we will still pass through exceptions and let the
2904  // guest handle the case (if allowed).
2905  if (NULL == victim.Object.Vad && pDstProc->MonitorVad)
2906  {
2907  WARNING("[WARNING] Injection (read: %d) from %s (%u) into %s "
2908  "(%u) for VA %llx with ""size %d (which has no VAD)!\n",
2909  isRead, pSrcProc->Name, pSrcProc->Pid, pDstProc->Name,
2910  pDstProc->Pid, dstAddress, size);
2911 
2912  for (QWORD currentDst = dstAddress; currentDst < dstAddress + size;)
2913  {
2914  VAD *pNewVad = IntWinVadFindAndUpdateIfNecessary(pDstProc, currentDst, 1);
2915  if (pNewVad)
2916  {
2917  WARNING("[WARNING] Vad-> [%llx -> %llx] (path: %s, stack: %d)\n",
2918  pNewVad->StartPage, pNewVad->EndPage,
2919  pNewVad->Path ? utf16_for_log(pNewVad->Path->Path) : "(none)", pNewVad->IsStack);
2920  currentDst += pNewVad->PageCount * PAGE_SIZE;
2921  }
2922  else
2923  {
2924  currentDst += PAGE_SIZE;
2925  }
2926  }
2927  }
2928 
2929  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventInjectionViolation);
2930 
2931 _stop_count_and_notify:
2933 
2934  STATS_ENTER(isRead ? statsCopyMemoryProtectedRead : statsCopyMemoryProtectedWrite);
2935 
2936  // Print lsass read details only if not allowed
2937  if (introGuestNotAllowed == action && isLsass && isRead && (NULL != pLsassMod))
2938  {
2939  LOG("[WINPROCESS] Suspicious read from lsass.exe: %s from process %s at address %llx:%d\n",
2940  utf16_for_log(pLsassMod->Path->Name), pSrcProc->Name, srcAddress, size);
2941  }
2942 
2943  if (IntPolicyProcTakeAction(PROC_OPT_PROT_WRITE_MEM, pDstProc, &action, &reason))
2944  {
2946 
2947  memzero(pInjEvent, sizeof(*pInjEvent));
2948 
2949  LOG("[ALERT] [INJECTION DETECTED] Injection took place from EPROCESS 0x%016llx with CR3 0x%016llx in " \
2950  "EPROCESS 0x%016llx with CR3 0x%016llx. CR3: 0x%016llx, IsRead: %s\n",
2951  srcEproc, srcCr3, dstEproc, dstCr3, pRegs->Cr3, isRead ? "yes" : "no");
2952 
2953  pInjEvent->Header.Action = action;
2954  pInjEvent->Header.Reason = reason;
2955 
2956  if (isRead && isLsass)
2957  {
2958  pInjEvent->Header.MitreID = idCredDump;
2959  }
2960  else
2961  {
2962  pInjEvent->Header.MitreID = idProcInject;
2963  }
2964 
2966  IntAlertFillWinProcess(pSrcProc, &pInjEvent->Originator.Process);
2967  IntAlertFillWinProcess(pDstProc, &pInjEvent->Victim.Process);
2969 
2970  if (victim.Object.Library.Module)
2971  {
2973  }
2974 
2975  if (victim.Object.Library.Export != NULL)
2976  {
2977  WIN_PROCESS_MODULE *pModule = victim.Object.Library.Module;
2978  WINUM_CACHE_EXPORT *pExport = victim.Object.Library.Export;
2979 
2980  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
2981  {
2982  strlcpy(pInjEvent->Export.Name[export], pExport->Names[export],
2983  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
2984 
2985  pInjEvent->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
2986  }
2987 
2988  strlcpy(pInjEvent->FunctionName,
2989  pExport->Names[0],
2990  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
2991 
2992  pInjEvent->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
2993 
2994  if (pModule != NULL)
2995  {
2996  pInjEvent->Export.Delta =
2997  (DWORD)(dstAddress - pModule->VirtualBase - victim.Object.Library.Export->Rva);
2998 
2999  pInjEvent->Delta =
3000  (DWORD)(dstAddress - pModule->VirtualBase - victim.Object.Library.Export->Rva);
3001  }
3002  }
3003 
3004  pInjEvent->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_WRITE_MEM, pDstProc, reason, 0);
3005 
3006  // If the the destination process is a system process, a flag will be set
3007  if (pDstProc->SystemProcess)
3008  {
3009  pInjEvent->Header.Flags |= ALERT_FLAG_SYSPROC;
3010  }
3011 
3012  // Injection violations are always from RING 3.
3013  pInjEvent->Header.Flags |= ALERT_FLAG_NOT_RING0;
3014 
3015  // Set the internal information
3016  pInjEvent->DestinationVirtualAddress = dstAddress;
3017  pInjEvent->SourceVirtualAddress = srcAddress;
3018  pInjEvent->CopySize = size;
3020 
3021  // read maximum 512 bytes form the source address into the alert. If this is a read, we won't include a buffer,
3022  // since we may end up sending sensitive info (see Mimikatz reading credentials from lsass memory).
3023  if (!isRead)
3024  {
3025  status = IntVirtMemRead(srcAddress,
3026  MIN(size, sizeof(pInjEvent->RawDump)),
3027  srcCr3,
3028  &pInjEvent->RawDump,
3029  NULL);
3030  if (INT_SUCCESS(status))
3031  {
3032  pInjEvent->DumpValid = TRUE;
3033  }
3034  }
3035 
3036  IntAlertFillVersionInfo(&pInjEvent->Header);
3037 
3038  status = IntNotifyIntroEvent(introEventInjectionViolation, pInjEvent, sizeof(*pInjEvent));
3039  if (!INT_SUCCESS(status))
3040  {
3041  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
3042  }
3043 
3044  status = INT_STATUS_SUCCESS;
3045  }
3046 
3047 _stats_exit:
3048  STATS_EXIT(isRead ? statsCopyMemoryRead : statsCopyMemoryWrite);
3049 
3050 cleanup_and_exit:
3052 
3053  if (pDstProc != NULL)
3054  {
3056  }
3057 
3058  status = IntDetSetReturnValue(Detour,
3059  pRegs,
3061  if (!INT_SUCCESS(status))
3062  {
3063  ERROR("[ERROR] IntDetSetReturnValue failed: 0x%08x\n", status);
3064  }
3065 
3066  return status;
3067 }
3068 
3069 
3070 INTSTATUS
3072  _In_ WIN_PROCESS_OBJECT *Process
3073  )
3082 {
3083  INTSTATUS status;
3084 
3085  if (NULL == Process)
3086  {
3088  }
3089 
3090  if (Process->Protected)
3091  {
3093  }
3094 
3095  Process->Context = 0;
3096 
3097  // Remove the protection.
3098  status = IntWinProcChangeProtectionFlags(Process, Process->ProtectionMask, 0);
3099  if (!INT_SUCCESS(status))
3100  {
3101  ERROR("[ERROR] IntWinProcChangeProtectionFlags failed: 0x%08x\n", status);
3102  }
3103 
3104  IntExceptInvCbCacheByCr3(Process->Cr3);
3105 
3106  return INT_STATUS_SUCCESS;
3107 }
3108 
3109 
3110 INTSTATUS
3112  _In_ WIN_PROCESS_OBJECT *Process
3113  )
3123 {
3124  INTSTATUS status;
3125 
3126  if (NULL == Process)
3127  {
3129  }
3130 
3131  if (!Process->Protected)
3132  {
3134  }
3135 
3136  // It is ok to do this here because if this function fails, it calls IntWinProcUnprotect which will decrement
3137  // the counter
3139 
3140  // Make sure enough memory is available.
3142  {
3143  WARNING("[WARNING] Not enough heap is available. Will NOT protect the process '%s'.\n", Process->Name);
3145  goto cleanup_and_exit;
3146  }
3147 
3148  TRACE("[PROCESS] Protecting process %s with CR3 0x%016llx, EPROC 0x%016llx, WOW64 %d, PEB at 0x%016llx," \
3149  "PEB32 at 0x%016llx, Parent 0x%016llx, ProtMask: 0x%08x, the process is %s.\n",
3150  Process->Name,
3151  Process->Cr3,
3152  Process->EprocessAddress,
3153  Process->Wow64Process,
3154  Process->Peb64Address,
3155  Process->Peb32Address,
3156  Process->ParentEprocess,
3157  Process->ProtectionMask,
3158  Process->StaticDetected ? "already created" : "being created");
3159 
3160  // Activate the protection.
3161  status = IntWinProcChangeProtectionFlags(Process, 0, Process->ProtectionMask);
3162  if (!INT_SUCCESS(status))
3163  {
3164  ERROR("[ERROR] IntWinProcChangeProtectionFlags failed: 0x%08x\n", status);
3165  goto cleanup_and_exit;
3166  }
3167 
3168  status = INT_STATUS_SUCCESS;
3169 
3170 cleanup_and_exit:
3171  if (!INT_SUCCESS(status))
3172  {
3173  INTSTATUS status2;
3174 
3175  status2 = IntWinProcUnprotect(Process);
3176  if (!INT_SUCCESS(status2))
3177  {
3178  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status2);
3179  }
3180 
3181  memset(&gErrorContext, 0, sizeof(gErrorContext));
3184 
3187  &gErrorContext);
3188  }
3189 
3190  return status;
3191 }
3192 
3193 
3196  void
3197  )
3206 {
3207  INTSTATUS status;
3208  WIN_PROCESS_OBJECT *pProc;
3209  VA_TRANSLATION tr;
3210  QWORD cr3;
3211  INTRO_ACTION action;
3212  INTRO_ACTION_REASON reason;
3213 
3215  {
3217  }
3218 
3219  if (!gGuest.GuestInitialized)
3220  {
3222  }
3223 
3225  {
3227  }
3228 
3229  cr3 = 0;
3230  action = introGuestNotAllowed;
3231  reason = introReasonUnknown;
3232 
3233  // Make sure we have at least one process.
3234  if (IsListEmpty(&gWinProcesses))
3235  {
3237  }
3238 
3239  // Get the System process, which is always the first one.
3240  pProc = (PWIN_PROCESS_OBJECT)gWinProcesses.Flink;
3241  if (4 != pProc->Pid)
3242  {
3243  ERROR("[ERROR] First process is not System: PID = %d\n", pProc->Pid);
3244  return INT_STATUS_NOT_FOUND;
3245  }
3246 
3247  // Translate the system EPROCESS to a physical address.
3248  status = IntTranslateVirtualAddressEx(pProc->EprocessAddress + WIN_KM_FIELD(Process, Cr3),
3250  TRFLG_PG_MODE,
3251  &tr);
3252  if (!INT_SUCCESS(status))
3253  {
3254  ERROR("[ERROR] IntTranslateVirtualAddressEx failed: 0x%08x\n", status);
3255  return status;
3256  }
3257 
3258  if (0 == (tr.Flags & PT_P))
3259  {
3261  }
3262 
3263  // Fetch the active PDBR for the System process.
3265  if (!INT_SUCCESS(status))
3266  {
3267  ERROR("[ERROR] IntGpaCacheFetchAndAdd failed: 0x%08x\n", status);
3268  return status;
3269  }
3270 
3271  if (!gGuest.Guest64)
3272  {
3273  // Note that CR3 is 32 bit wide in legacy paging mode and PAE mode.
3274  cr3 &= 0xFFFFFFFF;
3275  }
3276 
3277  if (cr3 != pProc->Cr3)
3278  {
3280 
3281  IntPauseVcpus();
3282 
3283  // Restore the original, if no BETA
3285  {
3286  action = introGuestNotAllowed;
3287  reason = introReasonNoException;
3288 
3289  status = IntVirtMemSafeWrite(0,
3290  pProc->EprocessAddress + WIN_KM_FIELD(Process, Cr3),
3291  gGuest.Guest64 ? sizeof(QWORD) : sizeof(DWORD),
3292  &pProc->Cr3,
3293  IG_CS_RING_0);
3294  if (!INT_SUCCESS(status))
3295  {
3296  ERROR("[ERROR] IntVirtMemSafeWrite failed: 0x%x\n", status);
3297  }
3298  }
3299  else
3300  {
3301  // The action will be BETA detected, it will be allowed by default, so there is no use of
3302  // specifying it in the reason while the BETA flag is specified in the alert.
3303  action = introGuestAllowed;
3304  reason = introReasonAllowed;
3305  }
3306 
3307  pTrViol = &gAlert.Translation;
3308  memzero(pTrViol, sizeof(*pTrViol));
3309 
3310  pTrViol->Header.Flags = 0;
3311 
3312  pTrViol->Header.Flags |= ALERT_FLAG_ASYNC;
3314  {
3315  pTrViol->Header.Flags |= ALERT_FLAG_BETA;
3316  }
3317 
3318  pTrViol->Header.CpuContext.Valid = FALSE;
3319  pTrViol->Header.Action = action;
3320  pTrViol->Header.Reason = reason;
3321  pTrViol->Header.MitreID = idRootkit;
3322 
3324 
3325  // If VirtualAddress is -1, this means that we're dealing with an invalid CR3 modification. VirtualAddress
3326  // must be != -1 for all other types of translation violations.
3327  pTrViol->Victim.VirtualAddress = 0xFFFFFFFFFFFFFFFF;
3328  pTrViol->WriteInfo.OldValue[0] = pProc->Cr3;
3329  pTrViol->WriteInfo.NewValue[0] = cr3;
3330  pTrViol->WriteInfo.Size = sizeof(QWORD);
3332 
3333  IntAlertFillVersionInfo(&pTrViol->Header);
3334 
3335  status = IntNotifyIntroEvent(introEventTranslationViolation, pTrViol, sizeof(*pTrViol));
3336  if (!INT_SUCCESS(status))
3337  {
3338  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
3339  }
3340 
3341  IntResumeVcpus();
3342  }
3343 
3344  return INT_STATUS_SUCCESS;
3345 }
3346 
3347 
3348 static BOOLEAN
3350  _In_ const WCHAR *Path
3351  )
3358 {
3359  SIZE_T i = 0;
3360 
3361  while (Path[i] != 0)
3362  {
3363  if ((Path[i] == u'\\') || (Path[i] == u'/'))
3364  {
3365  return TRUE;
3366  }
3367 
3368  i++;
3369  }
3370 
3371  return FALSE;
3372 }
3373 
3374 
3375 static BOOLEAN
3377  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
3378  _In_ const WCHAR *FullPath,
3379  _In_ DWORD ProtectionMask,
3380  _In_ QWORD Context
3381  )
3396 {
3397  LIST_ENTRY *list, *pList;
3398 
3399  list = gWinProtectedProcesses.Flink;
3400  while (list != &gWinProtectedProcesses)
3401  {
3403 
3404  list = list->Flink;
3405 
3406  if ((0 == strcasecmp(pProc->ImageBaseNamePattern, BaseName)) &&
3407  (0 == wstrcasecmp(pProc->FullPathPattern, FullPath)) &&
3408  (pProc->Protection.Current == ProtectionMask))
3409  {
3410  // Change the context and bail out early on if the protection mask is the same
3411  if (pProc->Context != Context)
3412  {
3413  pProc->Context = Context;
3414 
3415  pList = gWinProcesses.Flink;
3416  while (pList != &gWinProcesses)
3417  {
3418  WIN_PROCESS_OBJECT *pProcObject = CONTAINING_RECORD(pList, WIN_PROCESS_OBJECT, Link);
3419 
3420  pList = pList->Flink;
3421 
3422  if (!strcasecmp(pProcObject->Name, BaseName))
3423  {
3424  pProcObject->Context = Context;
3425  }
3426  }
3427  }
3428 
3429  return TRUE;
3430  }
3431  }
3432 
3433  return FALSE;
3434 }
3435 
3436 
3437 static INTSTATUS
3439  _In_ CHAR BaseName[IMAGE_BASE_NAME_LEN],
3440  _In_ const WCHAR *FullPath
3441  )
3453 {
3454  LIST_ENTRY *list;
3455 
3456  list = gWinProtectedProcesses.Flink;
3457  while (list != &gWinProtectedProcesses)
3458  {
3460 
3461  list = list->Flink;
3462 
3463  if ((0 == strcasecmp(pProc->ImageBaseNamePattern, BaseName)) &&
3464  (0 == wstrcasecmp(pProc->FullPathPattern, FullPath)))
3465  {
3466  memset(pProc->ImageBaseNamePattern, 0, IMAGE_BASE_NAME_LEN);
3467 
3469 
3470  RemoveEntryList(&pProc->Link);
3471 
3473  }
3474  }
3475 
3476  return INT_STATUS_SUCCESS;
3477 }
3478 
3479 
3480 void
3482  _In_ const void *Name,
3483  _In_ const CAMI_STRING_ENCODING Encoding,
3484  _In_ const CAMI_PROT_OPTIONS *Options
3485  )
3493 {
3494  LIST_ENTRY *list = gWinProtectedProcesses.Flink;
3495  while (list != &gWinProtectedProcesses)
3496  {
3498  BOOLEAN match = FALSE;
3499 
3500  list = list->Flink;
3501 
3502  switch (Encoding)
3503  {
3505  if (IntMatchPatternUtf8(Name, pProcess->ImageBaseNamePattern, 0))
3506  {
3507  match = TRUE;
3508  }
3509  break;
3511  if (IntMatchPatternUtf16(Name, pProcess->FullNamePattern, 0))
3512  {
3513  match = TRUE;
3514  }
3515  break;
3516  default:
3517  WARNING("[WARNING] Unsupported string encoding: %d\n", Encoding);
3518  }
3519 
3520  if (match)
3521  {
3522  pProcess->Protection.Current = pProcess->Protection.Original & ~(Options->ForceOff);
3523  pProcess->Protection.Beta = Options->ForceBeta;
3524  pProcess->Protection.Feedback = Options->ForceFeedback;
3525 
3526  TRACE("[CAMI] Protected process info updated '%s'. Original : 0x%x, "
3527  "Current : 0x%x, Beta : 0x%llx, Feedback : 0x%llx\n",
3528  pProcess->ImageBaseNamePattern, pProcess->Protection.Original,
3529  pProcess->Protection.Current, pProcess->Protection.Beta, pProcess->Protection.Feedback);
3530  }
3531  }
3532 }
3533 
3534 
3535 INTSTATUS
3537  _In_ const WCHAR *Path,
3538  _In_ DWORD ProtectionMask,
3539  _In_ QWORD Context
3540  )
3550 {
3551  INTSTATUS status;
3553  SIZE_T fplen;
3554  CHAR baseName[IMAGE_BASE_NAME_LEN] = { 0 };
3555  const WCHAR *fullName;
3556 
3557  if (NULL == Path)
3558  {
3560  }
3561 
3562  pProc = NULL;
3563 
3564  // Remove the drive name from the path.
3565  if ((Path[0] | 0x20) >= 'a' && (Path[0] | 0x20) <= 'z' && Path[1] == ':')
3566  {
3567  Path += 2;
3568  }
3569 
3570  fplen = wstrlen(Path);
3571  if ((0 == fplen) || (fplen >= 0x10000))
3572  {
3574  }
3575 
3576  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
3577 
3578  strlower_utf8(baseName, sizeof(baseName));
3579 
3580  // Check if an identical policy already exists. If so, bail out now.
3581  if (IntWinProcExistsProtectedProcess(baseName, Path, ProtectionMask, Context))
3582  {
3583  TRACE("[INFO] A policy for process '%s', base name '%s', flags 0x%08x already exits.\n",
3584  utf16_for_log(Path), baseName, ProtectionMask);
3586  }
3587 
3588  // First of all, remove any instance of this process from the protected list.
3590 
3591  // Now add a new one.
3592  pProc = HpAllocWithTag(sizeof(*pProc), IC_TAG_PPIF);
3593  if (NULL == pProc)
3594  {
3596  }
3597 
3598  pProc->FullPathPattern = HpAllocWithTag(fplen * sizeof(WCHAR) + 2, IC_TAG_PATH);
3599  if (NULL == pProc->FullPathPattern)
3600  {
3603  }
3604 
3605  pProc->Protection.Original = ProtectionMask;
3606  pProc->Protection.Current = ProtectionMask;
3607  pProc->Protection.Beta = 0;
3608  pProc->Protection.Feedback = 0;
3609 
3610  memcpy(pProc->ImageBaseNamePattern, baseName, IMAGE_BASE_NAME_LEN);
3611 
3612  memcpy(pProc->FullPathPattern, Path, fplen * sizeof(WCHAR));
3613  strlower_utf16(pProc->FullPathPattern, fplen);
3614 
3615  pProc->FullNamePattern = pProc->FullPathPattern + (fullName - Path);
3616 
3617  if (!IntWinProcIsFullPath(Path))
3618  {
3619  pProc->Flags |= PROT_PROC_FLAG_NO_PATH;
3620  }
3621  else
3622  {
3623  pProc->Flags = 0;
3624  }
3625 
3626  pProc->Context = Context;
3627 
3629 
3630  InsertTailList(&gWinProtectedProcesses, &pProc->Link);
3631 
3632  // UM introspection is not active, just leave.
3634  {
3635  return INT_STATUS_SUCCESS;
3636  }
3637 
3638  status = IntWinProcUpdateProtection();
3639  if (!INT_SUCCESS(status))
3640  {
3641  ERROR("[ERROR] IntWinProcUpdateProtection failed: 0x%08x\n", status);
3642  return status;
3643  }
3644 
3645  return status;
3646 }
3647 
3648 
3649 INTSTATUS
3651  _In_ const WCHAR *Path
3652  )
3660 {
3661  INTSTATUS status = INT_STATUS_SUCCESS;
3662  CHAR baseName[IMAGE_BASE_NAME_LEN] = {0};
3663  const WCHAR *fullName;
3664 
3665  if (NULL == Path)
3666  {
3668  }
3669 
3670  // Remove the drive name from the path.
3671  if ((Path[0] | 0x20) >= 'a' && (Path[0] | 0x20) <= 'z' && Path[1] == ':')
3672  {
3673  Path += 2;
3674  }
3675 
3676  if (0 == wstrlen(Path))
3677  {
3679  }
3680 
3681  IntWinProcGetImageBaseNameFromPath(Path, baseName, &fullName);
3682 
3683  status = IntWinProcRemoveProtectedProcessInternal(baseName, Path);
3684  if (!INT_SUCCESS(status))
3685  {
3686  ERROR("[ERROR] IntWinProcRemoveProtectedProcessInternal failed: 0x%08x\n", status);
3687  goto cleanup_and_exit;
3688  }
3689 
3690  status = IntWinProcUpdateProtection();
3691  if (!INT_SUCCESS(status))
3692  {
3693  ERROR("[ERROR] IntWinProcUpdateProtection failed: 0x%08x\n", status);
3694  goto cleanup_and_exit;
3695  }
3696 
3697 cleanup_and_exit:
3698 
3699  return status;
3700 }
3701 
3702 
3703 INTSTATUS
3705  void
3706  )
3712 {
3713  LIST_ENTRY *list;
3714 
3715  list = gWinProtectedProcesses.Flink;
3716  while (list != &gWinProtectedProcesses)
3717  {
3719 
3720  list = list->Flink;
3721 
3722  memset(pProc->ImageBaseNamePattern, 0, IMAGE_BASE_NAME_LEN);
3723 
3725 
3726  RemoveEntryList(&pProc->Link);
3727 
3729  }
3730 
3731  return INT_STATUS_SUCCESS;
3732 }
3733 
3734 
3735 void
3737  void
3738  )
3742 {
3743  DWORD i = 0;
3744 
3745  for (LIST_ENTRY *list = gWinProtectedProcesses.Flink;
3746  list != &gWinProtectedProcesses;
3747  list = list->Flink)
3748  {
3750 
3751  LOG("# %04d %s, %08x, '%s':'%s'\n",
3752  i,
3753  pProc->ImageBaseNamePattern,
3754  pProc->Protection.Original,
3756  utf16_for_log(pProc->FullNamePattern));
3757 
3758  i++;
3759  }
3760 }
3761 
3762 
3763 void
3765  void
3766  )
3771 {
3772  LIST_ENTRY *list;
3773  INTSTATUS status;
3774 
3775  list = gWinProtectedProcesses.Flink;
3776  while (list != &gWinProtectedProcesses)
3777  {
3779 
3780  list = list->Flink;
3781 
3782  if (NULL != pTarget->FullPathPattern)
3783  {
3785  }
3786 
3787  RemoveEntryList(&pTarget->Link);
3788 
3789  HpFreeAndNullWithTag(&pTarget, IC_TAG_PPIF);
3790  }
3791 
3792  list = gWinProcesses.Flink;
3793  while (list != &gWinProcesses)
3794  {
3796 
3797  list = list->Flink;
3798 
3799  pProc->Terminating = TRUE;
3800 
3801  if (!gGuest.ShutDown && pProc->IsAgent)
3802  {
3803  IntWinProcMarkAgent(pProc, TRUE);
3804  }
3805 
3806  // Remove the process from the list & RB tree.
3807  RemoveEntryList(&pProc->Link);
3808 
3809  RbDeleteNode(&gWinProcTreeCr3, &pProc->NodeCr3);
3810 
3811  RbDeleteNode(&gWinProcTreeUserCr3, &pProc->NodeUserCr3);
3812 
3813  RbDeleteNode(&gWinProcTreeEprocess, &pProc->NodeEproc);
3814 
3815  if (pProc->Protected)
3816  {
3817  status = IntWinProcUnprotect(pProc);
3818  if (!INT_SUCCESS(status))
3819  {
3820  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
3821  }
3822  }
3823 
3824  status = IntWinProcRemoveProcess(pProc);
3825  if (!INT_SUCCESS(status))
3826  {
3827  ERROR("[ERROR] IntWinProcRemoveProcess failed: 0x%08x\n", status);
3828  }
3829  }
3830 }
3831 
3832 
3833 INTSTATUS
3835  _In_ DWORD Pid,
3836  _Outptr_ WIN_PROCESS_OBJECT **Process
3837  )
3848 {
3849  LIST_ENTRY *list = NULL;
3850 
3851  if (NULL == Process)
3852  {
3854  }
3855 
3856  list = gWinProcesses.Flink;
3857  while (list != &gWinProcesses)
3858  {
3860 
3861  if (pProc->Pid == Pid)
3862  {
3863  *Process = pProc;
3864 
3865  return INT_STATUS_SUCCESS;
3866  }
3867 
3868  list = list->Flink;
3869  }
3870 
3871  return INT_STATUS_NOT_FOUND;
3872 }
3873 
3874 
3875 
3876 INTSTATUS
3878  _In_ WIN_PROCESS_OBJECT *Process,
3879  _In_ DWORD OldMask,
3880  _In_ DWORD NewMask
3881  )
3893 {
3894  INTSTATUS status;
3895  BOOLEAN vadWasMonitored;
3896 
3897  if (NULL == Process)
3898  {
3900  }
3901 
3902  if (OldMask == NewMask)
3903  {
3905  }
3906 
3907  vadWasMonitored = !!Process->MonitorVad;
3908 
3909  Process->ProtectionMask = NewMask;
3910  Process->Protected = NewMask != 0;
3911 
3912  if (!Process->Protected)
3913  {
3914  // Invalidate all the entries inside the ICACHE associated to this process,
3915  // since the CR3 will not be hooked anymore.
3916  status = IntIcFlushVaSpace(gGuest.InstructionCache, Process->Cr3);
3917  if (!INT_SUCCESS(status))
3918  {
3919  ERROR("[ERROR] IntIcFlushVaSpace failed: 0x%08x\n", status);
3920  }
3921  }
3922 
3923  // Set the BetaDetections policy
3924  if (Process->SystemProcess)
3925  {
3926  Process->BetaDetections = gGuest.SysprocBetaDetections;
3927  }
3928  else
3929  {
3930  Process->BetaDetections = !!(Process->ProtectionMask & PROC_OPT_BETA);
3931  }
3932 
3933  if (NewMask == 0)
3934  {
3935  Process->MonitorModules = FALSE;
3936  Process->MonitorVad = FALSE;
3937  }
3938  else
3939  {
3940  Process->MonitorModules = (!!(gGuest.CoreOptions.Current & INTRO_OPT_ENABLE_FULL_PATH) &&
3941  !Process->SystemProcess) ||
3942  (Process->ProtCoreModules || Process->ProtWsockModules || Process->ProtUnpack ||
3943  Process->Lsass || Process->ProtDoubleAgent);
3944 
3945  // Global per process flag that indicates if VAD is interesting for this process or not.
3946  Process->MonitorVad = (Process->MonitorModules || Process->ProtExploits);
3947  }
3948 
3949  // We must patch the in-guest protection indicator (used to be the first two characters in ImageName, now we use
3950  // some unused spare values) BEFORE actually trying to enable/disable protection. Otherwise, we may end up with a
3951  // process which has an altered spare value, which does not reflect the actual protection policy.
3952  status = IntWinProcPatchSpareValue(Process);
3953  if (!INT_SUCCESS(status))
3954  {
3955  ERROR("[ERROR] IntWinProcPatchSpareValue failed: 0x%08x\n", status);
3956  return status;
3957  }
3958 
3959  if ((OldMask & PROC_OPT_PROT_INJECTION) != (NewMask & PROC_OPT_PROT_INJECTION))
3960  {
3961  // we assume that if LateProtection and we must protect the injection, process is already initialized
3962  if ((NewMask & PROC_OPT_PROT_INJECTION) != 0 && Process->LateProtection)
3963  {
3964  Process->Initialized = TRUE;
3965  }
3966  }
3967 
3968  if ((OldMask & PROC_OPT_PROT_EXPLOIT) != (NewMask & PROC_OPT_PROT_EXPLOIT))
3969  {
3970  if (OldMask & PROC_OPT_PROT_EXPLOIT)
3971  {
3972  IntWinVadStopExploitMonitor(Process);
3973  }
3974  else
3975  {
3976  status = IntWinProcEnforceProcessDep(Process);
3977  if (!INT_SUCCESS(status))
3978  {
3979  ERROR("[ERROR] IntWinProcEnforceProcessDep failed: 0x%08x\n", status);
3980  return status;
3981  }
3982  }
3983  }
3984 
3987  {
3988  if (NULL != Process->Subsystemx86)
3989  {
3990  IntWinModulesChangeProtectionFlags(Process->Subsystemx86);
3991  }
3992 
3993  if (NULL != Process->Subsystemx64)
3994  {
3995  IntWinModulesChangeProtectionFlags(Process->Subsystemx64);
3996  }
3997  }
3998 
3999  if (vadWasMonitored && !Process->MonitorVad)
4000  {
4001  // We did VAD monitoring, but now we don't need to monitor the VAD - we can uninit the VAD tree.
4002  status = IntWinVadRemoveProcessTree(Process);
4003  if (!INT_SUCCESS(status))
4004  {
4005  ERROR("[ERROR] IntWinVadRemoveProcessTree failed: 0x%08x\n", status);
4006  return status;
4007  }
4008  }
4009  else if (!vadWasMonitored && Process->MonitorVad)
4010  {
4011  // VAD monitoring was off, but we need to turn it on, so read all the VADs from the guest space.
4012  status = IntWinVadImportProcessTree(Process);
4013  if (!INT_SUCCESS(status))
4014  {
4015  ERROR("[ERROR] IntWinVadImportProcessTree failed: 0x%08x\n", status);
4016  return status;
4017  }
4018  }
4019 
4020  // Remove or add hook on self map index
4021  if (Process->Protected && NULL == Process->SelfMapHook)
4022  {
4023  status = IntWinSelfMapProtectSelfMapIndex(Process);
4024  if (!INT_SUCCESS(status))
4025  {
4026  ERROR("[ERROR] IntWinProcProtectSelfMapIndex failed: 0x%08x\n", status);
4027  return status;
4028  }
4029  }
4030  else if (!Process->Protected && NULL != Process->SelfMapHook)
4031  {
4032  status = IntWinSelfMapUnprotectSelfMapIndex(Process);
4033  if (!INT_SUCCESS(status))
4034  {
4035  ERROR("[ERROR] IntWinProcUnprotectSelfMapIndex failed: 0x%08x\n", status);
4036  return status;
4037  }
4038  }
4039 
4040  return INT_STATUS_SUCCESS;
4041 }
WINUM_PATH * Path
Module path.
Definition: winummodule.h:62
DWORD CommandLineSize
Includes the NULL terminator.
Definition: winprocess.h:114
PCHAR CommandLine
The command line with which the process was created (can be NULL).
Definition: winprocess.h:112
static WIN_PROCESS_OBJECT * IntWinProcHandleCreateInternal(QWORD NewEprocess, QWORD ParentEprocess, QWORD DebugHandle, INTRO_ACTION *Action)
Handles process creation for Windows guests.
Definition: winprocess.c:2318
uint16_t * PWCHAR
Definition: intro_types.h:63
void * Module
The internal structure of a module.
Definition: exceptions.h:790
#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:3650
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
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
Credential Dumping.
Definition: intro_types.h:1032
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:300
#define __unlikely(x)
Definition: common.h:47
_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:571
#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:1369
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:818
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:1391
DWORD Size
The size of the access.
Definition: intro_types.h:896
DWORD Original
The original protection flags as received from GLUE_IFACE.AddRemoveProtectedProcessUtf16 or GLUE_IFAC...
Definition: winguest.h:37
INTRO_MODULE Module
The module which was written or read.
Definition: intro_types.h:1329
struct _EVENT_MEMCOPY_VIOLATION::@290 Victim
#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:2282
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:3376
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:1750
DWORD Index
The VCPU number.
Definition: guests.h:172
EVENT_EXCEPTION_EVENT Exception
Definition: alerts.h:28
LIST_ENTRY Link
Entry within gWinProcesses (Doubly Linked List).
Definition: winprocess.h:83
This is the structure as documented in winternl.h.
Definition: wddefs.h:680
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:1088
void IntWinDpiGatherDpiInfo(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Parent, QWORD DebugHandle)
Gathers all the necessary DPI (Deep Process Inspection) information that will later be used to decide...
Definition: windpi.c:1293
static 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:144
INTSTATUS IntWinProcPatchPspInsertProcess86(QWORD FunctionAddress, void *Handler, QWORD HandlerAddress)
This functions is responsible for patching the detour that handles the "PspInsertProcess".
Definition: winprocess.c:2277
#define INTRO_OPT_PROT_KM_SYSTEM_CR3
Enable System process PDBR protection.
Definition: intro_types.h:399
QWORD RealParentEprocess
The active EPROCESS at the moment of creation.
Definition: winprocess.h:90
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:207
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
QWORD Context
The context supplied in the protection policy.
Definition: winguest.h:74
Event structure for process creation/termination.
Definition: intro_types.h:1747
INTRO_PROCESS Process
The process that attempted the access.
Definition: intro_types.h:1318
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:895
CHAR FunctionName[ALERT_MAX_FUNCTION_NAME_LEN]
The name of the accessed function, if any.
Definition: intro_types.h:1377
#define WIN_STATUS_SUCCESS
Equivalent to NTSTATUS STATUS_SUCCESS.
Definition: winprocess.h:23
#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:2752
INTSTATUS IntWinTokenPrivsCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the privileges bitfields for the given process have been changed in a malicio...
Definition: wintoken.c:818
#define STATS_EXIT(id)
Definition: stats.h:148
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:1803
void * ParamsSwapHandle
The swap memory handle for Process->Peb->ProcessParameters (used to read the command line of the proc...
Definition: winprocess.h:245
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:557
INTSTATUS IntWinProcAddProtectedProcess(const WCHAR *Path, DWORD ProtectionMask, QWORD Context)
This function adds the provided process to the protected process list.
Definition: winprocess.c:3536
#define IC_TAG_POBJ
Process Object List Entry.
Definition: memtags.h:14
QWORD FeedbackMask
The protection mask in feedback mode.
Definition: winprocess.h:225
Exits caused by "MmCopyVirtualMemory".
Definition: winprocess.h:42
struct _UNICODE_STRING64 UNICODE_STRING64
The Windows UNICODE_STRING structure used for 64-bit guests.
User-mode exception.
Definition: exceptions.h:61
Described a detour handler.
Definition: detours.h:279
static INTSTATUS IntWinProcSendAgentEvent(WIN_PROCESS_OBJECT *Process, BOOLEAN Created)
Send a process creation/termination event that symbolizes an agent.
Definition: winprocess.c:394
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:2184
INTRO_PROCESS Process
The process that could not be protected.
Definition: intro_types.h:2260
DWORD Lsass
TRUE if this is the lsass process.
Definition: winprocess.h:135
INTSTATUS IntWinVadProcImportMainModuleVad(WIN_PROCESS_OBJECT *Process)
Imports the VAD that describes the main module of a process.
Definition: winvad.c:3799
BOOLEAN SysprocBetaDetections
Definition: guests.h:300
TIMER_FRIENDLY INTSTATUS IntWinProcValidateSystemCr3(void)
This function checks if the system CR3 value was modified and if GUEST_STATE::KernelBetaDetections is...
Definition: winprocess.c:3195
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:400
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:309
INTSTATUS IntWinProcReadCommandLine(WIN_PROCESS_OBJECT *Process)
Reads the command line of the given process using IntSwapMemReadData.
Definition: winprocess.c:893
#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:1449
Process Injection.
Definition: intro_types.h:1035
The process was not protected because there is not enough memory available.
Definition: intro_types.h:2281
static void IntWinProcHandleDuplicate(QWORD Cr3, QWORD Eprocess)
Ensures that a newly created process does not exist already.
Definition: winprocess.c:1269
static INTSTATUS IntWinProcEnforceProcessDep(WIN_PROCESS_OBJECT *Process)
Enables DEP (Data Execution Prevention) for a certain process.
Definition: winprocess.c:222
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
#define PROC_OPT_PROT_WSOCK_HOOKS
Blocks hooks being set on Wininet user-mode DLLs (Windows only).
Definition: intro_types.h:339
BOOLEAN ProtectionActivated
Definition: guests.h:293
Mitigation flags.
Definition: wddefs.h:1614
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:819
The action was not allowed because there was no reason to allow it.
Definition: intro_types.h:183
#define ARRAYSIZE(A)
Definition: introdefs.h:101
QWORD Context
Context from integrator if the process is protected, 0 otherwise.
Definition: winprocess.h:260
BOOLEAN KernelBetaDetections
True if the kernel protection is in beta (log-only) mode.
Definition: guests.h:299
Event structure for agent injection and termination.
Definition: intro_types.h:2182
Measures the IntWinProcHandleCopyMemory detour handler.
Definition: stats.h:67
The agent process finished execution.
Definition: intro_types.h:1939
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:612
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1420
Windows process subsystem.
Definition: winprocess.h:52
struct _INTRO_ERROR_CONTEXT::@328 ProcessProtection
Process protection errors.
DWORD Delta
The offset inside the affected function at which the access was made.
Definition: intro_types.h:1383
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:267
DWORD Current
The currently used protection flags.
Definition: winguest.h:43
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
Exits caused by "NtQueueApcThreadEx".
Definition: winprocess.h:45
Describes a user-mode originator.
Definition: exceptions.h:933
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:637
static LIST_HEAD gWinProtectedProcesses
A list with all the protected processes (containing PROTECTED_PROCESS_INFO elements).
Definition: winprocess.c:60
#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:35
#define _Outptr_
Definition: intro_sal.h:19
QWORD Feedback
Flags that will be forced to feedback only mode.
Definition: winguest.h:57
INTSTATUS IntWinProcHandleTerminate(void *Detour)
This functions handles the termination of a Windows process.This function is invoked every time "MmCl...
Definition: winprocess.c:2506
#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:550
const WCHAR gSysWowPath[]
The syswow path (32 bit process on a 64 bit OS).
Definition: winprocess.c:75
INTSTATUS IntWinSelfMapGetAndCheckSelfMapEntry(WIN_PROCESS_OBJECT *Process)
Sets and validates the self map entry values for a process.
Definition: winselfmap.c:571
DWORD ExitStatus
The exit code of the process.
Definition: intro_types.h:1764
DWORD OSVersion
Os version.
Definition: guests.h:277
#define KEXEC_OPT_PERMANENT
Freezes the DEP settings for a process.
Definition: wddefs.h:1296
DWORD OneTimeInjectionDone
The one time injection already took place (exception).
Definition: winprocess.h:151
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
DWORD NameHash
Name hash, as used by the exceptions module.
Definition: winprocess.h:99
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:1430
BOOLEAN Continuable
True if the exception is considered to be continuable.
Definition: intro_types.h:1829
QWORD Peb64Address
PEB 64 address (on x86 OSes, this will be 0).
Definition: winprocess.h:101
Event structure for illegal paging-structures modifications.
Definition: intro_types.h:1418
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:1005
DWORD Flags
Flags that describe the protection mode.
Definition: winguest.h:63
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:665
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:701
INTRO_PROCESS CurrentProcess
The agent process.
Definition: intro_types.h:2192
Rootkit.
Definition: intro_types.h:1033
Measures the process creation checks.
Definition: stats.h:84
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:3071
#define IMAGE_BASE_NAME_LEN
The maximum length of a process name.
Definition: winguest.h:14
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:274
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:2186
#define MIN(a, b)
Definition: introdefs.h:146
QWORD MainModuleAddress
The address of the main module.
Definition: winprocess.h:104
#define IC_TAG_PATH
Object path.
Definition: memtags.h:55
INTSTATUS IntWinSelfMapUnprotectSelfMapIndex(WIN_PROCESS_OBJECT *Process)
Removes the EPT protection for the self map entry index of a process.
Definition: winselfmap.c:793
QWORD ParentEprocess
The EPROCESS of the parent process.
Definition: winprocess.h:89
#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:421
Process subsystem type 32 bit.
Definition: winprocess.h:33
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:128
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:23
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:433
DWORD Wow64Process
TRUE if this is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:123
RBTREE gWinProcTreeUserCr3
Tree of all the processes inside the guest, using the user-mode CR3 as the key/.
Definition: winprocesshp.c:15
struct _EVENT_MEMCOPY_VIOLATION::@289 Originator
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:287
INTSTATUS IntWinTokenPrivsProtectOnProcess(WIN_PROCESS_OBJECT *Process)
Updates the stored original Privileges bitfields (Present and Enabled) and hooks through EPT the Priv...
Definition: wintoken.c:1008
TRANS_VIOLATION_TYPE ViolationType
Definition: intro_types.h:1440
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1084
EXCEPTION_VICTIM_OBJECT Object
The modified object.
Definition: exceptions.h:849
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:96
#define ALERT_FLAG_BETA
If set, the alert is a BETA alert. No action was taken.
Definition: intro_types.h:633
MEMCOPY_VIOLATION_TYPE ViolationType
The type of the access.
Definition: intro_types.h:1358
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:1809
DWORD LateProtection
TRUE if the protection was not activated right from start.
Definition: winprocess.h:152
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:1956
#define _Inout_
Definition: intro_sal.h:20
QWORD CreationTime
The creation time of the process, as stored inside the EPROCESS.
Definition: winprocess.h:93
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:109
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:1314
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:1418
#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:27
#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:1355
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
The CR3 of a process was changed.
Definition: intro_types.h:1408
#define STATS_ENTER(id)
Definition: stats.h:141
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1085
uint8_t * PBYTE
Definition: intro_types.h:47
DWORD IsPreviousAgent
TRUE if this is an agent injected in a previous session.
Definition: winprocess.h:162
#define INTRO_OPT_EVENT_PROCESSES
Enable process creation and termination events (generates introEventProcessEvent events).
Definition: intro_types.h:427
BOOLEAN IntMatchPatternUtf16(const WCHAR *Pattern, const WCHAR *String, DWORD Flags)
Matches a pattern using glob match.
Definition: introcore.c:2491
RBNODE NodeEproc
Entry within gWinProcTreeEprocess (RB Tree).
Definition: winprocess.h:86
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:289
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:419
#define PT_P
Definition: pgtable.h:83
LIST_ENTRY Link
Entry inside the gWinProtectedProcesses list.
Definition: winguest.h:77
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:286
#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:106
QWORD Current
The currently used options.
Definition: guests.h:232
INTRO_PROCESS CurrentProcess
The currently active process.
Definition: intro_types.h:1767
BYTE Code[DETOUR_MAX_HANDLER_SIZE]
The code of the detour handler. Only CodeLength bytes are valid.
Definition: detours.h:294
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:183
QWORD UserCr3
Process user PDBR. Includes PCID.
Definition: winprocess.h:97
CHAR ImageBaseNamePattern[IMAGE_BASE_NAME_LEN]
Process name pattern.
Definition: winguest.h:28
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:1770
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:124
int strlower_utf16(WCHAR *buf, size_t len)
Definition: introcrt.c:28
void * GpaCache
The currently used GPA cache.
Definition: guests.h:399
#define KEXEC_OPT_EXEC_ENABLE
Enables execution rights for memory that contains data. Disables DEP.
Definition: wddefs.h:1290
#define TRUE
Definition: intro_types.h:30
QWORD Beta
Flags that were forced to beta (log-only) mode.
Definition: winguest.h:50
#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:1394
INTRO_WRITE_INFO WriteInfo
The original and new address to which VirtualAddress translates.
Definition: intro_types.h:1438
DWORD StartInitializing
TRUE if the process actually started initializing (there is a time windows from the moment we add the...
Definition: winprocess.h:149
#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:20
struct _EVENT_TRANSLATION_VIOLATION::@293 Victim
DWORD ProtectionMask
Protection mask: tells us what level of protection will be activated for this process.
Definition: winprocess.h:196
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
Definition: guests.h:289
This is a classic code injection attempt that simply modifies the memory of the victim process...
Definition: intro_types.h:1293
#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:122
DWORD ExitStatus
The exit status of the process (used when sending the process terminated event).
Definition: winprocess.h:188
#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:1312
DWORD AgentTag
Unique agent tag. See INTRO_DEP_AG_TAGS.
Definition: intro_types.h:2185
BOOLEAN DumpValid
True if the contents of RawDump are valid, False if not.
Definition: intro_types.h:1361
Exits caused by "MiCommitExistingVad".
Definition: winprocess.h:41
#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:641
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:54
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:363
BOOLEAN Protected
True if the process is protected.
Definition: intro_types.h:1752
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:353
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:183
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:224
INTSTATUS IntDetGetArgument(void const *Detour, DWORD Index, BYTE const *StackBuffer, DWORD StackBufferSize, QWORD *Value)
Reads the specified argument for a detour.
Definition: detours.c:2105
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Definition: introstatus.h:323
INTSTATUS IntWinProcPatchCopyMemoryDetour(QWORD FunctionAddress, void *Handler, QWORD HandlerAddress)
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:2570
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:98
INTSTATUS IntWinTokenPtrCheckIntegrityOnProcess(WIN_PROCESS_OBJECT *Process)
This function checks if the security token of a given process has been stone from another process...
Definition: wintoken.c:604
Process subsystem type 64 bit.
Definition: winprocess.h:32
static void IntWinProcSetUserCr3(WIN_PROCESS_OBJECT *Process, const BYTE *EprocessBuffer)
Sets the User CR3 value for a newly created process.
Definition: winprocess.c:1320
PWCHAR FullPathPattern
Full application path pattern.
Definition: winguest.h:65
struct _PROTECTED_PROCESS_INFO::@206 Protection
The protection flags used for this process.
#define INTRO_OPT_FULL_PATH
Enable full-path protection of processes.
Definition: intro_types.h:440
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.
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:636
static INTSTATUS IntWinProcRemoveProtectedProcessInternal(CHAR BaseName[IMAGE_BASE_NAME_LEN], const WCHAR *FullPath)
This function removes the protection for the given process.
Definition: winprocess.c:3438
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:527
#define PAGE_SIZE
Definition: common.h:53
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:847
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
#define PROC_OPT_PROT_EXPLOIT
Blocks malicious execution attempts.
Definition: intro_types.h:341
#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:400
DWORD BetaDetections
TRUE if BETA is enabled for this particular process.
Definition: winprocess.h:133
INTSTATUS IntWinTokenPrivsUnprotectOnProcess(WIN_PROCESS_OBJECT *Process)
Definition: wintoken.c:1069
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:1825
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:726
EVENT_AGENT_EVENT Agent
Definition: alerts.h:29
QWORD Peb32Address
PEB 32 address (on pure x64 processes, this will be 0).
Definition: winprocess.h:102
static BOOLEAN IntWinProcIsFullPath(const WCHAR *Path)
This function checks if the provided path is a full path.
Definition: winprocess.c:3349
uint32_t DWORD
Definition: intro_types.h:49
const WCHAR gSystemPath[]
The system path.
Definition: winprocess.c:70
#define PROC_OPT_PROT_CORE_HOOKS
Blocks hooks being set on core user-mode DLLs.
Definition: intro_types.h:333
INTSTATUS IntDetGetArguments(void const *Detour, DWORD Argc, QWORD *Argv)
Reads multiple arguments from a detour.
Definition: detours.c:2164
QWORD OriginalTokenPtr
Original Token pointer inside EPROCESS (should never change).
Definition: winprocess.h:241
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:879
LIST_ENTRY Link
List entry element.
Definition: winummodule.h:32
static DWORD gTotalProtectedProcs
The total number of protected processes.
Definition: winprocess.c:65
INTSTATUS IntWinProcRemoveAllProtectedProcesses(void)
This function removed all the processes from the protected process list.
Definition: winprocess.c:3704
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:894
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:3834
INTRO_PROCESS CurrentProcess
The process in which the exception was triggered.
Definition: intro_types.h:1832
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
struct _EVENT_MEMCOPY_VIOLATION::@291 Export
All the names used to export the modified function.
#define WIN_STATUS_ACCESS_DENIED
Equivalent to NTSTATUS STATUS_ACCESS_DENIED.
Definition: winprocess.h:22
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:68
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:2618
Event structure for process exceptions.
Definition: intro_types.h:1820
RBNODE NodeUserCr3
Entry within gWinProcTreeUserCr3 (RB Tree).
Definition: winprocess.h:85
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:884
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:370
void * CmdBufSwapHandle
The swap memory handle for the command line buffer.
Definition: winprocess.h:251
DWORD ExploitGuardEnabled
TRUE if any Exploit Guard mitigation option is set for this process.
Definition: winprocess.h:165
INTSTATUS IntWinProcHandleCopyMemory(void *Detour)
This functions is responsible handling process read/write operations.This function is invoked every t...
Definition: winprocess.c:2694
DWORD ProtWriteMem
Protect the the memory against writes.
Definition: winprocess.h:203
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:88
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:635
DWORD ParentWow64
TRUE if the parent is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:144
DWORD FunctionNameHash
The hash of the FunctionName. It is the same as Export.Hash[0].
Definition: intro_types.h:1380
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:134
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
static INTSTATUS IntWinProcMarkAgent(WIN_PROCESS_OBJECT *Process, BOOLEAN Mark)
Mark the given process as being an agent.
Definition: winprocess.c:357
static INTSTATUS IntWinProcDeleteProcessObject(QWORD EprocessAddress, QWORD Cr3, DWORD Pid)
Used to delete the process from the Introcore internal structures.
Definition: winprocess.c:2096
void * CmdLineSwapHandle
The swap memory handle for the UNICODE_STRING containing the command line of the a process...
Definition: winprocess.h:249
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:2106
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:1370
This is the structure as documented in winternl.h.
Definition: wddefs.h:608
DWORD Count
The number of currently protected processes.
Definition: intro_types.h:2261
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:950
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 IntWinProcHandleCreate(void *Detour)
Detour handler for the PspInsertProcess Windows kernel API.The actual process creation is handled by ...
Definition: winprocess.c:2434
#define PROC_OPT_PROT_INJECTION
Aggregates all the flags that will generate introEventInjectionViolation events.
Definition: intro_types.h:366
#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
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:23
void RbDeleteNode(RBTREE *Tree, RBNODE *Node)
Definition: rbtree.c:710
INTSTATUS IntWinProcChangeProtectionFlags(WIN_PROCESS_OBJECT *Process, DWORD OldMask, DWORD NewMask)
This function changes the protection flags for the given process.
Definition: winprocess.c:3877
#define FIELD_OFFSET(type, field)
Definition: introdefs.h:239
WIN_SUBSYTEM_TYPE SubsystemType
Process subsystem type.
Definition: winprocess.h:55
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:57
#define PROC_OPT_BETA
Process is monitored, but in log-only mode so no actions will be blocked.
Definition: intro_types.h:363
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1083
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:337
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:699
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:160
#define PROC_OPT_PROT_UNPACK
Identifies unpacking/decryption attempts in the main executable.
Definition: intro_types.h:335
DWORD StaticDetected
TRUE if the process was detected using a static scan (during static init).
Definition: winprocess.h:138
QWORD Rip
The RIP at which the exception was triggered.
Definition: intro_types.h:1827
#define LIST_HEAD_INIT(Name)
Definition: introlists.h:39
#define _Out_writes_z_(expr)
Definition: intro_sal.h:37
INTSTATUS RbInsertNode(RBTREE *Tree, RBNODE *Node)
Definition: rbtree.c:606
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:46
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:441
Measures the information gathering for the DPI mechanism.
Definition: stats.h:83
void IntWinProcDumpProtected(void)
Log all the protected processes.
Definition: winprocess.c:3736
EXCEPTION_VICTIM_MODULE Library
The victim module of the modified library.
Definition: exceptions.h:831
#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:1086
#define IC_TAG_PPIF
Protected process info.
Definition: memtags.h:81
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
#define INTRO_OPT_PROT_KM_TOKEN_PRIVS
Enable protection over Token Privileges bitmaps.
Definition: intro_types.h:489
BOOLEAN Crashed
True if the process crashed.
Definition: intro_types.h:1758
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:129
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 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:1938
static INTSTATUS IntWinProcSendProcessExceptionEvent(WIN_PROCESS_OBJECT *Process)
Send a process exception event.
Definition: winprocess.c:500
This is the structure as documented in winternl.h.
Definition: wddefs.h:706
VAD * Vad
The internal structure of the modified VAD.
Definition: exceptions.h:830
const PROTECTED_PROCESS_INFO gSystemProcesses[]
This is a list with system processes and their default protection mask.
Definition: winprocess.c:80
#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:129
Holds register state.
Definition: glueiface.h:30
INTSTATUS IntWinModRemoveModule(PWIN_PROCESS_MODULE Module)
Removes a Windows module.
Definition: winummodule.c:1714
Exits caused by "MmCopyVirtualMemory".
Definition: winprocess.h:43
Exits caused by "PspSetContextThreadInternal".
Definition: winprocess.h:44
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:3481
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:1772
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:1063
QWORD SourceVirtualAddress
The virtual address of the source buffer.
Definition: intro_types.h:1342
INTSTATUS IntWinGuestFindDriversNamespace(void)
Runs the driver object namespace search.
Definition: winobj.c:1781
QWORD EndPage
Definition: winvad.h:106
QWORD DestinationVirtualAddress
The virtual address of the destination buffer.
Definition: intro_types.h:1352
void IntWinProcUninit(void)
This function removes all process objects from the list, and registers the calls the cleanup function...
Definition: winprocess.c:3764
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
Definition: guests.h:324
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:445
#define KEXEC_OPT_EXEC_DISABLE
Disables execution rights for memory that contains data. Enables DEP.
Definition: wddefs.h:1286
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:648
PWCHAR FullNamePattern
Full application name pattern.
Definition: winguest.h:69
This represents a read done from another process.
Definition: intro_types.h:1296
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:296
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
RBNODE NodeCr3
Entry within gWinProcTreeCr3 (RB Tree).
Definition: winprocess.h:84
This is the structure as documented in winternl.h.
Definition: wddefs.h:619
INTSTATUS IntWinModUnHookModule(PWIN_PROCESS_MODULE Module)
Remove the protection from the indicated module.
Definition: winummodule.c:878
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:742
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:227
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:1494
A representation of a Windows VAD structure.
Definition: winvad.h:80
DWORD IsMainModule
TRUE if this is the main module.
Definition: winummodule.h:47
INTSTATUS IntWinProcProtect(WIN_PROCESS_OBJECT *Process)
Protects a new process.
Definition: winprocess.c:3111
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:698
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:267
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:797
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:3317
INTSTATUS IntWinProcUpdateProtection(void)
Iterates trough the global process list (gWinProcesses) in order to update the protection state for e...
Definition: winprocess.c:1155
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:607
This structure describes a running process inside the guest.
Definition: winprocess.h:81
#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