Bitdefender Hypervisor Memory Introspection
exceptions_user.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
10 
11 
12 #include "exceptions.h"
13 #include "guests.h"
14 #include "winpe.h"
15 #include "winprocesshp.h"
16 #include "winstack.h"
17 #include "winuser_checks.h"
18 
19 
20 extern char gExcLogLine[2 * ONE_KILOBYTE];
21 
22 
23 static char *
26  )
34 {
35  switch(Type)
36  {
38  return "Normal";
39 
41  return "Debug";
42 
44  return "Pivoted Stack";
45 
47  return "Stolen token";
48 
50  return "Heap spray";
51 
53  return "Token Privs";
54 
56  return "Thread Start";
57 
59  return "Security Descriptor";
60 
62  return "ACL Edit";
63 
64  default:
65  return "<Unknown>";
66  }
67 }
68 
69 
70 int
72  _In_opt_ const LIX_TASK_OBJECT *Task,
73  _In_ char *Header,
74  _Out_ char *Line,
75  _In_ int MaxLength,
76  _In_opt_ DWORD NameAlignment
77  )
89 {
90  int ret, total = 0;
91 
92  if (NULL == Task)
93  {
94  return total;
95  }
96 
97  if (NameAlignment)
98  {
99  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, Task->ProcName);
100  }
101  else
102  {
103  ret = snprintf(Line, MaxLength, "%s(%s", Header, Task->ProcName);
104  }
105 
106  if (ret < 0 || ret >= MaxLength)
107  {
108  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
109  }
110  else
111  {
112  Line += ret;
113  total += ret;
114  MaxLength -= ret;
115  }
116 
117  ret = snprintf(Line, MaxLength, " '%s' [0x%08x], %016llx, %016llx, %016llx, %d/%d",
118  Task->Comm, Task->CommHash, Task->Gva, Task->Cr3, Task->MmGva, Task->Pid, Task->Tgid);
119 
120  if (ret < 0 || ret >= MaxLength)
121  {
122  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
123  }
124  else
125  {
126  Line += ret;
127  total += ret;
128  MaxLength -= ret;
129  }
130 
131  if (Task->CmdLine)
132  {
133  ret = snprintf(Line, MaxLength, ", CLI:`%s`", Task->CmdLine);
134 
135  if (ret < 0 || ret >= MaxLength)
136  {
137  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
138  }
139  else
140  {
141  Line += ret;
142  total += ret;
143  MaxLength -= ret;
144  }
145  }
146 
147  ret = snprintf(Line, MaxLength, ")");
148 
149  if (ret < 0 || ret >= MaxLength)
150  {
151  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
152  }
153  else
154  {
155  Line += ret;
156  total += ret;
157  MaxLength -= ret;
158  }
159 
160  return total;
161 }
162 
163 
164 static void
166  _In_ EXCEPTION_VICTIM_ZONE *Victim,
167  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
168  _In_ INTRO_ACTION Action,
170  )
179 {
180  DWORD procNameAlignment;
181  char *l;
182  int ret, rem;
183 
184  // This cannot be NULL! Everything must happen inside a process in user-mode
185  if (NULL == Originator->LixProc)
186  {
187  ERROR("[ERROR] Originator process is NULL!\n");
188  return;
189  }
190 
191  procNameAlignment = 0;
192  if (Victim->Object.LixProc)
193  {
194  procNameAlignment = (DWORD)MIN(MAX_PATH,
195  MAX(Victim->Object.LixProc->ProcNameLength,
196  Originator->LixProc->ProcNameLength));
197  }
198 
199  l = gExcLogLine;
200  rem = sizeof(gExcLogLine);
201 
202  if ((Victim->ZoneType == exceptionZoneProcess) ||
203  (Victim->Object.Type == introObjectTypeUmGenericNxZone))
204  {
205  ret = IntExceptPrintLixTaskInfo(Originator->LixProc, "Originator-> Process: ", l, rem, procNameAlignment);
206  rem -= ret;
207  l += ret;
208 
209  if (Victim->ZoneType == exceptionZoneProcess)
210  {
211  ret = snprintf(l, rem, ", VA: %016llx", Originator->SourceVA);
212  }
213  else
214  {
215  ret = snprintf(l, rem, ", RIP: %016llx", Originator->Rip);
216  }
217 
218  if (ret < 0 || ret >= rem)
219  {
220  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
221  }
222  else
223  {
224  rem -= ret;
225  l += ret;
226  }
227 
228  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Originator->LixProc->Parent), ", Parent: ", l, rem, 0);
229  rem -= ret;
230  l += ret;
231 
232  LOG("%s\n", gExcLogLine);
233  }
234  else if (Victim->ZoneType == exceptionZonePc)
235  {
236  ret = IntExceptPrintLixTaskInfo(Originator->LixProc, "Originator-> Process: ", l, rem, procNameAlignment);
237  rem -= ret;
238  l += ret;
239 
240  ret = snprintf(l, rem, ", Type: %s (0x%08x)", IntExceptUserGetPcTypeString(Originator->PcType),
241  Originator->PcType);
242 
243  if (ret < 0 || ret >= rem)
244  {
245  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
246  }
247  else
248  {
249  rem -= ret;
250  l += ret;
251  }
252 
253  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Originator->LixProc->Parent), ", Parent: ", l, rem, 0);
254  rem -= ret;
255  l += ret;
256 
257  LOG("%s\n", gExcLogLine);
258  }
259  else if ((Victim->Object.Type == introObjectTypeVdso) ||
260  (Victim->Object.Type == introObjectTypeVsyscall))
261  {
262  ret = IntExceptPrintLixTaskInfo(Originator->LixProc, "Originator-> Process: ", l, rem, procNameAlignment);
263  rem -= ret;
264  l += ret;
265 
266  ret = snprintf(l, rem, ", RIP: %016llx", Originator->Rip);
267 
268  if (ret < 0 || ret >= rem)
269  {
270  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
271  }
272  else
273  {
274  rem -= ret;
275  l += ret;
276  }
277 
278  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Originator->LixProc->Parent),
279  ", Parent: ", l, rem, 0);
280  rem -= ret;
281  l += ret;
282 
283  LOG("%s\n", gExcLogLine);
284  }
285 
286  l = gExcLogLine;
287  rem = sizeof(gExcLogLine);
288 
289  if ((Victim->ZoneType == exceptionZoneProcess) ||
290  (Victim->Object.Type == introObjectTypeUmGenericNxZone))
291  {
292  ret = IntExceptPrintLixTaskInfo(Victim->Object.LixProc, "Victim -> Process: ", l, rem, procNameAlignment);
293  rem -= ret;
294  l += ret;
295 
296  if (Victim->ZoneType == exceptionZoneProcess)
297  {
298  ret = snprintf(l, rem, ", InjInfo: (%u, %016llx)",
299  Victim->Injection.Length, Victim->Injection.Gva);
300  }
301  else
302  {
303  ret = snprintf(l, rem, ", ExecInfo: (%016llx, %016llx), Stack: (0x%016llx, 0x%16llx), RSP = 0x%016llx",
304  Victim->Ept.Gva, Victim->Ept.Gpa, Victim->ExecInfo.StackBase, Victim->ExecInfo.StackLimit,
305  Victim->ExecInfo.Rsp);
306  }
307 
308  if (ret < 0 || ret >= rem)
309  {
310  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
311  }
312  else
313  {
314  rem -= ret;
315  l += ret;
316  }
317 
318  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Victim->Object.LixProc->Parent),
319  ", Parent: ", l, rem, 0);
320  rem -= ret;
321  l += ret;
322 
323  LOG("%s\n", gExcLogLine);
324  }
325  if (Victim->ZoneType == exceptionZonePc)
326  {
327  ret = IntExceptPrintLixTaskInfo(Victim->Object.LixProc, "Victim -> Process: ", l, rem, procNameAlignment);
328  rem -= ret;
329  l += ret;
330 
331  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Victim->Object.LixProc->Parent), ", Parent: ", l, rem, 0);
332  rem -= ret;
333  l += ret;
334 
335  LOG("%s\n", gExcLogLine);
336  }
337  else if ((Victim->Object.Type == introObjectTypeVdso) ||
338  (Victim->Object.Type == introObjectTypeVsyscall))
339  {
340  const char *libName = (Victim->Object.Type == introObjectTypeVdso) ? "[vdso]" : "[vsyscall]";
341 
342  ret = IntExceptPrintLixTaskInfo(Victim->Object.LixProc, "Victim -> Process: ", l, rem, procNameAlignment);
343  rem -= ret;
344  l += ret;
345 
346  ret = snprintf(l, rem, ", Address: (%0llx, %0llx), Lib: %s, WriteInfo: (%u, %016llx -> %016llx)",
347  Victim->Ept.Gva, Victim->Ept.Gpa,
348  libName, Victim->WriteInfo.AccessSize,
349  Victim->WriteInfo.OldValue[0],
350  Victim->WriteInfo.NewValue[0]);
351 
352  if (ret < 0 || ret >= rem)
353  {
354  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
355  }
356  else
357  {
358  rem -= ret;
359  l += ret;
360  }
361 
362  LOG("%s\n", gExcLogLine);
363  }
364 
365  if (Action == introGuestNotAllowed)
366  {
367  l = gExcLogLine;
368  rem = sizeof(gExcLogLine);
369 
370  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sMALWARE (user-mode) ",
371  (Victim->Object.LixProc && Victim->Object.LixProc->Protection.Mask & PROC_OPT_BETA) ?
372  " (B) " : " ");
373 
374  if (ret < 0 || ret >= rem)
375  {
376  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
377  }
378  else
379  {
380  rem -= ret;
381  l += ret;
382  }
383 
384  switch (Reason)
385  {
387  ret = snprintf(l, rem, "(no sig)");
388  break;
390  ret = snprintf(l, rem, "(no exc)");
391  break;
393  ret = snprintf(l, rem, "(extra)");
394  break;
396  ret = snprintf(l, rem, "(error)");
397  break;
399  ret = snprintf(l, rem, "(value)");
400  break;
402  ret = snprintf(l, rem, "(value code)");
403  break;
405  ret = snprintf(l, rem, "(idt)");
406  break;
408  ret = snprintf(l, rem, "(version os)");
409  break;
411  ret = snprintf(l, rem, "(version intro)");
412  break;
414  ret = snprintf(l, rem, "(export)");
415  break;
417  ret = snprintf(l, rem, "(process creation)");
418  break;
419  case introReasonUnknown:
420  ret = snprintf(l, rem, "(unknown)");
421  break;
422  default:
423  ret = snprintf(l, rem, "(%d)", Reason);
424  break;
425  }
426 
427  if (ret < 0 || ret >= rem)
428  {
429  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
430  }
431  else
432  {
433  rem -= ret;
434  l += ret;
435  }
436 
437  ret = snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
438 
439  if (ret < 0 || ret >= rem)
440  {
441  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
442  }
443  else
444  {
445  rem -= ret;
446  l += ret;
447  }
448 
449  LOG("%s\n\n", gExcLogLine);
450  }
451 }
452 
453 
454 int
456  _In_ WIN_PROCESS_OBJECT *Process,
457  _In_ char *Header,
458  _Out_ char *Line,
459  _In_ int MaxLength,
460  _In_opt_ DWORD NameAlignment
461  )
473 {
474  int ret, total = 0;
475 
476  if (NULL == Process)
477  {
478  return total;
479  }
480 
481  if (NameAlignment)
482  {
483  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, Process->Name);
484  }
485  else
486  {
487  ret = snprintf(Line, MaxLength, "%s(%s", Header, Process->Name);
488  }
489 
490  if (ret < 0 || ret >= MaxLength)
491  {
492  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
493  }
494  else
495  {
496  Line += ret;
497  total += ret;
498  MaxLength -= ret;
499  }
500 
501  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx, %0*llx, %u, F%x",
502  Process->NameHash, gGuest.WordSize * 2, Process->EprocessAddress,
503  gGuest.WordSize * 2, Process->Cr3, Process->Pid, Process->Flags);
504 
505  if (ret < 0 || ret >= MaxLength)
506  {
507  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
508  }
509  else
510  {
511  Line += ret;
512  total += ret;
513  MaxLength -= ret;
514  }
515 
516  if (Process->Wow64Process)
517  {
518  ret = snprintf(Line, MaxLength, ", WOW64");
519 
520  if (ret < 0 || ret >= MaxLength)
521  {
522  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
523  }
524  else
525  {
526  Line += ret;
527  total += ret;
528  MaxLength -= ret;
529  }
530  }
531 
532  if (Process->SystemProcess)
533  {
534  ret = snprintf(Line, MaxLength, ", SYS");
535 
536  if (ret < 0 || ret >= MaxLength)
537  {
538  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
539  }
540  else
541  {
542  Line += ret;
543  total += ret;
544  MaxLength -= ret;
545  }
546  }
547 
548  if (Process->Peb64Address)
549  {
550  ret = snprintf(Line, MaxLength, ", PEB64: %0*llx", gGuest.WordSize * 2, Process->Peb64Address);
551 
552  if (ret < 0 || ret >= MaxLength)
553  {
554  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
555  }
556  else
557  {
558  Line += ret;
559  total += ret;
560  MaxLength -= ret;
561  }
562  }
563 
564  if (Process->Peb32Address)
565  {
566  ret = snprintf(Line, MaxLength, ", PEB32: %0*llx", gGuest.WordSize * 2, Process->Peb32Address);
567 
568  if (ret < 0 || ret >= MaxLength)
569  {
570  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
571  }
572  else
573  {
574  Line += ret;
575  total += ret;
576  MaxLength -= ret;
577  }
578  }
579 
580  if (Process->CommandLine)
581  {
582  ret = snprintf(Line, MaxLength, ", CLI:`%s`", Process->CommandLine);
583 
584  if (ret < 0 || ret >= MaxLength)
585  {
586  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
587  }
588  else
589  {
590  Line += ret;
591  total += ret;
592  MaxLength -= ret;
593  }
594  }
595 
596  ret = snprintf(Line, MaxLength, ")");
597 
598  if (ret < 0 || ret >= MaxLength)
599  {
600  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
601  }
602  else
603  {
604  Line += ret;
605  total += ret;
606  MaxLength -= ret;
607  }
608  return total;
609 }
610 
611 
612 int
614  _In_ WIN_PROCESS_MODULE *Module,
615  _In_ char *Header,
616  _Out_ char *Line,
617  _In_ int MaxLength,
618  _In_opt_ DWORD NameAlignment
619  )
631 {
632  int ret, total = 0;
633  WCHAR *wName;
634  DWORD nameHash;
635  char name[MAX_PATH];
636 
637  if (NULL == Module)
638  {
639  return snprintf(Line, MaxLength, "%s(%s)", Header, EXCEPTION_NO_NAME);
640  }
641 
642  if (Module->Path)
643  {
644  wName = Module->Path->Path;
645  nameHash = Module->Path->NameHash;
646  }
647  else
648  {
649  wName = NULL;
650  nameHash = INITIAL_CRC_VALUE;
651  }
652 
653  if (wName)
654  {
655  utf16toutf8(name, wName, sizeof(name));
656  }
657  else
658  {
659  memcpy(name, EXCEPTION_NO_NAME, sizeof(EXCEPTION_NO_NAME));
660  }
661 
662  if (NameAlignment)
663  {
664  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, name);
665  }
666  else
667  {
668  ret = snprintf(Line, MaxLength, "%s(%s", Header, name);
669  }
670 
671  if (ret < 0 || ret >= MaxLength)
672  {
673  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
674  }
675  else
676  {
677  Line += ret;
678  total += ret;
679  MaxLength -= ret;
680  }
681 
682  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx, F%x",
683  nameHash, gGuest.WordSize * 2, Module->VirtualBase, Module->Flags);
684 
685  if (ret < 0 || ret >= MaxLength)
686  {
687  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
688  }
689  else
690  {
691  Line += ret;
692  total += ret;
693  MaxLength -= ret;
694  }
695 
696  if (Module->Cache && Module->Cache->Info.TimeDateStamp)
697  {
698  ret = snprintf(Line, MaxLength, ", VerInfo: %x:%x",
699  Module->Cache->Info.TimeDateStamp, Module->Cache->Info.SizeOfImage);
700 
701  if (ret < 0 || ret >= MaxLength)
702  {
703  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
704  }
705  else
706  {
707  Line += ret;
708  total += ret;
709  MaxLength -= ret;
710  }
711  }
712 
713  if (Module->Cache && (Module->Cache->Info.IatRva || Module->Cache->Info.IatSize))
714  {
715  ret = snprintf(Line, MaxLength, ", IAT: %x:%x",
716  Module->Cache->Info.IatRva, Module->Cache->Info.IatSize);
717  if (ret < 0 || ret >= MaxLength)
718  {
719  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
720  }
721  else
722  {
723  Line += ret;
724  total += ret;
725  MaxLength -= ret;
726  }
727  }
728 
729  ret = snprintf(Line, MaxLength, ")");
730  if (ret < 0 || ret >= MaxLength)
731  {
732  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, MaxLength);
733  }
734  else
735  {
736  Line += ret;
737  total += ret;
738  MaxLength -= ret;
739  }
740 
741  return total;
742 }
743 
744 
745 static void
747  _In_ EXCEPTION_VICTIM_ZONE *Victim,
748  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
749  _In_ INTRO_ACTION Action,
751  )
760 {
761  DWORD modNameAlignment;
762  char *l;
763  int ret, rem;
764 
765  // This cannot be NULL! Everything must happen inside a process in user-mode
766  if (NULL == Originator->WinProc)
767  {
768  ERROR("[ERROR] Originator process is NULL!\n");
769  return;
770  }
771 
772  // We will log only the first double agent alert, afterwards we'll only check exceptions
773  if ((Victim->ZoneFlags & ZONE_MODULE_LOAD) != 0 &&
774  Originator->WinLib->DoubleAgentAlertSent)
775  {
776  return;
777  }
778 
779  modNameAlignment = 0;
780  if (Victim->Object.Type == introObjectTypeUmModule)
781  {
782  if (Victim->Object.Library.WinMod && Originator->WinLib)
783  {
784  modNameAlignment = MIN(MAX_PATH,
785  MAX(Victim->Object.Library.WinMod->Path->PathSize,
786  Originator->WinLib->Path->PathSize) >> 1);
787  }
788  }
789 
790  l = gExcLogLine;
791  rem = sizeof(gExcLogLine);
792 
793  if ((Victim->ZoneType == exceptionZoneProcess) ||
794  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
795  (Victim->Object.Type == introObjectTypeSudExec))
796  {
797  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Originator->WinProc->ParentEprocess);
798 
799  ret = IntExceptPrintWinProcInfo(Originator->WinProc, "Originator-> Process: ", l, rem, 14);
800  rem -= ret;
801  l += ret;
802 
803  if (Victim->ZoneType == exceptionZoneProcess)
804  {
805  ret = snprintf(l, rem, ", VA: %0*llx", gGuest.WordSize * 2, Originator->SourceVA);
806  }
807  else
808  {
809  ret = snprintf(l, rem, ", RIP: %0*llx", gGuest.WordSize * 2, Originator->Rip);
810  }
811 
812  if (ret < 0 || ret >= rem)
813  {
814  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
815  }
816  else
817  {
818  rem -= ret;
819  l += ret;
820  }
821 
822  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
823  rem -= ret;
824  l += ret;
825 
826  LOG("%s\n", gExcLogLine);
827 
828  if ((Victim->Object.Type == introObjectTypeUmGenericNxZone ||
829  Victim->Object.Type == introObjectTypeSudExec) &&
830  Originator->Return.Library &&
831  Originator->Return.Rip != Originator->Rip)
832  {
833  l = gExcLogLine;
834  rem = sizeof(gExcLogLine);
835 
836  ret = IntExceptPrintWinModInfo(Originator->Return.WinLib,
837  "Return -> Module: ",
838  l,
839  rem,
840  modNameAlignment);
841  if (ret < 0 || ret >= rem)
842  {
843  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
844  }
845  else
846  {
847  rem -= ret;
848  l += ret;
849  }
850 
851  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Return.Rip);
852 
853  if (ret < 0 || ret >= rem)
854  {
855  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
856  }
857  else
858  {
859  rem -= ret;
860  l += ret;
861  }
862 
863  LOG("%s\n", gExcLogLine);
864  }
865  }
866  else if (Victim->ZoneType == exceptionZonePc)
867  {
868  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Originator->WinProc->ParentEprocess);
869 
870  ret = IntExceptPrintWinProcInfo(Originator->WinProc, "Originator-> Process: ", l, rem, 14);
871  rem -= ret;
872  l += ret;
873 
874  ret = snprintf(l, rem, ", Type: %s (0x%08x)", IntExceptUserGetPcTypeString(Originator->PcType),
875  Originator->PcType);
876 
877  if (ret < 0 || ret >= rem)
878  {
879  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
880  }
881  else
882  {
883  rem -= ret;
884  l += ret;
885  }
886 
887  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
888  rem -= ret;
889  l += ret;
890 
891  LOG("%s\n", gExcLogLine);
892  }
893  else if (Victim->Object.Type == introObjectTypeUmModule)
894  {
895  CHAR instr[ND_MIN_BUF_SIZE];
896  NDSTATUS ndstatus;
897 
898  ndstatus = NdToText(Originator->Instruction, Originator->Rip, sizeof(instr), instr);
899  if (!ND_SUCCESS(ndstatus))
900  {
901  memcpy(instr, EXPORT_NAME_UNKNOWN, sizeof(EXPORT_NAME_UNKNOWN));
902  }
903 
904  ret = IntExceptPrintWinModInfo(Originator->WinLib, "Originator-> Module: ", l, rem, modNameAlignment);
905  if (ret < 0 || ret >= rem)
906  {
907  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
908  }
909  else
910  {
911  rem -= ret;
912  l += ret;
913  }
914 
915  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Rip);
916 
917  if (ret < 0 || ret >= rem)
918  {
919  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
920  }
921  else
922  {
923  rem -= ret;
924  l += ret;
925  }
926 
927  ret = IntExceptPrintWinProcInfo(Originator->WinProc, ", Process: ", l, rem, 0);
928  rem -= ret;
929  l += ret;
930 
931  ret = snprintf(l, rem, ", Instr: %s", instr);
932 
933  if (ret < 0 || ret >= rem)
934  {
935  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
936  }
937  else
938  {
939  rem -= ret;
940  l += ret;
941  }
942 
943  LOG("%s\n", gExcLogLine);
944 
945  if (Originator->Return.Library && Originator->Return.Rip != Originator->Rip)
946  {
947  l = gExcLogLine;
948  rem = sizeof(gExcLogLine);
949 
950  ret = IntExceptPrintWinModInfo(Originator->Return.WinLib,
951  "Return -> Module: ",
952  l,
953  rem,
954  modNameAlignment);
955  if (ret < 0 || ret >= rem)
956  {
957  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
958  }
959  else
960  {
961  rem -= ret;
962  l += ret;
963  }
964 
965  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Return.Rip);
966 
967  if (ret < 0 || ret >= rem)
968  {
969  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
970  }
971  else
972  {
973  rem -= ret;
974  l += ret;
975  }
976 
977  LOG("%s\n", gExcLogLine);
978  }
979  }
980 
981  l = gExcLogLine;
982  rem = sizeof(gExcLogLine);
983 
984  if ((Victim->ZoneType == exceptionZoneProcess) ||
985  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
986  (Victim->Object.Type == introObjectTypeSudExec))
987  {
988  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Victim->Object.WinProc->ParentEprocess);
989 
990  ret = IntExceptPrintWinProcInfo(Victim->Object.WinProc, "Victim -> Process: ", l, rem, 14);
991  rem -= ret;
992  l += ret;
993 
994  if (Victim->ZoneType == exceptionZoneProcess)
995  {
996  ret = snprintf(l, rem, ", InjInfo: (%u, %0*llx), Init: (%u, %u)",
997  Victim->Injection.Length, gGuest.WordSize * 2,
998  Victim->Injection.Gva, Victim->Object.WinProc->StartInitializing,
999  Victim->Object.WinProc->Initialized);
1000  }
1001  else if (Victim->Object.Type == introObjectTypeUmGenericNxZone)
1002  {
1003 
1004  ret = snprintf(l, rem, ", ExecInfo: (0x%0*llx, 0x%0*llx), Stack: (0x%0*llx, 0x%0*llx), SP = 0x%0*llx",
1005  gGuest.WordSize * 2, Victim->Ept.Gva, gGuest.WordSize * 2, Victim->Ept.Gpa,
1006  gGuest.WordSize * 2, Victim->ExecInfo.StackBase, gGuest.WordSize * 2,
1007  Victim->ExecInfo.StackLimit, gGuest.WordSize * 2, Victim->ExecInfo.Rsp);
1008  }
1009 
1010  if (ret < 0 || ret >= rem)
1011  {
1012  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1013  }
1014  else
1015  {
1016  rem -= ret;
1017  l += ret;
1018  }
1019 
1020  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
1021  rem -= ret;
1022  l += ret;
1023 
1024  LOG("%s\n", gExcLogLine);
1025 
1026  if (Victim->Object.Vad)
1027  {
1028  PWCHAR path = EXCEPTION_NO_WNAME;
1029 
1030  if (Victim->Object.Vad->Path)
1031  {
1032  path = Victim->Object.Vad->Path->Path;
1033  }
1034  else if (Victim->Object.Vad->IsStack)
1035  {
1036  path = u"<stack>";
1037  }
1038 
1039  LOG("Victim -> VAD: [%llx - %llx], Prot: %x, VadProt: %x, Type: %d, Name: %s\n",
1040  Victim->Object.Vad->StartPage, Victim->Object.Vad->EndPage, Victim->Object.Vad->Protection,
1041  Victim->Object.Vad->VadProtection, Victim->Object.Vad->VadType, utf16_for_log(path));
1042  }
1043 
1044  if (Victim->Object.Library.WinMod)
1045  {
1046  QWORD startGva, exportGva;
1047  WINUM_CACHE_EXPORT *pExport = NULL;
1048 
1049  l = gExcLogLine;
1050  rem = sizeof(gExcLogLine);
1051 
1052  ret = IntExceptPrintWinModInfo(Victim->Object.Library.WinMod, "Victim -> Module: ", l, rem, 0);
1053  if (ret < 0 || ret >= rem)
1054  {
1055  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1056  }
1057  else
1058  {
1059  rem -= ret;
1060  l += ret;
1061  }
1062 
1063  if (Victim->ZoneType == exceptionZoneProcess)
1064  {
1065  startGva = exportGva = Victim->Injection.Gva;
1066  }
1067  else
1068  {
1069  startGva = exportGva = Victim->Ept.Gva;
1070  }
1071 
1072  if (Victim->Object.Library.Export == NULL)
1073  {
1074  pExport = IntWinUmCacheGetExportFromRange(Victim->Object.Library.WinMod, startGva, 0x20);
1075  }
1076  else
1077  {
1078  pExport = Victim->Object.Library.Export;
1079  }
1080 
1081  if (pExport != NULL)
1082  {
1083  ret = snprintf(l, rem, ", Exports (%u) : [", pExport->NumberOfOffsets);
1084 
1085  if (ret < 0 || ret >= rem)
1086  {
1087  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1088  }
1089  else
1090  {
1091  rem -= ret;
1092  l += ret;
1093  }
1094 
1095  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
1096  {
1097  if (export == pExport->NumberOfOffsets - 1)
1098  {
1099  ret = snprintf(l, rem, "'%s'", pExport->Names[export]);
1100  }
1101  else
1102  {
1103  ret = snprintf(l, rem, "'%s',", pExport->Names[export]);
1104  }
1105 
1106  if (ret < 0 || ret >= rem)
1107  {
1108  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1109  }
1110  else
1111  {
1112  rem -= ret;
1113  l += ret;
1114  }
1115  }
1116 
1117  ret = snprintf(l, rem, "], Delta: +%02x, ",
1118  (DWORD)(Victim->Ept.Gva - Victim->Object.Library.WinMod->VirtualBase - pExport->Rva));
1119 
1120  if (ret < 0 || ret >= rem)
1121  {
1122  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1123  }
1124  else
1125  {
1126  rem -= ret;
1127  l += ret;
1128  }
1129  }
1130 
1131  LOG("%s\n", gExcLogLine);
1132  }
1133  }
1134  else if (Victim->ZoneType == exceptionZonePc)
1135  {
1136  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Victim->Object.WinProc->ParentEprocess);
1137 
1138  ret = IntExceptPrintWinProcInfo(Victim->Object.WinProc, "Victim -> Process: ", l, rem, 14);
1139  rem -= ret;
1140  l += ret;
1141 
1142  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
1143  rem -= ret;
1144  l += ret;
1145 
1146  LOG("%s\n", gExcLogLine);
1147  }
1148  else if (Victim->Object.Type == introObjectTypeUmModule)
1149  {
1150  WINUM_CACHE_EXPORT *pExport = NULL;
1151 
1152  ret = IntExceptPrintWinModInfo(Victim->Object.Library.WinMod,
1153  "Victim -> Module: ",
1154  l,
1155  rem,
1156  modNameAlignment);
1157  if (ret < 0 || ret >= rem)
1158  {
1159  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1160  }
1161  else
1162  {
1163  rem -= ret;
1164  l += ret;
1165  }
1166 
1167 
1168  if (Victim->Object.Library.Export == NULL)
1169  {
1170  pExport = IntWinUmCacheGetExportFromRange(Victim->Object.Library.WinMod, Victim->Ept.Gva, 0x20);
1171  }
1172  else
1173  {
1174  pExport = Victim->Object.Library.Export;
1175  }
1176 
1177  if (pExport != NULL)
1178  {
1179  ret = snprintf(l, rem, ", Exports (%u) : [", pExport->NumberOfOffsets);
1180 
1181  if (ret < 0 || ret >= rem)
1182  {
1183  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1184  }
1185  else
1186  {
1187  rem -= ret;
1188  l += ret;
1189  }
1190 
1191  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
1192  {
1193  if (export == pExport->NumberOfOffsets - 1)
1194  {
1195  ret = snprintf(l, rem, "'%s'", pExport->Names[export]);
1196  }
1197  else
1198  {
1199  ret = snprintf(l, rem, "'%s',", pExport->Names[export]);
1200  }
1201 
1202  if (ret < 0 || ret >= rem)
1203  {
1204  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1205  }
1206  else
1207  {
1208  rem -= ret;
1209  l += ret;
1210  }
1211 
1212  }
1213 
1214  ret = snprintf(l, rem, "], Delta: +%02x, ",
1215  (DWORD)(Victim->Ept.Gva - Victim->Object.Library.WinMod->VirtualBase - pExport->Rva));
1216 
1217  if (ret < 0 || ret >= rem)
1218  {
1219  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1220  }
1221  else
1222  {
1223  rem -= ret;
1224  l += ret;
1225  }
1226  }
1227 
1228  ret = snprintf(l, rem, ", Address: (%0*llx, %0*llx)",
1229  gGuest.WordSize * 2, Victim->Ept.Gva,
1230  gGuest.WordSize * 2, Victim->Ept.Gpa);
1231 
1232  if (ret < 0 || ret >= rem)
1233  {
1234  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1235  }
1236  else
1237  {
1238  rem -= ret;
1239  l += ret;
1240  }
1241 
1242  ret = snprintf(l, rem, ", WriteInfo: (%u, %016llx -> %016llx)",
1243  Victim->WriteInfo.AccessSize,
1244  Victim->WriteInfo.OldValue[0],
1245  Victim->WriteInfo.NewValue[0]);
1246 
1247  if (ret < 0 || ret >= rem)
1248  {
1249  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1250  }
1251  else
1252  {
1253  rem -= ret;
1254  l += ret;
1255  }
1256 
1257  if (Victim->ZoneFlags)
1258  {
1259  ret = snprintf(l, rem, ", Flags:%s%s%s%s%s (0x%llx)",
1260  (Victim->ZoneFlags & ZONE_LIB_IMPORTS) ? " IMPORTS" : "",
1261  (Victim->ZoneFlags & ZONE_LIB_EXPORTS) ? " EXPORTS" : "",
1262  (Victim->ZoneFlags & ZONE_LIB_CODE) ? " CODE" : "",
1263  (Victim->ZoneFlags & ZONE_LIB_DATA) ? " DATA" : "",
1264  (Victim->ZoneFlags & ZONE_LIB_RESOURCES) ? " RSRC" : "",
1265  (unsigned long long)Victim->ZoneFlags);
1266 
1267  if (ret < 0 || ret >= rem)
1268  {
1269  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1270  }
1271  else
1272  {
1273  rem -= ret;
1274  l += ret;
1275  }
1276  }
1277 
1278  LOG("%s\n", gExcLogLine);
1279  }
1280 
1281  if (Action == introGuestNotAllowed)
1282  {
1283  l = gExcLogLine;
1284  rem = sizeof(gExcLogLine);
1285 
1286  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sMALWARE (user-mode) ",
1287  (Victim->Object.WinProc->BetaDetections) ? " (B) " : " ");
1288 
1289  if (ret < 0 || ret >= rem)
1290  {
1291  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1292  }
1293  else
1294  {
1295  rem -= ret;
1296  l += ret;
1297  }
1298 
1299  switch (Reason)
1300  {
1302  ret = snprintf(l, rem, "(no sig)");
1303  break;
1305  ret = snprintf(l, rem, "(no exc)");
1306  break;
1308  ret = snprintf(l, rem, "(extra)");
1309  break;
1311  ret = snprintf(l, rem, "(error)");
1312  break;
1314  ret = snprintf(l, rem, "(value)");
1315  break;
1317  ret = snprintf(l, rem, "(value code)");
1318  break;
1320  ret = snprintf(l, rem, "(export)");
1321  break;
1323  ret = snprintf(l, rem, "(idt)");
1324  break;
1326  ret = snprintf(l, rem, "(version os)");
1327  break;
1329  ret = snprintf(l, rem, "(version intro)");
1330  break;
1332  ret = snprintf(l, rem, "(process creation)");
1333  break;
1334  case introReasonUnknown:
1335  ret = snprintf(l, rem, "(unknown)");
1336  break;
1337  default:
1338  ret = snprintf(l, rem, "(%d)", Reason);
1339  break;
1340  }
1341 
1342  if (ret < 0 || ret >= rem)
1343  {
1344  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1345  }
1346  else
1347  {
1348  rem -= ret;
1349  l += ret;
1350  }
1351 
1352  ret = snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1353 
1354  if (ret < 0 || ret >= rem)
1355  {
1356  ERROR("[ERROR] snprintf error: %d, size %d\n", ret, rem);
1357  }
1358  else
1359  {
1360  rem -= ret;
1361  l += ret;
1362  }
1363 
1364  LOG("%s\n\n", gExcLogLine);
1365  }
1366 
1367  if (Victim->Object.Type == introObjectTypeProcessCreationDpi)
1368  {
1369  if (Originator->PcType == INT_PC_VIOLATION_DPI_DEBUG_FLAG)
1370  {
1371  WIN_PROCESS_OBJECT *pDebugged = Victim->Object.Process;
1372  WIN_PROCESS_OBJECT *pDebugger;
1373 
1375  if (NULL == pDebugger)
1376  {
1377  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) is debugged by process %s!\n",
1378  pDebugged->Name, pDebugged->NameHash, pDebugged->Pid, pDebugged->EprocessAddress, "<unknown>");
1379  }
1380  else
1381  {
1382  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) is debugged by process %s [0x%08x] (%d, 0x%016llx)!\n",
1383  pDebugged->Name, pDebugged->NameHash, pDebugged->Pid, pDebugged->EprocessAddress,
1384  pDebugger->Name, pDebugger->NameHash, pDebugger->Pid, pDebugger->EprocessAddress);
1385  }
1386  }
1387  else if (Originator->PcType == INT_PC_VIOLATION_DPI_PIVOTED_STACK)
1388  {
1389  WIN_PROCESS_OBJECT *pParent = Victim->Object.Process;
1390  WIN_PROCESS_OBJECT *pStarted = Originator->Process;
1391 
1392  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) attempted to start process %s [0x%08x] "
1393  "(%d, 0x%016llx) with a pivoted stack!\n",
1394  pParent->Name, pParent->NameHash, pParent->Pid, pParent->EprocessAddress,
1395  pStarted->Name, pStarted->NameHash, pStarted->Pid, pStarted->EprocessAddress);
1396 
1397  LOG("[DPI] Current stack 0x%016llx [base 0x%016llx, limit 0x%016llx], wow64 "
1398  "stack 0x%016llx [base 0x%016llx, limit 0x%016llx]\n",
1405 
1406  if (gGuest.Guest64)
1407  {
1408  KTRAP_FRAME64 *trapFrame = NULL;
1409  INTSTATUS status;
1410 
1412  sizeof(*trapFrame),
1414  0,
1415  &trapFrame);
1416 
1417  if (!INT_SUCCESS(status))
1418  {
1419  ERROR("[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n",
1421  status);
1422 
1423  goto _skip_trap_frame;
1424  }
1425 
1426  IntDumpWinTrapFrame64(trapFrame);
1427 
1428  IntVirtMemUnmap(&trapFrame);
1429  }
1430  else
1431  {
1432  KTRAP_FRAME32 *trapFrame = NULL;
1433  INTSTATUS status;
1434 
1436  sizeof(*trapFrame),
1438  0,
1439  &trapFrame);
1440 
1441  if (!INT_SUCCESS(status))
1442  {
1443  ERROR("[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n",
1445  status);
1446 
1447  goto _skip_trap_frame;
1448  }
1449 
1450  IntDumpWinTrapFrame32(trapFrame);
1451 
1452  IntVirtMemUnmap(&trapFrame);
1453  }
1454 
1455 _skip_trap_frame:
1456  ;
1457  }
1458  else if (Originator->PcType == INT_PC_VIOLATION_DPI_STOLEN_TOKEN)
1459  {
1460  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1461  WIN_PROCESS_OBJECT *pStolenFrom =
1463 
1464  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started with "
1465  "a stolen token from %s [0x%08x] (%d, 0x%016llx)!\n",
1466  pOriginator->Name, pOriginator->NameHash, pOriginator->Pid, pOriginator->EprocessAddress,
1467  pStolenFrom->Name, pStolenFrom->NameHash, pStolenFrom->Pid, pStolenFrom->EprocessAddress);
1468  }
1469  else if (Originator->PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
1470  {
1471  WIN_PROCESS_OBJECT *pHeapSprayed = Victim->Object.Process;
1472  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1473  WORD maxNumberOfHeapVals = 0;
1474  DWORD detectedPage = 0, maxPageHeapVals = 0;
1475 
1476  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s "
1477  "[0x%08x] (%d, 0x%016llx) after it has been heap sprayed! (shell code flags: 0x%016llx)\n",
1478  pOriginator->Name,
1479  pOriginator->NameHash,
1480  pOriginator->Pid,
1481  pOriginator->EprocessAddress,
1482  pHeapSprayed->Name,
1483  pHeapSprayed->NameHash,
1484  pHeapSprayed->Pid,
1485  pHeapSprayed->EprocessAddress,
1487 
1488  for (DWORD val = 1; val <= HEAP_SPRAY_NR_PAGES; val++)
1489  {
1490  DWORD checkedPage = ((val << 24) | (val << 16) | (val << 8) | val) & PAGE_MASK;
1491 
1492  LOG("[DPI] For page 0x%08x, %s %s %s (offset 0x%03x), number of heap values: %d\n",
1493  checkedPage,
1494  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped ?
1495  "was mapped" : "was not mapped",
1496  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected ?
1497  "was detected" : "was not detected",
1498  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable ?
1499  "executable" : "not executable",
1500  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset,
1501  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount);
1502 
1503  if (pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
1504  {
1505  detectedPage = checkedPage;
1506  }
1507 
1508  // Use >= so that we are sure that we will get at least one page even if there are no heap values.
1509  if (pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount
1510  >= maxNumberOfHeapVals &&
1511  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
1512  {
1513  maxNumberOfHeapVals =
1514  (WORD)pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1515  maxPageHeapVals = checkedPage;
1516  }
1517  }
1518 
1519  LOG("[INFO] Page detected: 0x%08x, maximum number of heap values: 0x%08x (%d)\n",
1520  detectedPage, maxPageHeapVals, maxNumberOfHeapVals);
1521 
1522  // At this point we might not have a detected page, but only pages that exceed the max heap values
1523  // heuristic, so don't bother to dump it if it is equal to zero.
1524  if (0 != detectedPage)
1525  {
1526  LOG("[INFO] Dumping page: 0x%08x...\n", detectedPage);
1527 
1528  IntDumpGva(detectedPage, PAGE_SIZE, pHeapSprayed->Cr3);
1529  }
1530 
1531  if (detectedPage != maxPageHeapVals)
1532  {
1533  LOG("[INFO] Dumping page: 0x%08x...\n", maxPageHeapVals);
1534 
1535  IntDumpGva(maxPageHeapVals, PAGE_SIZE, pHeapSprayed->Cr3);
1536  }
1537  }
1538  else if (Originator->PcType == INT_PC_VIOLATION_DPI_TOKEN_PRIVS)
1539  {
1540  WIN_PROCESS_OBJECT *pVictim = Victim->Object.Process;
1541  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1542 
1543  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s [0x%08x] (%d, 0x%016llx) "
1544  "after it didn't pass privileges checks!\n",
1545  pOriginator->Name,
1546  pOriginator->NameHash,
1547  pOriginator->Pid,
1548  pOriginator->EprocessAddress,
1549  pVictim->Name,
1550  pVictim->NameHash,
1551  pVictim->Pid,
1552  pVictim->EprocessAddress);
1553 
1554  LOG("[DPI] Privileges: Enabled: old: 0x%016llx, new: 0x%016llx, Present: old: 0x%016llx, new: 0x%016llx\n",
1559  }
1560  else if (Originator->PcType == INT_PC_VIOLATION_DPI_THREAD_START)
1561  {
1562  WIN_PROCESS_OBJECT *pVictim = Victim->Object.Process;
1563  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1564 
1565  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s "
1566  "[0x%08x] (%d, 0x%016llx) from a thread considered suspicious (start 0x%016llx, shellcode flags: 0x%016llx)!\n",
1567  pOriginator->Name,
1568  pOriginator->NameHash,
1569  pOriginator->Pid,
1570  pOriginator->EprocessAddress,
1571  pVictim->Name,
1572  pVictim->NameHash,
1573  pVictim->Pid,
1574  pVictim->EprocessAddress,
1577 
1579  PAGE_SIZE,
1580  pVictim->Cr3);
1581  }
1582  else if (Originator->PcType == INT_PC_VIOLATION_DPI_SEC_DESC ||
1583  Originator->PcType == INT_PC_VIOLATION_DPI_ACL_EDIT)
1584  {
1585  WIN_PROCESS_OBJECT *pVictim = Victim->Object.Process;
1586  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1589 
1590  if (Originator->PcType == INT_PC_VIOLATION_DPI_SEC_DESC)
1591  {
1592  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) was created by %s [0x%08x] (%d, 0x%016llx) "
1593  "using an altered SD (stolen from process %s [0x%08x] (%d, 0x%016llx))\n",
1594  pOriginator->Name,
1595  pOriginator->NameHash,
1596  pOriginator->Pid,
1597  pOriginator->EprocessAddress,
1598  pVictim->Name,
1599  pVictim->NameHash,
1600  pVictim->Pid,
1601  pVictim->EprocessAddress,
1602  pStolenFrom ? pStolenFrom->Name : "NULL",
1603  pStolenFrom ? pStolenFrom->NameHash : 0,
1604  pStolenFrom ? pStolenFrom->Pid : 0,
1605  pStolenFrom ? pStolenFrom->EprocessAddress : 0);
1606  }
1607  else
1608  {
1609  LOG("[DPI] SACL/DACL for process 0x%llx (%d / %s) have been modified\n",
1610  pVictim->EprocessAddress, pVictim->Pid, pVictim->Name);
1611  }
1612 
1613  // By having a different security descriptor pointer, the contents will almost certainly be different.
1614  LOG("[DPI] Old SACL AclSize:0x%x, AceCount:0x%x, AclRevision:0x%x "
1615  "New SACL AclSize:0x%x, AceCount:0x%x, AclRevision:0x%x "
1616  "Old DACL AclSize:0x%x, AceCount:0x%x, AclRevision:0x%x "
1617  "New DACL AclSize:0x%x, AceCount:0x%x, AclRevision:0x%x\n",
1630  }
1631  else
1632  {
1633  ERROR("[ERROR] Victim has type introObjectTypeProcessCreationDpi but no known flag was given, "
1634  "flags: 0x%x\n", Originator->PcType);
1635  }
1636  }
1637 }
1638 
1639 
1640 static __inline BOOLEAN
1642  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1643  _In_ DWORD ZoneFlags
1644  )
1653 {
1654  BOOLEAN match = FALSE;
1655 
1656  if ((ZoneFlags & EXCEPTION_FLG_READ) &&
1657  (Victim->ZoneFlags & ZONE_READ))
1658  {
1659  match = TRUE;
1660  }
1661 
1662  if ((ZoneFlags & EXCEPTION_FLG_EXECUTE) &&
1663  (Victim->ZoneFlags & ZONE_EXECUTE))
1664  {
1665  match = TRUE;
1666  }
1667 
1668  if ((ZoneFlags & EXCEPTION_FLG_WRITE) &&
1669  (Victim->ZoneFlags & ZONE_WRITE))
1670  {
1671  match = TRUE;
1672  }
1673 
1674  return match;
1675 }
1676 
1677 
1678 
1679 static __inline BOOLEAN
1681  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1682  _In_ UM_EXCEPTION_OBJECT ZoneType
1683  )
1692 {
1693  BOOLEAN match = FALSE;
1694 
1695  switch (ZoneType)
1696  {
1697  case umObjAny:
1698  match = TRUE;
1699  break;
1700 
1701  // We want to match only object_type process, not thread-context, thread-apc or instrument.
1702  case umObjProcess:
1703  if (Victim->ZoneType == exceptionZoneProcess &&
1704  (Victim->ZoneFlags & (ZONE_PROC_THREAD_CTX | ZONE_PROC_THREAD_APC | ZONE_PROC_INSTRUMENT)) == 0)
1705  {
1706  match = TRUE;
1707  }
1708  break;
1709 
1710  case umObjModule:
1711  if (Victim->Object.Type == introObjectTypeUmModule)
1712  {
1713  match = TRUE;
1714  }
1715  break;
1716 
1717  case umObjModuleImports:
1718  if ((Victim->Object.Type == introObjectTypeUmModule) &&
1719  (Victim->ZoneFlags & ZONE_LIB_IMPORTS))
1720  {
1721  match = TRUE;
1722  }
1723  break;
1724 
1725  case umObjNxZone:
1726  if (Victim->Object.Type == introObjectTypeUmGenericNxZone)
1727  {
1728  match = TRUE;
1729  }
1730  break;
1731 
1732  case umObjSharedUserData:
1733  if (Victim->Object.Type == introObjectTypeSudExec)
1734  {
1735  match = TRUE;
1736  }
1737  break;
1738 
1739  case umObjModuleExports:
1740  if ((Victim->Object.Type == introObjectTypeUmModule) &&
1741  (Victim->ZoneFlags & ZONE_LIB_EXPORTS))
1742  {
1743  match = TRUE;
1744  }
1745  break;
1746 
1748  if ((Victim->ZoneType == exceptionZoneProcess) &&
1749  (Victim->ZoneFlags & ZONE_PROC_THREAD_CTX))
1750  {
1751  match = TRUE;
1752  }
1753  break;
1754 
1755  case umObjProcessApcThread:
1756  if ((Victim->ZoneType == exceptionZoneProcess) &&
1757  (Victim->ZoneFlags & ZONE_PROC_THREAD_APC))
1758  {
1759  match = TRUE;
1760  }
1761  break;
1762 
1764  if ((Victim->ZoneType == exceptionZoneProcess) &&
1765  (Victim->ZoneFlags & ZONE_PROC_INSTRUMENT))
1766  {
1767  match = TRUE;
1768  }
1769  break;
1770 
1771  case umObjProcessPeb32:
1772  if (Victim->Injection.Gva >= Victim->Object.WinProc->Peb32Address &&
1773  Victim->Injection.Gva < Victim->Object.WinProc->Peb32Address + WIN_UM_FIELD(Peb, 32Size))
1774  {
1775  match = TRUE;
1776  }
1777  break;
1778 
1779  case umObjProcessPeb64:
1780  if (Victim->Injection.Gva >= Victim->Object.WinProc->Peb64Address &&
1781  Victim->Injection.Gva < Victim->Object.WinProc->Peb64Address + WIN_UM_FIELD(Peb, 64Size))
1782  {
1783  match = TRUE;
1784  }
1785  break;
1786 
1787  case umObjProcessCreation:
1788  if (Victim->Object.Type == introObjectTypeProcessCreation &&
1789  Victim->ZoneType == exceptionZonePc)
1790  {
1791  match = TRUE;
1792  }
1793  break;
1794 
1796  if (Victim->Object.Type == introObjectTypeProcessCreationDpi &&
1797  Victim->ZoneType == exceptionZonePc)
1798  {
1799  match = TRUE;
1800  }
1801  break;
1802 
1803  case umObjModuleLoad:
1804  if ((Victim->ZoneType == exceptionZoneProcess) &&
1805  (Victim->ZoneFlags & ZONE_MODULE_LOAD))
1806  {
1807  match = TRUE;
1808  }
1809  break;
1810 
1811  default:
1812  LOG("[ERROR] This is a corruption in the update/exception. Type = %d!\n", ZoneType);
1813  break;
1814  }
1815 
1816  return match;
1817 }
1818 
1819 
1820 static __inline BOOLEAN
1822  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1823  _In_ DWORD ExceptionFlags
1824  )
1833 {
1834  BOOLEAN match = FALSE;
1835 
1836  if ((ExceptionFlags & EXCEPTION_FLG_32) &&
1837  (ExceptionFlags & EXCEPTION_FLG_64))
1838  {
1839  match = TRUE;
1840  }
1841  else
1842  {
1844  {
1845  if (ExceptionFlags & EXCEPTION_FLG_32)
1846  {
1847  // 32-bit windows OR a 32-bit process in a 64-bit system
1848  match = !gGuest.Guest64 || Originator->WinProc->Wow64Process;
1849  }
1850  else if (ExceptionFlags & EXCEPTION_FLG_64)
1851  {
1852  // 64-bit windows AND a 64-bit process
1853  match = gGuest.Guest64 && !Originator->WinProc->Wow64Process;
1854  }
1855  }
1856  else if (gGuest.OSType == introGuestLinux)
1857  {
1858  // Only Linux don't check the process subsystem
1859  if (ExceptionFlags & EXCEPTION_FLG_32)
1860  {
1861  match = !gGuest.Guest64;
1862  }
1863  else if (ExceptionFlags & EXCEPTION_FLG_64)
1864  {
1865  match = gGuest.Guest64;
1866  }
1867  }
1868  }
1869 
1870  return match;
1871 }
1872 
1873 
1874 
1875 static __inline BOOLEAN
1877  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1878  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1879  _In_ DWORD ExceptionFlags
1880  )
1890 {
1891  BOOLEAN match = TRUE;
1892 
1893  if ((Victim->ZoneType == exceptionZoneProcess || Victim->ZoneType == exceptionZonePc) &&
1894  (ExceptionFlags & EXCEPTION_UM_FLG_CHILD_PROC))
1895  {
1897  {
1898  if (Victim->Object.WinProc->ParentEprocess != Originator->WinProc->EprocessAddress)
1899  {
1900  return FALSE;
1901  }
1902  }
1903  else
1904  {
1905  if (Victim->Object.LixProc->ActualParent != Originator->LixProc->Gva)
1906  {
1907  return FALSE;
1908  }
1909  }
1910  }
1911 
1912  return match;
1913 }
1914 
1915 
1916 
1917 static __inline BOOLEAN
1919  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1920  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1921  _In_ DWORD ExceptionFlags
1922  )
1935 {
1936  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_SYS_PROC))
1937  {
1938  //
1939  // This exception only matches if the originator process is a system process
1940  //
1941  if (Victim->Object.Type == introObjectTypeProcessCreation)
1942  {
1943  if (!Victim->Object.WinProc->SystemProcess)
1944  {
1945  return FALSE;
1946  }
1947  }
1948  else
1949  {
1950  if (!Originator->WinProc->SystemProcess)
1951  {
1952  return FALSE;
1953  }
1954  }
1955  }
1956 
1957  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_LIKE_APPHELP))
1958  {
1959  if ((Victim->Object.WinProc->InjectedApphelpAddress != Victim->Injection.Gva) ||
1960  (Victim->Object.WinProc->InjectedAppHelpSize != Victim->Injection.Length))
1961  {
1962  return FALSE;
1963  }
1964  }
1965 
1966  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_ONETIME))
1967  {
1968  if (Victim->Object.Type == introObjectTypeProcessCreation)
1969  {
1970  if (Originator->WinProc->OneTimeInjectionDone)
1971  {
1972  return FALSE;
1973  }
1974  else
1975  {
1976  Originator->WinProc->OneTimeInjectionDone = TRUE;
1977  }
1978  }
1979  else
1980  {
1981  if (Victim->Object.WinProc->OneTimeInjectionDone)
1982  {
1983  return FALSE;
1984  }
1985  else
1986  {
1987  Victim->Object.WinProc->OneTimeInjectionDone = TRUE;
1988  }
1989  }
1990  }
1991 
1992  return TRUE;
1993 }
1994 
1995 
1996 static __inline BOOLEAN
1998  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1999  _In_ UM_EXCEPTION_GLOB *Exception
2000  )
2009 {
2010  BOOLEAN match = FALSE;
2011 
2012  if (Victim->ZoneFlags & (ZONE_LIB_CODE | ZONE_LIB_EXPORTS | ZONE_LIB_IMPORTS | ZONE_LIB_DATA))
2013  {
2014  // We use WCHAR for module names
2015  match = glob_match_utf16(Exception->Victim.NameGlob, Victim->Object.NameWide, TRUE, TRUE);
2016  }
2017  else
2018  {
2019  match = glob_match_utf8(Exception->Victim.NameGlob, Victim->Object.Name, TRUE, TRUE);
2020  }
2021 
2022  return match;
2023 }
2024 
2025 
2026 static __inline BOOLEAN
2028  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2029  _In_ UM_EXCEPTION_GLOB *Exception
2030  )
2040 {
2041  BOOLEAN match = FALSE;
2042 
2044  {
2045  match = glob_match_utf8(Exception->Victim.ProcessGlob, Originator->WinProc->Name, TRUE, TRUE);
2046  }
2047  else if (Originator->LixProc->Path)
2048  {
2049  match = glob_match_utf8(Exception->Victim.ProcessGlob, Originator->LixProc->Path->Name, TRUE, TRUE);
2050  }
2051 
2052  return match;
2053 }
2054 
2055 
2056 
2057 static __inline BOOLEAN
2059  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2060  _In_ UM_EXCEPTION *Exception
2061  )
2070 {
2071  return (Exception->Victim.NameHash == umExcNameAny ||
2072  Exception->Victim.NameHash == Victim->Object.NameHash);
2073 }
2074 
2075 
2076 static __inline BOOLEAN
2078  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2079  _In_ UM_EXCEPTION *Exception
2080  )
2090 {
2091  BOOLEAN match = FALSE;
2092 
2093  if (Exception->Victim.ProcessHash == umExcNameAny)
2094  {
2095  match = TRUE;
2096  }
2097  else
2098  {
2100  {
2101  match = Exception->Victim.ProcessHash == Originator->WinProc->NameHash;
2102  }
2103  else
2104  {
2105  match = Exception->Victim.ProcessHash == Originator->LixProc->CommHash;
2106  }
2107  }
2108 
2109  return match;
2110 }
2111 
2112 
2113 
2114 static __forceinline BOOLEAN
2116  _In_ char Item
2117  )
2125 {
2126  return ((Item == '*') || (Item == '?') || (Item == ']') || (Item == '[') || (Item == '/'));
2127 }
2128 
2129 
2130 void
2132  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2133  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2134  _In_ INTRO_ACTION Action,
2135  _In_ INTRO_ACTION_REASON Reason
2136  )
2145 {
2146  if ((introGuestNotAllowed != Action) && (introReasonAllowedFeedback != Reason))
2147  {
2148  return;
2149  }
2150 
2151  if (Victim->Object.Type == introObjectTypeUmGenericNxZone && gVcpu->Regs.Cr3 != Victim->Object.WinProc->Cr3)
2152  {
2153  return;
2154  }
2155 
2157  {
2158  IntExceptUserLogWindowsInformation(Victim, Originator, Action, Reason);
2159  }
2160  else if (gGuest.OSType == introGuestLinux)
2161  {
2162  IntExceptUserLogLinuxInformation(Victim, Originator, Action, Reason);
2163  }
2164 
2165  if ((Victim->Object.Type == introObjectTypeUmModule) ||
2166  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
2167  (Victim->Object.Type == introObjectTypeSudExec))
2168  {
2169  IntExceptDumpSignatures(Originator, Victim, FALSE, FALSE);
2170  }
2171 
2172  BOOLEAN logInjection = (Victim->ZoneType == exceptionZoneProcess);
2173 
2174  // Don't dump lsass reads (we don't want our log to be mimikatz)
2175  if (logInjection && gGuest.OSType == introGuestWindows)
2176  {
2177  if (Victim->Object.WinProc->Lsass && (Victim->ZoneFlags & ZONE_READ))
2178  {
2179  logInjection = FALSE;
2180  }
2181  }
2182 
2183  if (logInjection && Originator->Process)
2184  {
2185  QWORD cr3 = 0;
2186 
2188  {
2189  cr3 = Originator->WinProc->Cr3;
2190  }
2191  else if (gGuest.OSType == introGuestLinux)
2192  {
2193  cr3 = Originator->LixProc->Cr3;
2194  }
2195 
2196  // If we could read the whole buffer when checking for value signatures, dump that
2197  if (Victim->Injection.Buffer &&
2198  Victim->Injection.BufferSize == Victim->Injection.Length)
2199  {
2200  IntDumpBuffer(Victim->Injection.Buffer,
2201  Originator->SourceVA,
2202  Victim->Injection.BufferSize,
2203  16,
2204  sizeof(BYTE),
2205  TRUE,
2206  TRUE);
2207  }
2208  else if ((Victim->ZoneFlags &
2210  {
2211  IntDumpGva(Originator->SourceVA,
2212  Victim->Injection.Length,
2213  cr3);
2214  }
2215  }
2216 }
2217 
2218 
2219 INTSTATUS
2221  _In_ void *Process,
2222  _Out_ EXCEPTION_UM_ORIGINATOR *Originator
2223  )
2232 {
2233  STACK_TRACE stack;
2234  STACK_ELEMENT stackElements[8];
2235 
2236  Originator->Process = Process;
2237  Originator->Library = NULL;
2238  Originator->Rip = gVcpu->Regs.Rip;
2239  Originator->Execute = TRUE;
2240  Originator->NameHash = INITIAL_CRC_VALUE; // The code is executed from the heap
2241 
2243  {
2244  INTSTATUS status;
2245 
2246  memzero(&stack, sizeof(stack));
2247  stack.Traces = stackElements;
2248 
2249  status = IntWinStackTraceGetUser(&gVcpu->Regs, Process, ARRAYSIZE(stackElements), &stack);
2250  if (!INT_SUCCESS(status) && 0 == stack.NumberOfTraces)
2251  {
2252  WARNING("[WARNING] IntWinStackTraceGetUser failed: %08x\n", status);
2253  }
2254 
2255  if (stack.NumberOfTraces > 0)
2256  {
2257  Originator->Return.Rip = stack.Traces[0].ReturnAddress;
2258  Originator->Return.Library = stack.Traces[0].ReturnModule;
2259  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->NameHash;
2260  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->Name;
2261  }
2262  }
2263 
2264  Originator->Instruction = &gVcpu->Instruction;
2265 
2266  return INT_STATUS_SUCCESS;
2267 }
2268 
2269 
2270 static INTSTATUS
2272  _In_ WIN_PROCESS_OBJECT *Process,
2273  _In_opt_ WIN_PROCESS_MODULE *Module,
2274  _Inout_ EXCEPTION_UM_ORIGINATOR *Originator
2275  )
2291 {
2292  INTSTATUS status;
2293  STACK_ELEMENT stackElements[8];
2294  STACK_TRACE stack;
2295  BOOLEAN isUcrtbase = FALSE;
2296 
2297  if (NULL == Module)
2298  {
2299  goto _get_stack;
2300  }
2301 
2302 #define MEMORY_FUNC_SIZE 0x400
2303 
2304  isUcrtbase = 0 == wstrcasecmp(Module->Path->Name, u"ucrtbase.dll");
2305 
2306  if (Module->Path->NameHash == NAMEHASH_NTDLL)
2307  {
2308  DWORD rva = (DWORD)(Originator->Rip - Module->VirtualBase);
2309  BOOLEAN foundMemFunc = FALSE;
2310 
2311  if (NULL == Module->Cache || !Module->Cache->MemoryFuncsRead)
2312  {
2314  }
2315 
2316  for (DWORD i = 0; i < ARRAYSIZE(Module->Cache->MemFuncs.FuncArray); i++)
2317  {
2318  if (0 == Module->Cache->MemFuncs.FuncArray[i])
2319  {
2320  continue;
2321  }
2322 
2323  if (rva > Module->Cache->MemFuncs.FuncArray[i] &&
2324  rva < Module->Cache->MemFuncs.FuncArray[i] + MEMORY_FUNC_SIZE)
2325  {
2326  foundMemFunc = TRUE;
2327  }
2328  }
2329 
2330  if (!foundMemFunc)
2331  {
2333  }
2334  }
2335  // Note: here we want to match "the first N bytes", not to match the whole module
2336  else if (((Module->Path->NameSize < 10 || 0 != memcmp(Module->Path->Name, u"msvcr", 10)) &&
2337  (Module->Path->NameSize < 18 || 0 != memcmp(Module->Path->Name, u"vcruntime", 18))) &&
2338  !isUcrtbase)
2339  {
2341  }
2342 
2343 _get_stack:
2344  memzero(&stack, sizeof(stack));
2345  stack.Traces = stackElements;
2346 
2347  status = IntWinStackTraceGetUser(&gVcpu->Regs,
2348  Process,
2349  ARRAYSIZE(stackElements),
2350  &stack);
2351  if (!INT_SUCCESS(status) &&
2352  stack.NumberOfTraces == 0)
2353  {
2354  // Don't log an error if we are checking an invalid originator or if the stack is swapped out.
2355  // For the first case it is very possible we wouldn't find anything anyway, and for the second case,
2356  // we'll handle this case by injecting a #PF and retrying if needed, on returning from this function.
2357  // Note that, in case we found at least a trace, we would not bother with the stack swapped out
2358  // case, as the information gathered should be enough for the exception mechanism to work properly.
2359  if (Module != NULL && status != INT_STATUS_STACK_SWAPPED_OUT)
2360  {
2361  ERROR("[ERROR] IntWinStackTraceGetUser failed: %08x\n", status);
2362  }
2363 
2364  return status;
2365  }
2366 
2367  if (stack.Bits64 && !isUcrtbase && !Process->ExploitGuardEnabled)
2368  {
2369  // On 64-bit we can only trust the first return
2370  if (stack.Traces[0].ReturnModule == Module)
2371  {
2372  return INT_STATUS_SUCCESS;
2373  }
2374 
2375  Originator->Return.Rip = stack.Traces[0].ReturnAddress;
2376  Originator->Return.Library = stack.Traces[0].ReturnModule;
2377  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->NameHash;
2378 
2379  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->Name;
2380 
2381  return INT_STATUS_SUCCESS;
2382  }
2383 
2384  // Dirty little hack for Exploit Guard. Some hooks are set by payloadrestrictions.dll using ucrtbase!memset
2385  // In these cases we can see other modules on the stack, besides payloadrestrictions.dll so first we search for it
2386  // and if that fails, we go with the first module we found
2387  if (isUcrtbase && Process->ExploitGuardEnabled)
2388  {
2389  for (DWORD i = 0; i < stack.NumberOfTraces; i++)
2390  {
2392 
2393  if (stack.Traces[i].ReturnModule == Module)
2394  {
2395  continue;
2396  }
2397 
2398  if (wstrcasecmp(pModule->Path->Name, u"payloadrestrictions.dll"))
2399  {
2400  continue;
2401  }
2402 
2403  Originator->Return.Rip = stack.Traces[i].ReturnAddress;
2404  Originator->Return.Library = pModule;
2405  Originator->Return.NameHash = pModule->Path->NameHash;
2406  Originator->Return.NameWide = pModule->Path->Name; // Module names are saved as WCHAR
2407 
2408  return INT_STATUS_SUCCESS;
2409  }
2410  }
2411 
2412  for (DWORD i = 0; i < stack.NumberOfTraces; i++)
2413  {
2414  // NOTE: Only on msvcr* it's relevant like this. On ntdll we must be able to know memcpy*, memset*, memmov*.
2415  if (stack.Traces[i].ReturnModule == Module)
2416  {
2417  continue;
2418  }
2419 
2420  Originator->Return.Rip = stack.Traces[i].ReturnAddress;
2421  Originator->Return.Library = stack.Traces[i].ReturnModule;
2422  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[i].ReturnModule)->Path->NameHash;
2423  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[i].ReturnModule)->Path->Name;
2424 
2425  break;
2426  }
2427 
2428  return INT_STATUS_SUCCESS;
2429 
2430 #undef MEMORY_FUNC_SIZE
2431 }
2432 
2433 
2434 INTSTATUS
2436  _In_ void *Process,
2437  _In_ BOOLEAN ModuleWrite,
2438  _In_ QWORD Address,
2439  _In_opt_ INSTRUX *Instrux,
2440  _Out_ EXCEPTION_UM_ORIGINATOR *Originator
2441  )
2455 {
2456  if (NULL == Process)
2457  {
2459  }
2460 
2461  if (NULL == Originator)
2462  {
2464  }
2465 
2466  Originator->Process = Process;
2467  Originator->Library = NULL;
2468  Originator->Execute = FALSE;
2469 
2470  if (ModuleWrite && gGuest.OSType == introGuestWindows)
2471  {
2472  INTSTATUS status;
2473  WIN_PROCESS_MODULE *pMod = IntWinUmModFindByAddress(Process, Address);
2474 
2475  Originator->Rip = Address;
2476  Originator->Instruction = Instrux;
2477 
2478  Originator->Library = pMod;
2479  if (NULL != Originator->Library)
2480  {
2481  Originator->NameHash = Originator->WinLib->Path->NameHash;
2482  Originator->NameWide = Originator->WinLib->Path->Name;
2483  }
2484  else
2485  {
2486  Originator->NameHash = INITIAL_CRC_VALUE;
2487  Originator->Name = NULL;
2488  }
2489 
2490  status = IntExceptUserHandleMemoryFunctions(Process, pMod, Originator);
2491  if (!INT_SUCCESS(status))
2492  {
2493  WARNING("[WARNING] IntExceptUserHandleMemoryFunctions failed: %08x\n", status);
2494 
2495  // Propagate the INT_STATUS_STACK_SWAPPED_OUT status so that the caller would handle it
2496  // properly by injecting #PF on the stack and retrying the instruction if needed.
2497  if (status == INT_STATUS_STACK_SWAPPED_OUT)
2498  {
2499  return status;
2500  }
2501  }
2502  }
2503  else if (ModuleWrite && gGuest.OSType == introGuestLinux)
2504  {
2505  Originator->Rip = Address;
2506  Originator->Instruction = Instrux;
2507 
2508  Originator->NameHash = INITIAL_CRC_VALUE;
2509  Originator->Name = NULL;
2510  }
2511  else if (!ModuleWrite)
2512  {
2513  Originator->SourceVA = Address;
2514 
2516  {
2517  Originator->NameHash = ((WIN_PROCESS_OBJECT *)Process)->NameHash;
2518  Originator->Name = ((WIN_PROCESS_OBJECT *)Process)->Name; // Process names are saved as char
2519  }
2520  else if (gGuest.OSType == introGuestLinux)
2521  {
2522  Originator->NameHash = ((LIX_TASK_OBJECT *)Process)->CommHash;
2523  Originator->Name = ((LIX_TASK_OBJECT *)Process)->Comm; // Linux uses only char
2524  }
2525  }
2526 
2527  return INT_STATUS_SUCCESS;
2528 }
2529 
2530 
2531 INTSTATUS
2533  _In_ void *Process,
2534  _In_ INTRO_OBJECT_TYPE ObjectType,
2536  )
2550 {
2551  if (Process == NULL)
2552  {
2554  }
2555 
2556  if (ObjectType != introObjectTypeProcessCreation && ObjectType != introObjectTypeProcessCreationDpi)
2557  {
2559  }
2560 
2561  if (Victim == NULL)
2562  {
2564  }
2565 
2566  Victim->Object.Type = ObjectType;
2567  Victim->Object.Process = Process;
2568 
2569  Victim->ZoneFlags = ZONE_EXECUTE;
2570  Victim->ZoneType = exceptionZonePc;
2571 
2573  {
2574  WIN_PROCESS_OBJECT *pProcess = (WIN_PROCESS_OBJECT *)(Process);
2575 
2576  Victim->Object.BaseAddress = pProcess->Cr3;
2577  Victim->Object.NameHash = pProcess->NameHash;
2578  Victim->Object.Name = pProcess->Name;
2579  }
2580  else if (gGuest.OSType == introGuestLinux)
2581  {
2582  LIX_TASK_OBJECT *pTask = (LIX_TASK_OBJECT *)(Process);
2583 
2584  Victim->Object.BaseAddress = pTask->Cr3;
2585  Victim->Object.NameHash = pTask->CommHash;
2586  Victim->Object.Name = pTask->Comm;
2587  }
2588 
2589  return INT_STATUS_SUCCESS;
2590 }
2591 
2592 
2593 INTSTATUS
2595  _In_ void *Process,
2596  _In_ QWORD DestinationGva,
2597  _In_ DWORD Length,
2598  _In_ QWORD ZoneFlags,
2600  )
2614 {
2615  if (NULL == Process)
2616  {
2618  }
2619 
2620  if (NULL == Victim)
2621  {
2623  }
2624 
2625  Victim->ZoneType = exceptionZoneProcess;
2626 
2627  Victim->ZoneFlags = ZoneFlags;
2628 
2629  Victim->Injection.Gva = DestinationGva;
2630  Victim->Injection.Length = Length;
2631 
2632  Victim->Object.Process = Process;
2633 
2635  {
2636  WIN_PROCESS_OBJECT *pProc = Process;
2637 
2638  Victim->Object.BaseAddress = pProc->Cr3;
2639  Victim->Object.NameHash = pProc->NameHash;
2640  Victim->Object.Name = pProc->Name; // Process names are saved as CHAR
2641 
2642  if (pProc->MonitorVad)
2643  {
2644  Victim->Object.Vad = IntWinVadFindAndUpdateIfNecessary(pProc, DestinationGva, Length);
2645  }
2646 
2647  if (pProc->MonitorModules && (!pProc->MonitorVad || Victim->Object.Vad))
2648  {
2649  WIN_PROCESS_MODULE *pMod = IntWinUmModFindByAddress(pProc, DestinationGva);
2650  Victim->Object.Library.Module = pMod;
2651 
2652  if (pMod != NULL)
2653  {
2654  Victim->Object.Library.Export = IntWinUmCacheGetExportFromRange(pMod, DestinationGva, 0x20);
2655  }
2656  }
2657  }
2658  else if (gGuest.OSType == introGuestLinux)
2659  {
2660  LIX_TASK_OBJECT *pTask = Process;
2661 
2662  Victim->Object.BaseAddress = pTask->Cr3;
2663  Victim->Object.NameHash = pTask->CommHash;
2664  Victim->Object.Name = pTask->Comm; // Linux uses only CHAR
2665  }
2666 
2667  return INT_STATUS_SUCCESS;
2668 }
2669 
2670 
2671 INTSTATUS
2673  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2674  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2675  _In_ UM_EXCEPTION *Exception
2676  )
2687 {
2689  {
2690  if ((Exception->Type == umObjProcess) &&
2691  (Exception->Flags & EXCEPTION_FLG_INIT))
2692  {
2693  return IntWinUmCheckInitializationInjection(Victim, Originator);
2694  }
2695  }
2696 
2698 }
2699 
2700 
2701 INTSTATUS
2703  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2704  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2705  _In_ UM_EXCEPTION_GLOB *Exception
2706  )
2717 {
2719  {
2720  if ((Exception->Type == umObjProcess) &&
2721  (Exception->Flags & EXCEPTION_FLG_INIT))
2722  {
2723  return IntWinUmCheckInitializationInjection(Victim, Originator);
2724  }
2725  }
2726 
2728 }
2729 
2730 
2731 INTSTATUS
2733  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2734  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2735  _In_ void *Exception,
2736  _In_ EXCEPTION_TYPE ExceptionType
2737  )
2759 {
2760  switch (ExceptionType)
2761  {
2762  case exceptionTypeUm:
2763  if (!IntExceptUserMatchZoneFlags(Victim, ((UM_EXCEPTION *)Exception)->Flags))
2764  {
2766  }
2767  break;
2768  case exceptionTypeUmGlob:
2769  if (!IntExceptUserMatchZoneFlags(Victim, ((UM_EXCEPTION_GLOB *)Exception)->Flags))
2770  {
2772  }
2773  break;
2774 
2775  default:
2776  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2777  return INT_STATUS_NOT_SUPPORTED;
2778  }
2779 
2780  switch (ExceptionType)
2781  {
2782  case exceptionTypeUm:
2783  if (!IntExceptUserMatchNameHash(Victim, Exception))
2784  {
2786  }
2787  break;
2788 
2789  case exceptionTypeUmGlob:
2790  if (!IntExceptUserMatchNameGlob(Victim, Exception))
2791  {
2793  }
2794  break;
2795 
2796  default:
2797  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2798  return INT_STATUS_NOT_SUPPORTED;
2799  }
2800 
2801  // Check if we are in the right process. This makes sense only for EPT violations (injections are cross-process,
2802  // so the ProcessHash will be forced to umExcNameAny). In cases of EPT violations, the originator process and
2803  // modified process are the same, so take the process name from the originator.
2804  switch (ExceptionType)
2805  {
2806  case exceptionTypeUm:
2807  if (!IntExceptUserMatchProcessHash(Originator, Exception))
2808  {
2810  }
2811  break;
2812 
2813  case exceptionTypeUmGlob:
2814  if (!IntExceptUserMatchProcessGlob(Originator, (UM_EXCEPTION_GLOB *)(Exception)))
2815  {
2817  }
2818  break;
2819 
2820  default:
2821  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2822  return INT_STATUS_NOT_SUPPORTED;
2823  }
2824 
2825  switch (ExceptionType)
2826  {
2827  case exceptionTypeUm:
2828  if (!IntExceptUserMatchZoneType(Victim, ((UM_EXCEPTION *)(Exception))->Type))
2829  {
2831  }
2832  break;
2833 
2834  case exceptionTypeUmGlob:
2835  if (!IntExceptUserMatchZoneType(Victim, ((UM_EXCEPTION_GLOB *)(Exception))->Type))
2836  {
2838  }
2839  break;
2840 
2841  default:
2842  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2843  return INT_STATUS_NOT_SUPPORTED;
2844  }
2845 
2846  switch (ExceptionType)
2847  {
2848  case exceptionTypeUm:
2849  if (!IntExceptUserMatchArchitecture(Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2850  {
2852  }
2853  break;
2854 
2855  case exceptionTypeUmGlob:
2856  if (!IntExceptUserMatchArchitecture(Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2857  {
2859  }
2860  break;
2861 
2862  default:
2863  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2864  return INT_STATUS_NOT_SUPPORTED;
2865  }
2866 
2867  switch (ExceptionType)
2868  {
2869  case exceptionTypeUm:
2870  if (!IntExceptUserMatchChild(Victim, Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2871  {
2873  }
2874  break;
2875 
2876  case exceptionTypeUmGlob:
2877  if (!IntExceptUserMatchChild(Victim, Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2878  {
2880  }
2881  break;
2882 
2883  default:
2884  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2885  return INT_STATUS_NOT_SUPPORTED;
2886  }
2887 
2888  switch (ExceptionType)
2889  {
2890  case exceptionTypeUm:
2891  if (!IntExceptUserMatchSystemProcess(Victim, Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2892  {
2894  }
2895  break;
2896 
2897  case exceptionTypeUmGlob:
2898  if (!IntExceptUserMatchSystemProcess(Victim, Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2899  {
2901  }
2902  break;
2903 
2904  default:
2905  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2906  return INT_STATUS_NOT_SUPPORTED;
2907  }
2908 
2909  // If we get here, then allow the action. Anyway, the extra checks & signatures mechanism will actually allow it
2911 }
2912 
2913 
2914 INTSTATUS
2916  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2917  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2918  _Out_ INTRO_ACTION *Action,
2919  _Out_ INTRO_ACTION_REASON *Reason
2920  )
2939 {
2940  INTSTATUS status;
2941  static BOOLEAN showNotLoadedWarning = TRUE;
2942  BYTE id;
2943 
2944  if (NULL == Victim)
2945  {
2947  }
2948 
2949  if (NULL == Originator)
2950  {
2952  }
2953 
2954  if (NULL == Action)
2955  {
2957  }
2958 
2959  if (NULL == Reason)
2960  {
2962  }
2963 
2964  if (NULL == gGuest.Exceptions || !gGuest.Exceptions->Loaded)
2965  {
2966  if (showNotLoadedWarning)
2967  {
2968  LOG("**************************************************\n");
2969  LOG("************Exceptions are not loaded*************\n");
2970  LOG("**************************************************\n");
2971 
2972  showNotLoadedWarning = FALSE;
2973  }
2974 
2975  *Action = introGuestAllowed;
2977 
2979  }
2980 
2981  *Action = introGuestNotAllowed;
2982  *Reason = introReasonNoException;
2983 
2985 
2986  // In some cases the Old/New values are the same - allow them by default.
2987  if (__unlikely(Victim->ZoneType == exceptionZoneEpt && !!(Victim->ZoneFlags & ZONE_WRITE) &&
2988  !memcmp(Victim->WriteInfo.OldValue, Victim->WriteInfo.NewValue,
2989  MIN(Victim->WriteInfo.AccessSize, sizeof(Victim->WriteInfo.NewValue)))))
2990  {
2991  *Action = introGuestAllowed;
2992  *Reason = introReasonSameValue;
2993 
2995  }
2996 
2998  {
2999  if (pEx->OriginatorNameHash == umExcNameAny)
3000  {
3001  // For now, we do not support exceptions from the alert that has originator umExcNameAny.
3002  // If an exception from the alert has no originator, umExcNoName will be used as the exception originator
3003  goto _match_ex_alert;
3004  }
3005 
3006  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
3007  {
3008  goto _match_ex_alert;
3009  }
3010 
3011  if (pEx->OriginatorNameHash > Originator->NameHash)
3012  {
3013  break;
3014  }
3015  else if (pEx->OriginatorNameHash != Originator->NameHash)
3016  {
3017  continue;
3018  }
3019 
3020 _match_ex_alert:
3021  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3022  if (status == INT_STATUS_EXCEPTION_ALLOW)
3023  {
3024  return status;
3025  }
3026  }
3027 
3028  if (Victim->Object.Type == introObjectTypeProcessCreation)
3029  {
3031  {
3032  if (pEx->OriginatorNameHash == umExcNameAny)
3033  {
3034  goto _match_ex_alert_process;
3035  }
3036 
3037  // Every list is ordered, so break when we got to a hash bigger than ours
3038  if (pEx->OriginatorNameHash > Originator->NameHash)
3039  {
3040  break;
3041  }
3042  else if (pEx->OriginatorNameHash < Originator->NameHash)
3043  {
3044  continue;
3045  }
3046 
3047 _match_ex_alert_process:
3048  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3049  if (status == INT_STATUS_EXCEPTION_ALLOW)
3050  {
3051  return status;
3052  }
3053  }
3054 
3056  {
3057  if (pEx->OriginatorNameHash == umExcNameAny)
3058  {
3059  goto _match_ex_process;
3060  }
3061 
3062  // Every list is ordered, so break when we got to a hash bigger than ours
3063  if (pEx->OriginatorNameHash > Originator->NameHash)
3064  {
3065  break;
3066  }
3067  else if (pEx->OriginatorNameHash < Originator->NameHash)
3068  {
3069  continue;
3070  }
3071 
3072 _match_ex_process:
3073  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3074  if (status == INT_STATUS_EXCEPTION_ALLOW)
3075  {
3076  return status;
3077  }
3078  }
3079  }
3080 
3081  if (Originator->NameHash == INITIAL_CRC_VALUE)
3082  {
3083  // Check the no name exceptions
3085  {
3086  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3087  if (status == INT_STATUS_EXCEPTION_ALLOW)
3088  {
3089  RemoveEntryList(&pEx->Link);
3091 
3092  return status;
3093  }
3094  }
3095  }
3096  else
3097  {
3098  // Check the generic exceptions (all of them, since originator matches anything)
3100  {
3101  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3102  if (status == INT_STATUS_EXCEPTION_ALLOW)
3103  {
3104  RemoveEntryList(&pEx->Link);
3106 
3107  return status;
3108  }
3109  }
3110  }
3111 
3112  if (Originator->Name != NULL)
3113  {
3115 
3117  {
3118  if ((Originator->Name[0] < pEx->OriginatorNameGlob[0]) &&
3119  !IntExceptUserIsGlobItem(pEx->OriginatorNameGlob[0]))
3120  {
3121  break;
3122  }
3123 
3124  if ((Originator->Name[0] != pEx->OriginatorNameGlob[0]) &&
3125  !IntExceptUserIsGlobItem(pEx->OriginatorNameGlob[0]))
3126  {
3127  continue;
3128  }
3129 
3130  if (Originator->Library == NULL && Originator->Name != NULL)
3131  {
3132  if (!glob_match_utf8(pEx->OriginatorNameGlob, Originator->Name, TRUE, TRUE))
3133  {
3134  continue;
3135  }
3136  }
3137  else if (Originator->Library != NULL && Originator->NameWide != NULL)
3138  {
3139  if (!glob_match_utf16(pEx->OriginatorNameGlob, Originator->NameWide, TRUE, TRUE))
3140  {
3141  continue;
3142  }
3143  }
3144  else
3145  {
3146  continue;
3147  }
3148 
3149  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUmGlob, Action, Reason);
3150  if (status == INT_STATUS_EXCEPTION_ALLOW)
3151  {
3152  TRACE("[EXCEPTION] IntExceptMatchException (GLOB) returned INT_STATUS_EXCEPTION_ALLOW.");
3153  return status;
3154  }
3155  }
3156 
3158  }
3159 
3160  if (Originator->NameHash != INITIAL_CRC_VALUE)
3161  {
3162  id = EXCEPTION_TABLE_ID(Originator->NameHash);
3163 
3165  {
3166  // Every list is ordered, so break when we got to a hash bigger than ours
3167  if (pEx->OriginatorNameHash > Originator->NameHash)
3168  {
3169  break;
3170  }
3171  else if (pEx->OriginatorNameHash < Originator->NameHash)
3172  {
3173  continue;
3174  }
3175 
3176  if (pEx->Flags & EXCEPTION_FLG_RETURN)
3177  {
3178  continue;
3179  }
3180 
3181  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3182  if (status == INT_STATUS_EXCEPTION_ALLOW)
3183  {
3184  return status;
3185  }
3186  }
3187  }
3188 
3189  if (Originator->Library && Originator->Return.Library &&
3190  (Originator->Rip == Originator->Return.Rip))
3191  {
3192  goto _beta_exceptions;
3193  }
3194 
3195  id = EXCEPTION_TABLE_ID(Originator->Return.NameHash);
3197  {
3198  // Every list is ordered, so break when we got to a hash bigger than ours
3199  if (pEx->OriginatorNameHash > Originator->Return.NameHash)
3200  {
3201  break;
3202  }
3203  else if (pEx->OriginatorNameHash < Originator->Return.NameHash)
3204  {
3205  continue;
3206  }
3207 
3208  if (0 == (pEx->Flags & EXCEPTION_FLG_RETURN))
3209  {
3210  continue;
3211  }
3212 
3213  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3214  if (status == INT_STATUS_EXCEPTION_ALLOW)
3215  {
3216  return status;
3217  }
3218  }
3219 
3220 _beta_exceptions:
3222  {
3223  if (pEx->OriginatorNameHash == umExcNameAny)
3224  {
3225  goto _match_ex;
3226  }
3227 
3228  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
3229  {
3230  goto _match_ex;
3231  }
3232 
3233  if (pEx->Flags & EXCEPTION_FLG_RETURN)
3234  {
3235  if (pEx->OriginatorNameHash != Originator->Return.NameHash)
3236  {
3237  continue;
3238  }
3239  }
3240  else
3241  {
3242  if (pEx->OriginatorNameHash != Originator->NameHash)
3243  {
3244  continue;
3245  }
3246  }
3247 
3248 _match_ex:
3249  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3250  if (status == INT_STATUS_EXCEPTION_ALLOW)
3251  {
3252  return status;
3253  }
3254  }
3255 
3257  {
3258  if (pEx->OriginatorNameHash == umExcNameAny)
3259  {
3260  goto _match_process_beta_ex;
3261  }
3262 
3263  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
3264  {
3265  goto _match_process_beta_ex;
3266  }
3267 
3268  if (pEx->Flags & EXCEPTION_FLG_RETURN)
3269  {
3270  if (pEx->OriginatorNameHash != Originator->Return.NameHash)
3271  {
3272  continue;
3273  }
3274  }
3275  else
3276  {
3277  if (pEx->OriginatorNameHash != Originator->NameHash)
3278  {
3279  continue;
3280  }
3281  }
3282 
3283 _match_process_beta_ex:
3284  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
3285  if (status == INT_STATUS_EXCEPTION_ALLOW)
3286  {
3287  return status;
3288  }
3289  }
3290 
3291  return status;
3292 }
WINUM_PATH * Path
Module path.
Definition: winummodule.h:62
uint16_t * PWCHAR
Definition: intro_types.h:63
The object allows only dlls which are detected as suspicous (e.g. module loads before kernel32...
Definition: exceptions.h:223
#define _In_opt_
Definition: intro_sal.h:16
INTSTATUS IntExceptUserVerifyExtra(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, UM_EXCEPTION *Exception)
This function is used as an extra step in exception mechanism that verify the initialization flags of...
BOOLEAN Bits64
TRUE if we got the stack frame in 64-bit mode (RBP) or 32 (EBP)
Definition: guest_stack.h:48
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
#define INT_STATUS_EXCEPTION_NOT_MATCHED
Definition: introstatus.h:406
#define __unlikely(x)
Definition: common.h:64
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
int IntExceptPrintWinProcInfo(WIN_PROCESS_OBJECT *Process, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the data from the provided WIN_PROCESS_OBJECT.
struct _DPI_EXTRA_INFO::@206::@210 HeapPages[HEAP_SPRAY_NR_PAGES]
QWORD Cr3
The CR3 for this process.
Definition: lixprocess.h:70
#define HEAP_SPRAY_NR_PAGES
Definition: windpi.h:22
DWORD MonitorModules
TRUE if we need to monitor module load/unloads.
Definition: winprocess.h:163
char * utf16toutf8(char *Destination, const WCHAR *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:460
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
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.
The creation of a process was attempted while the parent had its heap sprayed.
Definition: intro_types.h:1666
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
static __inline BOOLEAN IntExceptUserMatchProcessHash(EXCEPTION_UM_ORIGINATOR *Originator, UM_EXCEPTION *Exception)
Checks if the exception process name-hash of the current exception matches the process name-hash of t...
static void InsertHeadList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:152
uint8_t BYTE
Definition: intro_types.h:47
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
#define _In_
Definition: intro_sal.h:21
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:211
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
struct _DPI_EXTRA_INFO::@204 DpiPivotedStackExtraInfo
BOOLEAN glob_match_utf8(char const *Pattern, char const *String, BOOLEAN IgnoreCase, BOOLEAN Truncated)
Definition: introcrt.c:609
uint16_t WORD
Definition: intro_types.h:48
BOOLEAN glob_match_utf16(char const *Pattern, WCHAR const *String, BOOLEAN IgnoreCase, BOOLEAN Truncated)
Definition: introcrt.c:909
struct _DPI_EXTRA_INFO::@209 DpiSecDescAclExtraInfo
#define STATS_EXIT(id)
Definition: stats.h:160
#define ZONE_LIB_RESOURCES
Used for the resources section (usually .rsrc inside a driver or dll).
Definition: exceptions.h:726
User-mode exception.
Definition: exceptions.h:60
User-mode non executable zone.
Definition: intro_types.h:247
LIST_HEAD GenericUserExceptions
Linked list used for user-mode exceptions that have a generic originator(*).
Definition: exceptions.h:91
QWORD TrapFrameAddress
The address of the trap frame. Used for more information gathering when sending the alert...
Definition: windpi.h:40
Process creation violation.
Definition: intro_types.h:262
The modified object is anything inside the structure CONTEXT (valid only for windows).
Definition: exceptions.h:215
QWORD Wow64StackLimit
The known stack limit in WoW64 mode. Valid only if the process is WoW64.
Definition: windpi.h:44
Signals an attempt to set an insturmentation callback.
Definition: exceptions.h:226
LIST_HEAD ProcessCreationAlertExceptions
Linked list used for process-creation exceptions that are added from alert.
Definition: exceptions.h:122
QWORD NewEnabled
The new value from parent&#39;s token Privileges.Enabled field, which was deemed malicious.
Definition: windpi.h:74
struct _WIN_PROCESS_OBJECT::@232 CreationInfo
DWORD NumberOfOffsets
Number of symbols pointing to the exported RVA.
Definition: winumcache.h:27
#define WIN_UM_FIELD(Structure, Field)
Macro used to access user mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:778
The exception will take into consideration the return driver/dll.
Definition: exceptions.h:601
static __inline BOOLEAN IntExceptUserMatchChild(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, DWORD ExceptionFlags)
Checks if the victim is a child of the originator.
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
void IntDumpWinTrapFrame32(KTRAP_FRAME32 *TrapFrame)
This function dumps a windows 64 guest trap frame.
Definition: dumper.c:789
#define EXCEPTION_NO_NAME
Definition: exceptions.h:28
QWORD StartAddress
The address on which the parent&#39;s thread started execution.
Definition: windpi.h:82
ACL OldDacl
The old DACL header.
Definition: windpi.h:96
INTRO_PC_VIOLATION_TYPE
Process creation violation flags.
Definition: intro_types.h:1651
#define ARRAYSIZE(A)
Definition: introdefs.h:101
The modified object is inside an EPT hook.
Definition: exceptions.h:746
#define INT_STATUS_EXCEPTION_CHECKS_OK
Definition: introstatus.h:396
Describe a user-mode glob exception.
Definition: exceptions.h:336
enum _UM_EXCEPTION_OBJECT UM_EXCEPTION_OBJECT
Object type of the user-mode exception.
Structure that describes a stack trace element.
Definition: guest_stack.h:25
The exception is valid only for read violation.
Definition: exceptions.h:605
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
Process creation violation DPI.
Definition: intro_types.h:265
DWORD NumberOfTraces
Number of elements inside Traces.
Definition: guest_stack.h:44
#define ERROR(fmt,...)
Definition: glue.h:62
LIST_HEAD UserAlertExceptions
Linked list used for user-mode exceptions that are added from alert.
Definition: exceptions.h:124
Describes a user-mode originator.
Definition: exceptions.h:994
#define for_each_um_exception(_ex_head, _var_name)
Definition: exceptions.h:1070
INTSTATUS IntExceptUser(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
This function iterates through exception lists and tries to find an exception that matches the origin...
The name can be any string.
Definition: exceptions.h:687
QWORD StolenFromEprocess
The EPROCESS address from which the token was stolen.
Definition: windpi.h:49
LIST_HEAD UserExceptions[EXCEPTION_TABLE_SIZE]
Array of linked lists used for user-mode exceptions.
Definition: exceptions.h:109
INTSTATUS IntExceptMatchException(void *Victim, void *Originator, void *Exception, EXCEPTION_TYPE ExceptionType, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
This function tries to find a exception for the current violation..
Definition: exceptions.c:3167
int INTSTATUS
The status data type.
Definition: introstatus.h:24
BOOLEAN Loaded
True if the exceptions are loaded.
Definition: exceptions.h:146
DWORD NameHash
Name hash, as used by the exceptions module.
Definition: winprocess.h:101
The exception will match only for the init phase of a driver/process.
Definition: exceptions.h:599
static __inline BOOLEAN IntExceptUserMatchZoneType(EXCEPTION_VICTIM_ZONE *Victim, UM_EXCEPTION_OBJECT ZoneType)
Checks if the zone-type of the current exception matches the zone-type of the victim.
The exception is valid only if the originator process is a system process.
Definition: exceptions.h:621
#define ONE_KILOBYTE
Definition: introdefs.h:89
static char * IntExceptUserGetPcTypeString(INTRO_PC_VIOLATION_TYPE Type)
Returns a string that contains the descriptions of the porovided process creation violation type...
QWORD DebuggerEprocess
This will keep the EPROCESS of the debugger process (if any).
Definition: winprocess.h:284
#define MAX_PATH
The maximum size of a path (260 characters on windows).
Definition: winpe.h:579
struct _WIN_PROCESS_MODULE * PWIN_PROCESS_MODULE
User-mode exception that accepts glob content.
Definition: exceptions.h:62
static __inline BOOLEAN IntExceptUserMatchProcessGlob(EXCEPTION_UM_ORIGINATOR *Originator, UM_EXCEPTION_GLOB *Exception)
Checks if the exception process glob-name of the current exception matches the process glob-name of t...
ACL NewSacl
The new SACL header.
Definition: windpi.h:98
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
QWORD Wow64StackBase
The known stack base in WoW64 mode. Valid only if the process is WoW64.
Definition: windpi.h:43
INTSTATUS IntExceptUserGetExecOriginator(void *Process, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to get the originator for heap execution.
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
Definition: guests.h:88
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...
The exception is valid only for write violation.
Definition: exceptions.h:606
#define MIN(a, b)
Definition: introdefs.h:146
STACK_ELEMENT * Traces
Array describing the stack trace elements.
Definition: guest_stack.h:46
DWORD CommHash
The CRC32 checksum of the Comm field.
Definition: lixprocess.h:65
The name is missing.
Definition: exceptions.h:692
#define LOG(fmt,...)
Definition: glue.h:61
#define ZONE_PROC_INSTRUMENT
Used for exceptions for instrumentation callback.
Definition: exceptions.h:732
The modified object is only another process (injection basically).
Definition: exceptions.h:209
void * ReturnModule
The module to which the function belongs.
Definition: guest_stack.h:33
PWIN_PROCESS_MODULE IntWinUmModFindByAddress(PWIN_PROCESS_OBJECT Process, QWORD Gva)
Searches for a user-mode module which contains the indicated guest virtual address.
Definition: winummodule.c:2304
static __inline BOOLEAN IntExceptUserMatchNameHash(EXCEPTION_VICTIM_ZONE *Victim, UM_EXCEPTION *Exception)
Checks if the exception name-hash of the current exception matches the name-hash of the victim...
#define NAMEHASH_NTDLL
Definition: winummodule.h:11
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
enum _INTRO_OBJECT_TYPE INTRO_OBJECT_TYPE
The type of the object protected by an EPT hook.
#define _Inout_
Definition: intro_sal.h:20
#define ZONE_LIB_CODE
Used for a generic code zone.
Definition: exceptions.h:723
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:392
static INTSTATUS IntExceptUserHandleMemoryFunctions(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_MODULE *Module, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to check if the write has been made using a function that write/read memory (eg...
#define STATS_ENTER(id)
Definition: stats.h:153
#define MEMORY_FUNC_SIZE
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:736
The parent of a process has a stolen access token when it created the child.
Definition: intro_types.h:1663
#define memzero(a, s)
Definition: introcrt.h:35
The exception is valid only for execute violation.
Definition: exceptions.h:607
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
#define ZONE_PROC_THREAD_APC
Used for the APC thread hijacking technique.
Definition: exceptions.h:729
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
enum _EXCEPTION_TYPE EXCEPTION_TYPE
The type of an exception.
The creation of a process was attempted with token privileges altered in a malicious way...
Definition: intro_types.h:1669
static void IntExceptUserLogWindowsInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a violation (windows guest).
#define TRUE
Definition: intro_types.h:30
static __inline BOOLEAN IntExceptUserMatchNameGlob(EXCEPTION_VICTIM_ZONE *Victim, UM_EXCEPTION_GLOB *Exception)
Checks if the exception glob-name of the current exception matches the glob-name of the victim...
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
INTSTATUS IntExceptUserVerifyExtraGlobMatch(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, UM_EXCEPTION_GLOB *Exception)
This function is used as an extra step in exception mechanism that verify the initialization flags of...
The parent of a process had a pivoted stack when it created the child.
Definition: intro_types.h:1660
QWORD CurrentWow64Stack
The current stack of the process in WoW64 mode. Valid only if the process is WoW64.
Definition: windpi.h:42
int IntExceptPrintWinModInfo(WIN_PROCESS_MODULE *Module, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the data from the provided WIN_PROCESS_MODULE.
TIMER_FRIENDLY void IntDumpBuffer(const void *Buffer, QWORD Gva, DWORD Length, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given buffer in a user friendly format.
Definition: dumper.c:48
#define TRACE(fmt,...)
Definition: glue.h:58
WORD AclSize
Definition: wddefs.h:641
WORD AceCount
Definition: wddefs.h:642
#define INT_STATUS_INVALID_PARAMETER_5
Definition: introstatus.h:74
DPI_EXTRA_INFO DpiExtraInfo
Represents the gathered extra info while checking the DPI heuristics.
Definition: winprocess.h:304
QWORD ReturnAddress
The address where the current stack frame will return (@ ret)
Definition: guest_stack.h:34
QWORD SecDescStolenFromEproc
If the parent security descriptor has been stolen, this variable may indicate (in case we find it) th...
Definition: windpi.h:90
QWORD NewPresent
The new value from parent&#39;s token Privileges.Present field, which was deemed malicious.
Definition: windpi.h:77
QWORD CurrentStack
The current stack of the process at the point of process creation.
Definition: windpi.h:36
void IntDumpWinTrapFrame64(KTRAP_FRAME64 *TrapFrame)
This function dumps a windows 64 guest trap frame.
Definition: dumper.c:765
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:367
The modified object is anything inside of the PEB32 structure.
Definition: exceptions.h:216
ACL OldSacl
The old SACL header.
Definition: windpi.h:95
#define WARNING(fmt,...)
Definition: glue.h:60
void IntExceptUserLogInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a user-mode violation, dumps the code-blocks and the injection buffer...
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:100
#define ZONE_LIB_EXPORTS
Used for the exports of a dll, driver, etc.
Definition: exceptions.h:722
static __inline BOOLEAN IntExceptUserMatchZoneFlags(EXCEPTION_VICTIM_ZONE *Victim, DWORD ZoneFlags)
Checks if the zone-flags of the current exception match the zone flags of the victim.
#define PAGE_SIZE
Definition: common.h:70
The modified object is inside the process module&#39;s IAT.
Definition: exceptions.h:211
Describes the modified zone.
Definition: exceptions.h:893
struct _DPI_EXTRA_INFO::@205 DpiStolenTokenExtraInfo
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
Definition: winumpath.h:23
QWORD OldEnabled
Definition: windpi.h:72
ACL NewDacl
The new DACL header.
Definition: windpi.h:99
#define __forceinline
Definition: introtypes.h:61
Describe a user-mode exception.
Definition: exceptions.h:308
DWORD Rva
The RVA of this export.
Definition: winumcache.h:23
uint16_t WCHAR
Definition: intro_types.h:63
Executions inside the SharedUserData region.
Definition: intro_types.h:267
uint32_t DWORD
Definition: intro_types.h:49
struct _DPI_EXTRA_INFO::@208 DpiThreadStartExtraInfo
QWORD StackBase
The known stack base present in TIB at the moment of process creation.
Definition: windpi.h:37
struct _DPI_EXTRA_INFO::@206 DpiHeapSprayExtraInfo
LIST_HEAD GlobUserExceptions
Linked list used for user-mode exceptions that contains glob content.
Definition: exceptions.h:105
#define EXCEPTION_NO_WNAME
Definition: exceptions.h:29
User-mode library.
Definition: intro_types.h:248
#define for_each_um_glob_exception(_ex_head, _var_name)
Definition: exceptions.h:1072
The exception file was not loaded (there are no exceptions).
Definition: intro_types.h:193
enum _INTRO_ACTION INTRO_ACTION
Event actions.
LIST_HEAD ProcessCreationExceptions
Linked list used for process creations exceptions.
Definition: exceptions.h:110
static __inline BOOLEAN IntExceptUserMatchArchitecture(EXCEPTION_UM_ORIGINATOR *Originator, DWORD ExceptionFlags)
Checks if the architecture-flags of the current exception match the architecture-flags of the origina...
The exception is valid only if the modified process is a child of the originator process.
Definition: exceptions.h:623
INTSTATUS IntWinUmCheckInitializationInjection(PEXCEPTION_VICTIM_ZONE Victim, PEXCEPTION_UM_ORIGINATOR Originator)
This function is used by the exception mechanism in order to verify the initialization state of a pro...
static BOOLEAN IntExceptUserIsGlobItem(char Item)
Checks if the provided char is a glob char.
QWORD OldPresent
Definition: windpi.h:75
int IntExceptPrintLixTaskInfo(const LIX_TASK_OBJECT *Task, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the information about the provided LIX_TASK_OBJECT.
Signals an execution inside SharedUserData.
Definition: exceptions.h:225
The action was allowed, but it has the BETA flag (Introcore is in log-only mode). ...
Definition: intro_types.h:185
static __inline BOOLEAN IntExceptUserMatchSystemProcess(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, DWORD ExceptionFlags)
Checks if the originator is a system process; for process-creation violation this function checks if ...
WCHAR * Name
The name of the module contained in the path.
Definition: winumpath.h:18
#define MAX(a, b)
Definition: introdefs.h:151
struct _DPI_EXTRA_INFO::@207 DpiTokenPrivsExtraInfo
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
Definition: introcore.c:2134
#define ZONE_LIB_DATA
Definition: exceptions.h:724
INTSTATUS IntExceptUserMatchVictim(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, void *Exception, EXCEPTION_TYPE ExceptionType)
This function checks if the exception matches the originator and the modified zone.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:374
static void IntExceptUserLogLinuxInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a violation (Linux guest).
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:90
char Comm[LIX_COMM_SIZE]
The short name of the executable.
Definition: lixprocess.h:44
The parent of a process tried to obtain debug privileges over the child.
Definition: intro_types.h:1657
The parent of a process has an altered security descriptor pointer.
Definition: intro_types.h:1675
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
The modified object is inside a process.
Definition: exceptions.h:750
char gExcLogLine[2 *ONE_KILOBYTE]
The exception log line.
Definition: exceptions.c:40
VAD * IntWinVadFindAndUpdateIfNecessary(WIN_PROCESS_OBJECT *Process, QWORD StartHint, QWORD LengthHint)
Searches for a VAD in the Introcore VAD tree. If no VAD is found, or if the found one does not fully ...
Definition: winvad.c:2122
The modified object is inside the process modules.
Definition: exceptions.h:210
TIMER_FRIENDLY void IntDumpGva(QWORD Gva, DWORD Length, QWORD Cr3)
This function is a wrapper over IntDumpGvaEx (it uses RowLength = 16, ElementLength = 1...
Definition: dumper.c:273
LIST_HEAD ProcessCreationFeedbackExceptions
Linked list used for process-creation exceptions that have the feedback flag.
Definition: exceptions.h:119
#define EXCEPTION_TABLE_ID(H)
Definition: exceptions.h:50
#define INT_STATUS_STACK_SWAPPED_OUT
Indicates that the stack was needed in order to match the exceptions, but it is swapped out...
Definition: introstatus.h:465
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:96
LIST_HEAD UserFeedbackExceptions
Linked list used for user-mode exceptions that have the feedback flag.
Definition: exceptions.h:113
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1672
Virtual SYSCALL (user-mode, Linux-only).
Definition: intro_types.h:257
#define PROC_OPT_BETA
Process is monitored, but in log-only mode so no actions will be blocked.
Definition: intro_types.h:376
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:735
WINUM_CACHE_EXPORT * IntWinUmCacheGetExportFromRange(WIN_PROCESS_MODULE *Module, QWORD Gva, DWORD Length)
Tries to find an export in the range [Gva - Length, Gva].
Definition: winumcache.c:225
DWORD MonitorVad
TRUE if we need to handle VAD events for this process.
Definition: winprocess.h:162
BYTE AclRevision
Definition: wddefs.h:639
The action was blocked because no exception signature matched.
Definition: intro_types.h:187
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
void IntExceptDumpSignatures(void *Originator, EXCEPTION_VICTIM_ZONE *Victim, BOOLEAN KernelMode, BOOLEAN ReturnDrv)
Dump code blocks from the originator&#39;s RIP.
Definition: exceptions.c:2978
Virtual dynamic shared object (user-mode, Linux-only).
Definition: intro_types.h:256
The modified object is any with the modified name.
Definition: exceptions.h:208
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
Exposes the function used to perform initialization checks on Windows processes.
LIX_TASK_OBJECT * IntLixTaskFindByGva(QWORD TaskStruct)
Finds Linux process with the provided "task_struct" guest virtual address.
Definition: lixprocess.c:1025
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
The modified object is the thread which was performed an asynchronous procedure call on...
Definition: exceptions.h:219
#define ZONE_PROC_THREAD_CTX
Used for the CONTEXT structure of a thread.
Definition: exceptions.h:728
#define ZONE_LIB_IMPORTS
Used for the imports of a dll, driver, etc.
Definition: exceptions.h:721
Used for process-creation violations.
Definition: exceptions.h:752
Structure that describes a stack trace.
Definition: guest_stack.h:42
The exception is valid only on 32 bit systems/process.
Definition: exceptions.h:596
The parent of a process has an altered access control entry (inside SACL or DACL).
Definition: intro_types.h:1678
#define EXPORT_NAME_UNKNOWN
Definition: exceptions.h:34
QWORD StackLimit
Definition: windpi.h:38
char CHAR
Definition: intro_types.h:56
QWORD ShellcodeFlags
Contains the flags on the first page which was detected through shemu.
Definition: windpi.h:67
The exception is valid only for apphelp process.
Definition: exceptions.h:626
INTSTATUS IntExceptGetVictimProcessCreation(void *Process, INTRO_OBJECT_TYPE ObjectType, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim for process-creation violation...
#define ZONE_MODULE_LOAD
Used for exceptions for double agent.
Definition: exceptions.h:731
#define PAGE_MASK
Definition: pgtable.h:35
Measures glob-match exceptions.
Definition: stats.h:52
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
The exception is valid only once.
Definition: exceptions.h:625
LIST_HEAD NoNameUserExceptions
Linked list used for user-mode exceptions that don&#39;t have a valid originator (-). ...
Definition: exceptions.h:99
Process creation violation without any DPI heuristic being triggered.
Definition: intro_types.h:1654
INTSTATUS IntWinStackTraceGetUser(PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace)
Get the user stack trace of a windows process.
Definition: winstack.c:1604
The process object creates another process using DPI flags.
Definition: exceptions.h:224
The object that has a NX zone is executed.
Definition: exceptions.h:212
#define INT_STATUS_EXCEPTION_ALLOW
Definition: introstatus.h:391
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83
The exception (and signature, where&#39;s the case) matched, but the extra checks failed.
Definition: intro_types.h:191
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68