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 int
25  _In_opt_ const LIX_TASK_OBJECT *Task,
26  _In_ char *Header,
27  _Out_ char *Line,
28  _In_ int MaxLength,
29  _In_opt_ DWORD NameAlignment
30  )
42 {
43  int ret, total = 0;
44 
45  if (NULL == Task)
46  {
47  return total;
48  }
49 
50  if (NameAlignment)
51  {
52  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, Task->ProcName);
53  }
54  else
55  {
56  ret = snprintf(Line, MaxLength, "%s(%s", Header, Task->ProcName);
57  }
58 
59  if (ret < 0)
60  {
61  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
62  }
63  else
64  {
65  Line += ret;
66  total += ret;
67  MaxLength -= ret;
68  }
69 
70  ret = snprintf(Line, MaxLength, " '%s' [0x%08x], %016llx, %016llx, %016llx, %d/%d",
71  Task->Comm, Task->CommHash, Task->Gva, Task->Cr3, Task->MmGva, Task->Pid, Task->Tgid);
72 
73  if (ret < 0)
74  {
75  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
76  }
77  else
78  {
79  Line += ret;
80  total += ret;
81  MaxLength -= ret;
82  }
83 
84  if (Task->CmdLine)
85  {
86  ret = snprintf(Line, MaxLength, ", CLI:`%s`", Task->CmdLine);
87 
88  if (ret < 0)
89  {
90  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
91  }
92  else
93  {
94  Line += ret;
95  total += ret;
96  MaxLength -= ret;
97  }
98  }
99 
100  ret = snprintf(Line, MaxLength, ")");
101  total += ret;
102 
103  return total;
104 }
105 
106 
107 static void
109  _In_ EXCEPTION_VICTIM_ZONE *Victim,
110  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
111  _In_ INTRO_ACTION Action,
113  )
122 {
123  DWORD procNameAlignment;
124  char *l;
125  int ret, rem;
126 
127  // This cannot be NULL! Everything must happen inside a process in user-mode
128  if (NULL == Originator->LixProc)
129  {
130  ERROR("[ERROR] Originator process is NULL!\n");
131  return;
132  }
133 
134  procNameAlignment = 0;
135  if (Victim->Object.LixProc)
136  {
137  procNameAlignment = (DWORD)MIN(MAX_PATH,
138  MAX(Victim->Object.LixProc->ProcNameLength,
139  Originator->LixProc->ProcNameLength));
140  }
141 
142  l = gExcLogLine;
143  rem = sizeof(gExcLogLine);
144 
145  if ((Victim->ZoneType == exceptionZoneProcess) ||
146  (Victim->Object.Type == introObjectTypeUmGenericNxZone))
147  {
148  ret = IntExceptPrintLixTaskInfo(Originator->LixProc, "Originator-> Process: ", l, rem, procNameAlignment);
149  rem -= ret;
150  l += ret;
151 
152  if (Victim->ZoneType == exceptionZoneProcess)
153  {
154  ret = snprintf(l, rem, ", VA: %016llx", Originator->SourceVA);
155  }
156  else
157  {
158  ret = snprintf(l, rem, ", RIP: %016llx", Originator->Rip);
159  }
160 
161  if (ret < 0)
162  {
163  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
164  }
165  else
166  {
167  rem -= ret;
168  l += ret;
169  }
170 
171  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Originator->LixProc->Parent),
172  ", Parent: ", l, rem, 0);
173  rem -= ret;
174  l += ret;
175 
176  LOG("%s\n", gExcLogLine);
177  }
178  else if ((Victim->Object.Type == introObjectTypeVdso) ||
179  (Victim->Object.Type == introObjectTypeVsyscall))
180  {
181  ret = IntExceptPrintLixTaskInfo(Originator->LixProc, "Originator-> Process: ", l, rem, procNameAlignment);
182  rem -= ret;
183  l += ret;
184 
185  ret = snprintf(l, rem, ", RIP: %016llx", Originator->Rip);
186 
187  if (ret < 0)
188  {
189  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
190  }
191  else
192  {
193  rem -= ret;
194  l += ret;
195  }
196 
197  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Originator->LixProc->Parent),
198  ", Parent: ", l, rem, 0);
199  rem -= ret;
200  l += ret;
201 
202  LOG("%s\n", gExcLogLine);
203  }
204 
205  l = gExcLogLine;
206  rem = sizeof(gExcLogLine);
207 
208  if ((Victim->ZoneType == exceptionZoneProcess) ||
209  (Victim->Object.Type == introObjectTypeUmGenericNxZone))
210  {
211  ret = IntExceptPrintLixTaskInfo(Victim->Object.LixProc, "Victim -> Process: ", l, rem, procNameAlignment);
212  rem -= ret;
213  l += ret;
214 
215  if (Victim->ZoneType == exceptionZoneProcess)
216  {
217  ret = snprintf(l, rem, ", InjInfo: (%u, %016llx)",
218  Victim->Injection.Length, Victim->Injection.Gva);
219  }
220  else
221  {
222  ret = snprintf(l, rem, ", ExecInfo: (%016llx, %016llx), Stack: (0x%016llx, 0x%16llx), RSP = 0x%016llx",
223  Victim->Ept.Gva, Victim->Ept.Gpa, Victim->ExecInfo.StackBase, Victim->ExecInfo.StackLimit,
224  Victim->ExecInfo.Rsp);
225  }
226 
227  if (ret < 0)
228  {
229  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
230  }
231  else
232  {
233  rem -= ret;
234  l += ret;
235  }
236 
237  ret = IntExceptPrintLixTaskInfo(IntLixTaskFindByGva(Victim->Object.LixProc->Parent),
238  ", Parent: ", l, rem, 0);
239  rem -= ret;
240  l += ret;
241 
242  LOG("%s\n", gExcLogLine);
243  }
244  else if ((Victim->Object.Type == introObjectTypeVdso) ||
245  (Victim->Object.Type == introObjectTypeVsyscall))
246  {
247  const char *libName = (Victim->Object.Type == introObjectTypeVdso) ? "[vdso]" : "[vsyscall]";
248 
249  ret = IntExceptPrintLixTaskInfo(Victim->Object.LixProc, "Victim -> Process: ", l, rem, procNameAlignment);
250  rem -= ret;
251  l += ret;
252 
253  ret = snprintf(l, rem, ", Address: (%0llx, %0llx), Lib: %s, WriteInfo: (%u, %016llx -> %016llx)",
254  Victim->Ept.Gva, Victim->Ept.Gpa,
255  libName, Victim->WriteInfo.AccessSize,
256  Victim->WriteInfo.OldValue[0],
257  Victim->WriteInfo.NewValue[0]);
258  if (ret < 0)
259  {
260  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
261  }
262  else
263  {
264  rem -= ret;
265  l += ret;
266  }
267 
268  LOG("%s\n", gExcLogLine);
269  }
270 
271  if (Action == introGuestNotAllowed)
272  {
273  l = gExcLogLine;
274  rem = sizeof(gExcLogLine);
275 
276  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sMALWARE (user-mode) ",
277  (Victim->Object.LixProc && Victim->Object.LixProc->Protection.Mask & PROC_OPT_BETA) ?
278  " (B) " : " ");
279  if (ret < 0)
280  {
281  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
282  }
283  else
284  {
285  rem -= ret;
286  l += ret;
287  }
288 
289  switch (Reason)
290  {
292  ret = snprintf(l, rem, "(no sig)");
293  break;
295  ret = snprintf(l, rem, "(no exc)");
296  break;
298  ret = snprintf(l, rem, "(extra)");
299  break;
301  ret = snprintf(l, rem, "(error)");
302  break;
304  ret = snprintf(l, rem, "(value)");
305  break;
307  ret = snprintf(l, rem, "(value code)");
308  break;
310  ret = snprintf(l, rem, "(idt)");
311  break;
313  ret = snprintf(l, rem, "(version os)");
314  break;
316  ret = snprintf(l, rem, "(version intro)");
317  break;
319  ret = snprintf(l, rem, "(export)");
320  break;
322  ret = snprintf(l, rem, "(process creation)");
323  break;
324  case introReasonUnknown:
325  ret = snprintf(l, rem, "(unknown)");
326  break;
327  default:
328  ret = snprintf(l, rem, "(%d)", Reason);
329  break;
330  }
331 
332  if (ret < 0)
333  {
334  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
335  }
336  else
337  {
338  rem -= ret;
339  l += ret;
340  }
341 
342  snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
343 
344  LOG("%s\n\n", gExcLogLine);
345  }
346 }
347 
348 
349 int
351  _In_ WIN_PROCESS_OBJECT *Process,
352  _In_ char *Header,
353  _Out_ char *Line,
354  _In_ int MaxLength,
355  _In_opt_ DWORD NameAlignment
356  )
368 {
369  int ret, total = 0;
370 
371  if (NULL == Process)
372  {
373  return total;
374  }
375 
376  if (NameAlignment)
377  {
378  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, Process->Name);
379  }
380  else
381  {
382  ret = snprintf(Line, MaxLength, "%s(%s", Header, Process->Name);
383  }
384 
385  if (ret < 0)
386  {
387  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
388  }
389  else
390  {
391  Line += ret;
392  total += ret;
393  MaxLength -= ret;
394  }
395 
396  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx, %0*llx, %u, F%x",
397  Process->NameHash, gGuest.WordSize * 2, Process->EprocessAddress,
398  gGuest.WordSize * 2, Process->Cr3, Process->Pid, Process->Flags);
399 
400  if (ret < 0)
401  {
402  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
403  }
404  else
405  {
406  Line += ret;
407  total += ret;
408  MaxLength -= ret;
409  }
410 
411  if (Process->Wow64Process)
412  {
413  ret = snprintf(Line, MaxLength, ", WOW64");
414 
415  if (ret < 0)
416  {
417  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
418  }
419  else
420  {
421  Line += ret;
422  total += ret;
423  MaxLength -= ret;
424  }
425  }
426 
427  if (Process->SystemProcess)
428  {
429  ret = snprintf(Line, MaxLength, ", SYS");
430 
431  if (ret < 0)
432  {
433  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
434  }
435  else
436  {
437  Line += ret;
438  total += ret;
439  MaxLength -= ret;
440  }
441  }
442 
443  if (Process->Peb64Address)
444  {
445  ret = snprintf(Line, MaxLength, ", PEB64: %0*llx", gGuest.WordSize * 2, Process->Peb64Address);
446 
447  if (ret < 0)
448  {
449  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
450  }
451  else
452  {
453  Line += ret;
454  total += ret;
455  MaxLength -= ret;
456  }
457  }
458 
459  if (Process->Peb32Address)
460  {
461  ret = snprintf(Line, MaxLength, ", PEB32: %0*llx", gGuest.WordSize * 2, Process->Peb32Address);
462 
463  if (ret < 0)
464  {
465  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
466  }
467  else
468  {
469  Line += ret;
470  total += ret;
471  MaxLength -= ret;
472  }
473  }
474 
475  if (Process->CommandLine)
476  {
477  ret = snprintf(Line, MaxLength, ", CLI:`%s`", Process->CommandLine);
478 
479  if (ret < 0)
480  {
481  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
482  }
483  else
484  {
485  Line += ret;
486  total += ret;
487  MaxLength -= ret;
488  }
489  }
490 
491  ret = snprintf(Line, MaxLength, ")");
492  total += ret;
493 
494  return total;
495 }
496 
497 
498 int
500  _In_ WIN_PROCESS_MODULE *Module,
501  _In_ char *Header,
502  _Out_ char *Line,
503  _In_ int MaxLength,
504  _In_opt_ DWORD NameAlignment
505  )
517 {
518  int ret, total = 0;
519  WCHAR *wName;
520  DWORD nameHash;
521  char name[MAX_PATH];
522 
523  if (NULL == Module)
524  {
525  return snprintf(Line, MaxLength, "%s(%s)", Header, EXCEPTION_NO_NAME);
526  }
527 
528  if (Module->Path)
529  {
530  wName = Module->Path->Path;
531  nameHash = Module->Path->NameHash;
532  }
533  else
534  {
535  wName = NULL;
536  nameHash = INITIAL_CRC_VALUE;
537  }
538 
539  if (wName)
540  {
541  utf16toutf8(name, wName, sizeof(name));
542  }
543  else
544  {
545  memcpy(name, EXCEPTION_NO_NAME, sizeof(EXCEPTION_NO_NAME));
546  }
547 
548  if (NameAlignment)
549  {
550  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, name);
551  }
552  else
553  {
554  ret = snprintf(Line, MaxLength, "%s(%s", Header, name);
555  }
556 
557  if (ret < 0)
558  {
559  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
560  }
561  else
562  {
563  Line += ret;
564  total += ret;
565  MaxLength -= ret;
566  }
567 
568  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx, F%x",
569  nameHash, gGuest.WordSize * 2, Module->VirtualBase, Module->Flags);
570  if (ret < 0)
571  {
572  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
573  }
574  else
575  {
576  Line += ret;
577  total += ret;
578  MaxLength -= ret;
579  }
580 
581  if (Module->Cache && Module->Cache->Info.TimeDateStamp)
582  {
583  ret = snprintf(Line, MaxLength, ", VerInfo: %x:%x",
584  Module->Cache->Info.TimeDateStamp, Module->Cache->Info.SizeOfImage);
585 
586  if (ret < 0)
587  {
588  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
589  }
590  else
591  {
592  Line += ret;
593  total += ret;
594  MaxLength -= ret;
595  }
596  }
597 
598  if (Module->Cache && (Module->Cache->Info.IatRva || Module->Cache->Info.IatSize))
599  {
600  ret = snprintf(Line, MaxLength, ", IAT: %x:%x",
601  Module->Cache->Info.IatRva, Module->Cache->Info.IatSize);
602 
603  if (ret < 0)
604  {
605  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
606  }
607  else
608  {
609  Line += ret;
610  total += ret;
611  MaxLength -= ret;
612  }
613  }
614 
615  ret = snprintf(Line, MaxLength, ")");
616  total += ret;
617 
618  return total;
619 }
620 
621 
622 static void
624  _In_ EXCEPTION_VICTIM_ZONE *Victim,
625  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
626  _In_ INTRO_ACTION Action,
628  )
637 {
638  DWORD modNameAlignment;
639  char *l;
640  int ret, rem;
641 
642  // This cannot be NULL! Everything must happen inside a process in user-mode
643  if (NULL == Originator->WinProc)
644  {
645  ERROR("[ERROR] Originator process is NULL!\n");
646  return;
647  }
648 
649  // We will log only the first double agent alert, afterwards we'll only check exceptions
650  if ((Victim->ZoneFlags & ZONE_MODULE_LOAD) != 0 &&
651  Originator->WinLib->DoubleAgentAlertSent)
652  {
653  return;
654  }
655 
656  modNameAlignment = 0;
657  if (Victim->Object.Type == introObjectTypeUmModule)
658  {
659  if (Victim->Object.Library.WinMod && Originator->WinLib)
660  {
661  modNameAlignment = MIN(MAX_PATH,
662  MAX(Victim->Object.Library.WinMod->Path->PathSize,
663  Originator->WinLib->Path->PathSize) >> 1);
664  }
665  }
666 
667  l = gExcLogLine;
668  rem = sizeof(gExcLogLine);
669 
670  if ((Victim->ZoneType == exceptionZoneProcess) ||
671  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
672  (Victim->Object.Type == introObjectTypeSharedUserData))
673  {
674  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Originator->WinProc->ParentEprocess);
675 
676  ret = IntExceptPrintWinProcInfo(Originator->WinProc, "Originator-> Process: ", l, rem, 14);
677  rem -= ret;
678  l += ret;
679 
680  if (Victim->ZoneType == exceptionZoneProcess)
681  {
682  ret = snprintf(l, rem, ", VA: %0*llx", gGuest.WordSize * 2, Originator->SourceVA);
683  }
684  else
685  {
686  ret = snprintf(l, rem, ", RIP: %0*llx", gGuest.WordSize * 2, Originator->Rip);
687  }
688 
689  if (ret < 0)
690  {
691  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
692  }
693  else
694  {
695  rem -= ret;
696  l += ret;
697  }
698 
699  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
700  rem -= ret;
701  l += ret;
702 
703  LOG("%s\n", gExcLogLine);
704 
705  if ((Victim->Object.Type == introObjectTypeUmGenericNxZone ||
706  Victim->Object.Type == introObjectTypeSharedUserData) &&
707  Originator->Return.Library &&
708  Originator->Return.Rip != Originator->Rip)
709  {
710  l = gExcLogLine;
711  rem = sizeof(gExcLogLine);
712 
713  ret = IntExceptPrintWinModInfo(Originator->Return.WinLib,
714  "Return -> Module: ",
715  l,
716  rem,
717  modNameAlignment);
718  rem -= ret;
719  l += ret;
720 
721  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Return.Rip);
722 
723  if (ret < 0)
724  {
725  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
726  }
727  else
728  {
729  rem -= ret;
730  l += ret;
731  }
732 
733  LOG("%s\n", gExcLogLine);
734  }
735  }
736  else if (Victim->Object.Type == introObjectTypeUmModule)
737  {
738  CHAR instr[ND_MIN_BUF_SIZE];
739  NDSTATUS ndstatus;
740 
741  ndstatus = NdToText(Originator->Instruction, Originator->Rip, sizeof(instr), instr);
742  if (!ND_SUCCESS(ndstatus))
743  {
744  memcpy(instr, EXPORT_NAME_UNKNOWN, sizeof(EXPORT_NAME_UNKNOWN));
745  }
746 
747  ret = IntExceptPrintWinModInfo(Originator->WinLib, "Originator-> Module: ", l, rem, modNameAlignment);
748  rem -= ret;
749  l += ret;
750 
751  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Rip);
752 
753  if (ret < 0)
754  {
755  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
756  }
757  else
758  {
759  rem -= ret;
760  l += ret;
761  }
762 
763  ret = IntExceptPrintWinProcInfo(Originator->WinProc, ", Process: ", l, rem, 0);
764  rem -= ret;
765  l += ret;
766 
767  ret = snprintf(l, rem, ", Instr: %s", instr);
768 
769  if (ret < 0)
770  {
771  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
772  }
773  else
774  {
775  rem -= ret;
776  l += ret;
777  }
778 
779  LOG("%s\n", gExcLogLine);
780 
781  if (Originator->Return.Library && Originator->Return.Rip != Originator->Rip)
782  {
783  l = gExcLogLine;
784  rem = sizeof(gExcLogLine);
785 
786  ret = IntExceptPrintWinModInfo(Originator->Return.WinLib,
787  "Return -> Module: ",
788  l,
789  rem,
790  modNameAlignment);
791  rem -= ret;
792  l += ret;
793 
794  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Return.Rip);
795 
796  if (ret < 0)
797  {
798  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
799  }
800  else
801  {
802  rem -= ret;
803  l += ret;
804  }
805 
806  LOG("%s\n", gExcLogLine);
807  }
808  }
809 
810  l = gExcLogLine;
811  rem = sizeof(gExcLogLine);
812 
813  if ((Victim->ZoneType == exceptionZoneProcess) ||
814  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
815  (Victim->Object.Type == introObjectTypeSharedUserData))
816  {
817  WIN_PROCESS_OBJECT *pParent = IntWinProcFindObjectByEprocess(Victim->Object.WinProc->ParentEprocess);
818 
819  ret = IntExceptPrintWinProcInfo(Victim->Object.WinProc, "Victim -> Process: ", l, rem, 14);
820  rem -= ret;
821  l += ret;
822 
823  if (Victim->ZoneType == exceptionZoneProcess)
824  {
825  ret = snprintf(l, rem, ", InjInfo: (%u, %0*llx), Init: (%u, %u)",
826  Victim->Injection.Length, gGuest.WordSize * 2,
827  Victim->Injection.Gva, Victim->Object.WinProc->StartInitializing,
828  Victim->Object.WinProc->Initialized);
829  }
830  else if (Victim->Object.Type == introObjectTypeUmGenericNxZone)
831  {
832 
833  ret = snprintf(l, rem, ", ExecInfo: (0x%0*llx, 0x%0*llx), Stack: (0x%0*llx, 0x%0*llx), SP = 0x%0*llx",
834  gGuest.WordSize * 2, Victim->Ept.Gva, gGuest.WordSize * 2, Victim->Ept.Gpa,
835  gGuest.WordSize * 2, Victim->ExecInfo.StackBase, gGuest.WordSize * 2,
836  Victim->ExecInfo.StackLimit, gGuest.WordSize * 2, Victim->ExecInfo.Rsp);
837  }
838 
839  if (ret < 0)
840  {
841  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
842  }
843  else
844  {
845  rem -= ret;
846  l += ret;
847  }
848 
849  ret = IntExceptPrintWinProcInfo(pParent, ", Parent: ", l, rem, 0);
850  rem -= ret;
851  l += ret;
852 
853  LOG("%s\n", gExcLogLine);
854 
855  if (Victim->Object.Vad)
856  {
857  PWCHAR path = EXCEPTION_NO_WNAME;
858 
859  if (Victim->Object.Vad->Path)
860  {
861  path = Victim->Object.Vad->Path->Path;
862  }
863  else if (Victim->Object.Vad->IsStack)
864  {
865  path = u"<stack>";
866  }
867 
868  LOG("Victim -> VAD: [%llx - %llx], Prot: %x, VadProt: %x, Type: %d, Name: %s\n",
869  Victim->Object.Vad->StartPage, Victim->Object.Vad->EndPage, Victim->Object.Vad->Protection,
870  Victim->Object.Vad->VadProtection, Victim->Object.Vad->VadType, utf16_for_log(path));
871  }
872 
873  if (Victim->Object.Library.WinMod)
874  {
875  QWORD startGva, exportGva;
876  WINUM_CACHE_EXPORT *pExport = NULL;
877 
878  l = gExcLogLine;
879  rem = sizeof(gExcLogLine);
880 
881  ret = IntExceptPrintWinModInfo(Victim->Object.Library.WinMod, "Victim -> Module: ", l, rem, 0);
882  l += ret;
883  rem -= ret;
884 
885  if (Victim->ZoneType == exceptionZoneProcess)
886  {
887  startGva = exportGva = Victim->Injection.Gva;
888  }
889  else
890  {
891  startGva = exportGva = Victim->Ept.Gva;
892  }
893 
894 
895  if (Victim->Object.Library.Export == NULL)
896  {
897  pExport = IntWinUmCacheGetExportFromRange(Victim->Object.Library.WinMod, startGva, 0x20);
898  }
899  else
900  {
901  pExport = Victim->Object.Library.Export;
902  }
903 
904  if (pExport != NULL)
905  {
906  ret = snprintf(l, rem, ", Exports (%u) : [", pExport->NumberOfOffsets);
907  if (ret < 0)
908  {
909  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
910  }
911  else
912  {
913  rem -= ret;
914  l += ret;
915  }
916 
917  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
918  {
919  if (export == pExport->NumberOfOffsets - 1)
920  {
921  ret = snprintf(l, rem, "'%s'", pExport->Names[export]);
922  }
923  else
924  {
925  ret = snprintf(l, rem, "'%s',", pExport->Names[export]);
926  }
927 
928  if (ret < 0)
929  {
930  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
931  }
932  else
933  {
934  rem -= ret;
935  l += ret;
936  }
937 
938  }
939 
940  ret = snprintf(l, rem, "], Delta: +%02x, ",
941  (DWORD)(Victim->Ept.Gva - Victim->Object.Library.WinMod->VirtualBase - pExport->Rva));
942  if (ret < 0)
943  {
944  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
945  }
946  else
947  {
948  rem -= ret;
949  l += ret;
950  }
951  }
952 
953  LOG("%s\n", gExcLogLine);
954  }
955  }
956  else if (Victim->Object.Type == introObjectTypeUmModule)
957  {
958  WINUM_CACHE_EXPORT *pExport = NULL;
959 
960  ret = IntExceptPrintWinModInfo(Victim->Object.Library.WinMod,
961  "Victim -> Module: ",
962  l,
963  rem,
964  modNameAlignment);
965  rem -= ret;
966  l += ret;
967 
968 
969  if (Victim->Object.Library.Export == NULL)
970  {
971  pExport = IntWinUmCacheGetExportFromRange(Victim->Object.Library.WinMod, Victim->Ept.Gva, 0x20);
972  }
973  else
974  {
975  pExport = Victim->Object.Library.Export;
976  }
977 
978  if (pExport != NULL)
979  {
980  ret = snprintf(l, rem, ", Exports (%u) : [", pExport->NumberOfOffsets);
981  if (ret < 0)
982  {
983  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
984  }
985  else
986  {
987  rem -= ret;
988  l += ret;
989  }
990 
991  for (DWORD export = 0; export < pExport->NumberOfOffsets; export++)
992  {
993  if (export == pExport->NumberOfOffsets - 1)
994  {
995  ret = snprintf(l, rem, "'%s'", pExport->Names[export]);
996  }
997  else
998  {
999  ret = snprintf(l, rem, "'%s',", pExport->Names[export]);
1000  }
1001 
1002  if (ret < 0)
1003  {
1004  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1005  }
1006  else
1007  {
1008  rem -= ret;
1009  l += ret;
1010  }
1011 
1012  }
1013 
1014  ret = snprintf(l, rem, "], Delta: +%02x, ",
1015  (DWORD)(Victim->Ept.Gva - Victim->Object.Library.WinMod->VirtualBase - pExport->Rva));
1016  if (ret < 0)
1017  {
1018  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1019  }
1020  else
1021  {
1022  rem -= ret;
1023  l += ret;
1024  }
1025  }
1026 
1027  ret = snprintf(l, rem, ", Address: (%0*llx, %0*llx)",
1028  gGuest.WordSize * 2, Victim->Ept.Gva,
1029  gGuest.WordSize * 2, Victim->Ept.Gpa);
1030  if (ret < 0)
1031  {
1032  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1033  }
1034  else
1035  {
1036  rem -= ret;
1037  l += ret;
1038  }
1039 
1040  ret = snprintf(l, rem, ", WriteInfo: (%u, %016llx -> %016llx)",
1041  Victim->WriteInfo.AccessSize,
1042  Victim->WriteInfo.OldValue[0],
1043  Victim->WriteInfo.NewValue[0]);
1044  if (ret < 0)
1045  {
1046  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1047  }
1048  else
1049  {
1050  rem -= ret;
1051  l += ret;
1052  }
1053 
1054  if (Victim->ZoneFlags)
1055  {
1056  ret = snprintf(l, rem, ", Flags:%s%s%s%s%s (0x%llx)",
1057  (Victim->ZoneFlags & ZONE_LIB_IMPORTS) ? " IMPORTS" : "",
1058  (Victim->ZoneFlags & ZONE_LIB_EXPORTS) ? " EXPORTS" : "",
1059  (Victim->ZoneFlags & ZONE_LIB_CODE) ? " CODE" : "",
1060  (Victim->ZoneFlags & ZONE_LIB_DATA) ? " DATA" : "",
1061  (Victim->ZoneFlags & ZONE_LIB_RESOURCES) ? " RSRC" : "",
1062  (unsigned long long)Victim->ZoneFlags);
1063  if (ret < 0)
1064  {
1065  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1066  }
1067  else
1068  {
1069  rem -= ret;
1070  l += ret;
1071  }
1072  }
1073 
1074  LOG("%s\n", gExcLogLine);
1075  }
1076 
1077  if (Action == introGuestNotAllowed)
1078  {
1079  l = gExcLogLine;
1080  rem = sizeof(gExcLogLine);
1081 
1082  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sMALWARE (user-mode) ",
1083  (Victim->Object.WinProc->BetaDetections) ? " (B) " : " ");
1084  if (ret < 0)
1085  {
1086  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1087  }
1088  else
1089  {
1090  rem -= ret;
1091  l += ret;
1092  }
1093 
1094  switch (Reason)
1095  {
1097  ret = snprintf(l, rem, "(no sig)");
1098  break;
1100  ret = snprintf(l, rem, "(no exc)");
1101  break;
1103  ret = snprintf(l, rem, "(extra)");
1104  break;
1106  ret = snprintf(l, rem, "(error)");
1107  break;
1109  ret = snprintf(l, rem, "(value)");
1110  break;
1112  ret = snprintf(l, rem, "(value code)");
1113  break;
1115  ret = snprintf(l, rem, "(export)");
1116  break;
1118  ret = snprintf(l, rem, "(idt)");
1119  break;
1121  ret = snprintf(l, rem, "(version os)");
1122  break;
1124  ret = snprintf(l, rem, "(version intro)");
1125  break;
1127  ret = snprintf(l, rem, "(process creation)");
1128  break;
1129  case introReasonUnknown:
1130  ret = snprintf(l, rem, "(unknown)");
1131  break;
1132  default:
1133  ret = snprintf(l, rem, "(%d)", Reason);
1134  break;
1135  }
1136 
1137  if (ret < 0)
1138  {
1139  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1140  }
1141  else
1142  {
1143  rem -= ret;
1144  l += ret;
1145  }
1146 
1147  snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1148 
1149  LOG("%s\n\n", gExcLogLine);
1150  }
1151 
1152  if (Victim->Object.Type == introObjectTypeProcessCreationDpi)
1153  {
1154  if (Originator->PcType == INT_PC_VIOLATION_DPI_DEBUG_FLAG)
1155  {
1156  WIN_PROCESS_OBJECT *pDebugged = Victim->Object.Process;
1157  WIN_PROCESS_OBJECT *pDebugger;
1158 
1160  if (NULL == pDebugger)
1161  {
1162  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) is debugged by process %s!\n",
1163  pDebugged->Name, pDebugged->NameHash, pDebugged->Pid, pDebugged->EprocessAddress, "<unknown>");
1164  }
1165  else
1166  {
1167  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) is debugged by process %s [0x%08x] (%d, 0x%016llx)!\n",
1168  pDebugged->Name, pDebugged->NameHash, pDebugged->Pid, pDebugged->EprocessAddress,
1169  pDebugger->Name, pDebugger->NameHash, pDebugger->Pid, pDebugger->EprocessAddress);
1170  }
1171  }
1172  else if (Originator->PcType == INT_PC_VIOLATION_DPI_PIVOTED_STACK)
1173  {
1174  WIN_PROCESS_OBJECT *pParent = Victim->Object.Process;
1175  WIN_PROCESS_OBJECT *pStarted = Originator->Process;
1176 
1177  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) attempted to start process %s [0x%08x] "
1178  "(%d, 0x%016llx) with a pivoted stack!\n",
1179  pParent->Name, pParent->NameHash, pParent->Pid, pParent->EprocessAddress,
1180  pStarted->Name, pStarted->NameHash, pStarted->Pid, pStarted->EprocessAddress);
1181 
1182  LOG("[DPI] Current stack 0x%016llx [base 0x%016llx, limit 0x%016llx], wow64 "
1183  "stack 0x%016llx [base 0x%016llx, limit 0x%016llx]\n",
1190 
1191  if (gGuest.Guest64)
1192  {
1193  KTRAP_FRAME64 *trapFrame = NULL;
1194  INTSTATUS status;
1195 
1197  sizeof(*trapFrame),
1199  0,
1200  &trapFrame);
1201 
1202  if (!INT_SUCCESS(status))
1203  {
1204  ERROR("[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n",
1206  status);
1207 
1208  goto _skip_trap_frame;
1209  }
1210 
1211  IntDumpWinTrapFrame64(trapFrame);
1212 
1213  IntVirtMemUnmap(&trapFrame);
1214  }
1215  else
1216  {
1217  KTRAP_FRAME32 *trapFrame = NULL;
1218  INTSTATUS status;
1219 
1221  sizeof(*trapFrame),
1223  0,
1224  &trapFrame);
1225 
1226  if (!INT_SUCCESS(status))
1227  {
1228  ERROR("[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n",
1230  status);
1231 
1232  goto _skip_trap_frame;
1233  }
1234 
1235  IntDumpWinTrapFrame32(trapFrame);
1236 
1237  IntVirtMemUnmap(&trapFrame);
1238  }
1239 
1240 _skip_trap_frame:
1241  ;
1242  }
1243  else if (Originator->PcType == INT_PC_VIOLATION_DPI_STOLEN_TOKEN)
1244  {
1245  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1246  WIN_PROCESS_OBJECT *pStolenFrom =
1248 
1249  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started with "
1250  "a stolen token from %s [0x%08x] (%d, 0x%016llx)!\n",
1251  pOriginator->Name, pOriginator->NameHash, pOriginator->Pid, pOriginator->EprocessAddress,
1252  pStolenFrom->Name, pStolenFrom->NameHash, pStolenFrom->Pid, pStolenFrom->EprocessAddress);
1253  }
1254  else if (Originator->PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
1255  {
1256  WIN_PROCESS_OBJECT *pHeapSprayed = Victim->Object.Process;
1257  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1258  WORD maxNumberOfHeapVals = 0;
1259  DWORD detectedPage = 0, maxPageHeapVals = 0;
1260 
1261  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s "
1262  "[0x%08x] (%d, 0x%016llx) after it has been heap sprayed! (shell code flags: 0x%016llx)\n",
1263  pOriginator->Name,
1264  pOriginator->NameHash,
1265  pOriginator->Pid,
1266  pOriginator->EprocessAddress,
1267  pHeapSprayed->Name,
1268  pHeapSprayed->NameHash,
1269  pHeapSprayed->Pid,
1270  pHeapSprayed->EprocessAddress,
1272 
1273  for (DWORD val = 1; val <= HEAP_SPRAY_NR_PAGES; val++)
1274  {
1275  DWORD checkedPage = ((val << 24) | (val << 16) | (val << 8) | val) & PAGE_MASK;
1276 
1277  LOG("[DPI] For page 0x%08x, %s %s %s (offset 0x%03x), number of heap values: %d\n",
1278  checkedPage,
1279  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped ?
1280  "was mapped" : "was not mapped",
1281  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected ?
1282  "was detected" : "was not detected",
1283  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable ?
1284  "executable" : "not executable",
1285  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset,
1286  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount);
1287 
1288  if (pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
1289  {
1290  detectedPage = checkedPage;
1291  }
1292 
1293  // Use >= so that we are sure that we will get at least one page even if there are no heap values.
1294  if (pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount
1295  >= maxNumberOfHeapVals &&
1296  pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
1297  {
1298  maxNumberOfHeapVals =
1299  (WORD)pOriginator->DpiExtraInfo.DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1300  maxPageHeapVals = checkedPage;
1301  }
1302  }
1303 
1304  LOG("[INFO] Page detected: 0x%08x, maximum number of heap values: 0x%08x (%d)\n",
1305  detectedPage, maxPageHeapVals, maxNumberOfHeapVals);
1306 
1307  // At this point we might not have a detected page, but only pages that exceed the max heap values
1308  // heuristic, so don't bother to dump it if it is equal to zero.
1309  if (0 != detectedPage)
1310  {
1311  LOG("[INFO] Dumping page: 0x%08x...\n", detectedPage);
1312 
1313  IntDumpGva(detectedPage, PAGE_SIZE, pHeapSprayed->Cr3);
1314  }
1315 
1316  if (detectedPage != maxPageHeapVals)
1317  {
1318  LOG("[INFO] Dumping page: 0x%08x...\n", maxPageHeapVals);
1319 
1320  IntDumpGva(maxPageHeapVals, PAGE_SIZE, pHeapSprayed->Cr3);
1321  }
1322  }
1323  else if (Originator->PcType == INT_PC_VIOLATION_DPI_TOKEN_PRIVS)
1324  {
1325  WIN_PROCESS_OBJECT *pVictim = Victim->Object.Process;
1326  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1327 
1328  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s [0x%08x] (%d, 0x%016llx) "
1329  "after it didn't pass privileges checks!\n",
1330  pOriginator->Name,
1331  pOriginator->NameHash,
1332  pOriginator->Pid,
1333  pOriginator->EprocessAddress,
1334  pVictim->Name,
1335  pVictim->NameHash,
1336  pVictim->Pid,
1337  pVictim->EprocessAddress);
1338 
1339  LOG("[DPI] Privileges: Enabled: old: 0x%016llx, new: 0x%016llx, Present: old: 0x%016llx, new: 0x%016llx\n",
1344  }
1345  else if (Originator->PcType == INT_PC_VIOLATION_DPI_THREAD_START)
1346  {
1347  WIN_PROCESS_OBJECT *pVictim = Victim->Object.Process;
1348  WIN_PROCESS_OBJECT *pOriginator = Originator->Process;
1349 
1350  LOG("[DPI] Process %s [0x%08x] (%d, 0x%016llx) started from %s "
1351  "[0x%08x] (%d, 0x%016llx) from a thread considered suspicious (start 0x%016llx, shellcode flags: 0x%016llx)!\n",
1352  pOriginator->Name,
1353  pOriginator->NameHash,
1354  pOriginator->Pid,
1355  pOriginator->EprocessAddress,
1356  pVictim->Name,
1357  pVictim->NameHash,
1358  pVictim->Pid,
1359  pVictim->EprocessAddress,
1362 
1364  PAGE_SIZE,
1365  pVictim->Cr3);
1366  }
1367  else
1368  {
1369  ERROR("[ERROR] Victim has type introObjectTypeProcessCreationDpi but no known flag was given, "
1370  "flags: 0x%x\n", Originator->PcType);
1371  }
1372  }
1373 }
1374 
1375 
1376 static __inline BOOLEAN
1378  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1379  _In_ DWORD ZoneFlags
1380  )
1389 {
1390  BOOLEAN match = FALSE;
1391 
1392  if ((ZoneFlags & EXCEPTION_FLG_READ) &&
1393  (Victim->ZoneFlags & ZONE_READ))
1394  {
1395  match = TRUE;
1396  }
1397 
1398  if ((ZoneFlags & EXCEPTION_FLG_EXECUTE) &&
1399  (Victim->ZoneFlags & ZONE_EXECUTE))
1400  {
1401  match = TRUE;
1402  }
1403 
1404  if ((ZoneFlags & EXCEPTION_FLG_WRITE) &&
1405  (Victim->ZoneFlags & ZONE_WRITE))
1406  {
1407  match = TRUE;
1408  }
1409 
1410  return match;
1411 }
1412 
1413 
1414 
1415 static __inline BOOLEAN
1417  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1418  _In_ UM_EXCEPTION_OBJECT ZoneType
1419  )
1428 {
1429  BOOLEAN match = FALSE;
1430 
1431  switch (ZoneType)
1432  {
1433  case umObjAny:
1434  match = TRUE;
1435  break;
1436 
1437  // We want to match only object_type process, not thread-context or thread-apc
1438  case umObjProcess:
1439  if (Victim->ZoneType == exceptionZoneProcess &&
1440  (Victim->ZoneFlags & (ZONE_PROC_THREAD_CTX | ZONE_PROC_THREAD_APC)) == 0)
1441  {
1442  match = TRUE;
1443  }
1444  break;
1445 
1446  case umObjModule:
1447  if (Victim->Object.Type == introObjectTypeUmModule)
1448  {
1449  match = TRUE;
1450  }
1451  break;
1452 
1453  case umObjModuleImports:
1454  if ((Victim->Object.Type == introObjectTypeUmModule) &&
1455  (Victim->ZoneFlags & ZONE_LIB_IMPORTS))
1456  {
1457  match = TRUE;
1458  }
1459  break;
1460 
1461  case umObjNxZone:
1462  if (Victim->Object.Type == introObjectTypeUmGenericNxZone)
1463  {
1464  match = TRUE;
1465  }
1466  break;
1467 
1468  case umObjSharedUserData:
1469  if (Victim->Object.Type == introObjectTypeSharedUserData)
1470  {
1471  match = TRUE;
1472  }
1473  break;
1474 
1475  case umObjModuleExports:
1476  if ((Victim->Object.Type == introObjectTypeUmModule) &&
1477  (Victim->ZoneFlags & ZONE_LIB_EXPORTS))
1478  {
1479  match = TRUE;
1480  }
1481  break;
1482 
1484  if ((Victim->ZoneType == exceptionZoneProcess) &&
1485  (Victim->ZoneFlags & ZONE_PROC_THREAD_CTX))
1486  {
1487  match = TRUE;
1488  }
1489  break;
1490 
1491  case umObjProcessApcThread:
1492  if ((Victim->ZoneType == exceptionZoneProcess) &&
1493  (Victim->ZoneFlags & ZONE_PROC_THREAD_APC))
1494  {
1495  match = TRUE;
1496  }
1497  break;
1498 
1499  case umObjProcessPeb32:
1500  if (Victim->Injection.Gva >= Victim->Object.WinProc->Peb32Address &&
1501  Victim->Injection.Gva < Victim->Object.WinProc->Peb32Address + WIN_UM_FIELD(Peb, 32Size))
1502  {
1503  match = TRUE;
1504  }
1505  break;
1506 
1507  case umObjProcessPeb64:
1508  if (Victim->Injection.Gva >= Victim->Object.WinProc->Peb64Address &&
1509  Victim->Injection.Gva < Victim->Object.WinProc->Peb64Address + WIN_UM_FIELD(Peb, 64Size))
1510  {
1511  match = TRUE;
1512  }
1513  break;
1514 
1515  case umObjProcessCreation:
1516  if (Victim->Object.Type == introObjectTypeProcessCreation)
1517  {
1518  match = TRUE;
1519  }
1520  break;
1521 
1523  if (Victim->Object.Type == introObjectTypeProcessCreationDpi)
1524  {
1525  match = TRUE;
1526  }
1527  break;
1528 
1529  case umObjModuleLoad:
1530  if ((Victim->ZoneType == exceptionZoneProcess) &&
1531  (Victim->ZoneFlags & ZONE_MODULE_LOAD))
1532  {
1533  match = TRUE;
1534  }
1535  break;
1536 
1537  default:
1538  LOG("[ERROR] This is a corruption in the update/exception. Type = %d!\n", ZoneType);
1539  break;
1540  }
1541 
1542  return match;
1543 }
1544 
1545 
1546 static __inline BOOLEAN
1548  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1549  _In_ DWORD ExceptionFlags
1550  )
1559 {
1560  BOOLEAN match = FALSE;
1561 
1562  if ((ExceptionFlags & EXCEPTION_FLG_32) &&
1563  (ExceptionFlags & EXCEPTION_FLG_64))
1564  {
1565  match = TRUE;
1566  }
1567  else
1568  {
1570  {
1571  if (ExceptionFlags & EXCEPTION_FLG_32)
1572  {
1573  // 32-bit windows OR a 32-bit process in a 64-bit system
1574  match = !gGuest.Guest64 || Originator->WinProc->Wow64Process;
1575  }
1576  else if (ExceptionFlags & EXCEPTION_FLG_64)
1577  {
1578  // 64-bit windows AND a 64-bit process
1579  match = gGuest.Guest64 && !Originator->WinProc->Wow64Process;
1580  }
1581  }
1582  else if (gGuest.OSType == introGuestLinux)
1583  {
1584  // Only Linux don't check the process subsystem
1585  if (ExceptionFlags & EXCEPTION_FLG_32)
1586  {
1587  match = !gGuest.Guest64;
1588  }
1589  else if (ExceptionFlags & EXCEPTION_FLG_64)
1590  {
1591  match = gGuest.Guest64;
1592  }
1593  }
1594  }
1595 
1596  return match;
1597 }
1598 
1599 
1600 
1601 static __inline BOOLEAN
1603  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1604  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1605  _In_ DWORD ExceptionFlags
1606  )
1616 {
1617  BOOLEAN match = TRUE;
1618 
1619  if ((Victim->ZoneType == exceptionZoneProcess) &&
1620  (ExceptionFlags & EXCEPTION_UM_FLG_CHILD_PROC))
1621  {
1623  {
1624  if (Victim->Object.WinProc->ParentEprocess != Originator->WinProc->EprocessAddress)
1625  {
1626  return FALSE;
1627  }
1628  }
1629  else
1630  {
1631  if (Victim->Object.LixProc->ActualParent != Originator->LixProc->Gva)
1632  {
1633  return FALSE;
1634  }
1635  }
1636  }
1637 
1638  return match;
1639 }
1640 
1641 
1642 
1643 static __inline BOOLEAN
1645  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1646  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1647  _In_ DWORD ExceptionFlags
1648  )
1661 {
1662  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_SYS_PROC))
1663  {
1664  //
1665  // This exception only matches if the originator process is a system process
1666  //
1667  if (Victim->Object.Type == introObjectTypeProcessCreation)
1668  {
1669  if (!Victim->Object.WinProc->SystemProcess)
1670  {
1671  return FALSE;
1672  }
1673  }
1674  else
1675  {
1676  if (!Originator->WinProc->SystemProcess)
1677  {
1678  return FALSE;
1679  }
1680  }
1681  }
1682 
1683  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_LIKE_APPHELP))
1684  {
1685  if ((Victim->Object.WinProc->InjectedApphelpAddress != Victim->Injection.Gva) ||
1686  (Victim->Object.WinProc->InjectedAppHelpSize != Victim->Injection.Length))
1687  {
1688  return FALSE;
1689  }
1690  }
1691 
1692  if ((gGuest.OSType == introGuestWindows) && (ExceptionFlags & EXCEPTION_UM_FLG_ONETIME))
1693  {
1694  if (Victim->Object.Type == introObjectTypeProcessCreation)
1695  {
1696  if (Originator->WinProc->OneTimeInjectionDone)
1697  {
1698  return FALSE;
1699  }
1700  else
1701  {
1702  Originator->WinProc->OneTimeInjectionDone = TRUE;
1703  }
1704  }
1705  else
1706  {
1707  if (Victim->Object.WinProc->OneTimeInjectionDone)
1708  {
1709  return FALSE;
1710  }
1711  else
1712  {
1713  Victim->Object.WinProc->OneTimeInjectionDone = TRUE;
1714  }
1715  }
1716  }
1717 
1718  return TRUE;
1719 }
1720 
1721 
1722 static __inline BOOLEAN
1724  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1725  _In_ UM_EXCEPTION_GLOB *Exception
1726  )
1735 {
1736  BOOLEAN match = FALSE;
1737 
1738  if (Victim->ZoneFlags & (ZONE_LIB_CODE | ZONE_LIB_EXPORTS | ZONE_LIB_IMPORTS | ZONE_LIB_DATA))
1739  {
1740  // We use WCHAR for module names
1741  match = glob_match_utf16(Exception->Victim.NameGlob, Victim->Object.NameWide, TRUE, TRUE);
1742  }
1743  else
1744  {
1745  match = glob_match_utf8(Exception->Victim.NameGlob, Victim->Object.Name, TRUE, TRUE);
1746  }
1747 
1748  return match;
1749 }
1750 
1751 
1752 static __inline BOOLEAN
1754  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1755  _In_ UM_EXCEPTION_GLOB *Exception
1756  )
1766 {
1767  BOOLEAN match = FALSE;
1768 
1770  {
1771  match = glob_match_utf8(Exception->Victim.ProcessGlob, Originator->WinProc->Name, TRUE, TRUE);
1772  }
1773  else if (Originator->LixProc->Path)
1774  {
1775  match = glob_match_utf8(Exception->Victim.ProcessGlob, Originator->LixProc->Path->Name, TRUE, TRUE);
1776  }
1777 
1778  return match;
1779 }
1780 
1781 
1782 
1783 static __inline BOOLEAN
1785  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1786  _In_ UM_EXCEPTION *Exception
1787  )
1796 {
1797  return (Exception->Victim.NameHash == umExcNameAny ||
1798  Exception->Victim.NameHash == Victim->Object.NameHash);
1799 }
1800 
1801 
1802 static __inline BOOLEAN
1804  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1805  _In_ UM_EXCEPTION *Exception
1806  )
1816 {
1817  BOOLEAN match = FALSE;
1818 
1819  if (Exception->Victim.ProcessHash == umExcNameAny)
1820  {
1821  match = TRUE;
1822  }
1823  else
1824  {
1826  {
1827  match = Exception->Victim.ProcessHash == Originator->WinProc->NameHash;
1828  }
1829  else
1830  {
1831  match = Exception->Victim.ProcessHash == Originator->LixProc->CommHash;
1832  }
1833  }
1834 
1835  return match;
1836 }
1837 
1838 
1839 
1840 static __forceinline BOOLEAN
1842  _In_ char Item
1843  )
1851 {
1852  return ((Item == '*') || (Item == '?') || (Item == ']') || (Item == '[') || (Item == '/'));
1853 }
1854 
1855 
1856 void
1858  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1859  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
1860  _In_ INTRO_ACTION Action,
1861  _In_ INTRO_ACTION_REASON Reason
1862  )
1871 {
1872  if ((introGuestNotAllowed != Action) && (introReasonAllowedFeedback != Reason))
1873  {
1874  return;
1875  }
1876 
1877  if (Victim->Object.Type == introObjectTypeUmGenericNxZone && gVcpu->Regs.Cr3 != Victim->Object.WinProc->Cr3)
1878  {
1879  return;
1880  }
1881 
1883  {
1884  IntExceptUserLogWindowsInformation(Victim, Originator, Action, Reason);
1885  }
1886  else if (gGuest.OSType == introGuestLinux)
1887  {
1888  IntExceptUserLogLinuxInformation(Victim, Originator, Action, Reason);
1889  }
1890 
1891  if ((Victim->Object.Type == introObjectTypeUmModule) ||
1892  (Victim->Object.Type == introObjectTypeUmGenericNxZone) ||
1893  (Victim->Object.Type == introObjectTypeSharedUserData))
1894  {
1895  IntExceptDumpSignatures(Originator, Victim, FALSE, FALSE);
1896  }
1897 
1898  BOOLEAN logInjection = (Victim->ZoneType == exceptionZoneProcess);
1899 
1900  // Don't dump lsass reads (we don't want our log to be mimikatz)
1901  if (logInjection && gGuest.OSType == introGuestWindows)
1902  {
1903  if (Victim->Object.WinProc->Lsass && (Victim->ZoneFlags & ZONE_READ))
1904  {
1905  logInjection = FALSE;
1906  }
1907  }
1908 
1909  if (logInjection && Originator->Process)
1910  {
1911  QWORD cr3 = 0;
1912 
1914  {
1915  cr3 = Originator->WinProc->Cr3;
1916  }
1917  else if (gGuest.OSType == introGuestLinux)
1918  {
1919  cr3 = Originator->LixProc->Cr3;
1920  }
1921 
1922  // If we could read the whole buffer when checking for value signatures, dump that
1923  if (Victim->Injection.Buffer &&
1924  Victim->Injection.BufferSize == Victim->Injection.Length)
1925  {
1926  IntDumpBuffer(Victim->Injection.Buffer,
1927  Originator->SourceVA,
1928  Victim->Injection.BufferSize,
1929  16,
1930  sizeof(BYTE),
1931  TRUE,
1932  TRUE);
1933  }
1934  else if ((Victim->ZoneFlags & (ZONE_PROC_THREAD_CTX | ZONE_PROC_THREAD_APC | ZONE_MODULE_LOAD)) == 0)
1935  {
1936  IntDumpGva(Originator->SourceVA,
1937  Victim->Injection.Length,
1938  cr3);
1939  }
1940  }
1941 }
1942 
1943 
1944 INTSTATUS
1946  _In_ void *Process,
1947  _Out_ EXCEPTION_UM_ORIGINATOR *Originator
1948  )
1957 {
1958  STACK_TRACE stack;
1959  STACK_ELEMENT stackElements[8];
1960 
1961  Originator->Process = Process;
1962  Originator->Library = NULL;
1963  Originator->Rip = gVcpu->Regs.Rip;
1964  Originator->Execute = TRUE;
1965  Originator->NameHash = INITIAL_CRC_VALUE; // The code is executed from the heap
1966 
1968  {
1969  INTSTATUS status;
1970 
1971  memzero(&stack, sizeof(stack));
1972  stack.Traces = stackElements;
1973 
1974  status = IntWinStackTraceGetUser(&gVcpu->Regs, Process, ARRAYSIZE(stackElements), &stack);
1975  if (!INT_SUCCESS(status) && 0 == stack.NumberOfTraces)
1976  {
1977  WARNING("[WARNING] IntWinStackTraceGetUser failed: %08x\n", status);
1978  }
1979 
1980  if (stack.NumberOfTraces > 0)
1981  {
1982  Originator->Return.Rip = stack.Traces[0].ReturnAddress;
1983  Originator->Return.Library = stack.Traces[0].ReturnModule;
1984  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->NameHash;
1985  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->Name;
1986  }
1987  }
1988 
1989  Originator->Instruction = &gVcpu->Instruction;
1990 
1991  return INT_STATUS_SUCCESS;
1992 }
1993 
1994 
1995 static INTSTATUS
1997  _In_ WIN_PROCESS_OBJECT *Process,
1998  _In_opt_ WIN_PROCESS_MODULE *Module,
1999  _Inout_ EXCEPTION_UM_ORIGINATOR *Originator
2000  )
2016 {
2017  INTSTATUS status;
2018  STACK_ELEMENT stackElements[8];
2019  STACK_TRACE stack;
2020  BOOLEAN isUcrtbase = FALSE;
2021 
2022  if (NULL == Module)
2023  {
2024  goto _get_stack;
2025  }
2026 
2027 #define MEMORY_FUNC_SIZE 0x400
2028 
2029  isUcrtbase = 0 == wstrcasecmp(Module->Path->Name, u"ucrtbase.dll");
2030 
2031  if (Module->Path->NameHash == NAMEHASH_NTDLL)
2032  {
2033  DWORD rva = (DWORD)(Originator->Rip - Module->VirtualBase);
2034  BOOLEAN foundMemFunc = FALSE;
2035 
2036  if (NULL == Module->Cache || !Module->Cache->MemoryFuncsRead)
2037  {
2039  }
2040 
2041  for (DWORD i = 0; i < ARRAYSIZE(Module->Cache->MemFuncs.FuncArray); i++)
2042  {
2043  if (0 == Module->Cache->MemFuncs.FuncArray[i])
2044  {
2045  continue;
2046  }
2047 
2048  if (rva > Module->Cache->MemFuncs.FuncArray[i] &&
2049  rva < Module->Cache->MemFuncs.FuncArray[i] + MEMORY_FUNC_SIZE)
2050  {
2051  foundMemFunc = TRUE;
2052  }
2053  }
2054 
2055  if (!foundMemFunc)
2056  {
2058  }
2059  }
2060  // Note: here we want to match "the first N bytes", not to match the whole module
2061  else if (((Module->Path->NameSize < 10 || 0 != memcmp(Module->Path->Name, u"msvcr", 10)) &&
2062  (Module->Path->NameSize < 18 || 0 != memcmp(Module->Path->Name, u"vcruntime", 18))) &&
2063  !isUcrtbase)
2064  {
2066  }
2067 
2068 _get_stack:
2069  memzero(&stack, sizeof(stack));
2070  stack.Traces = stackElements;
2071 
2072  status = IntWinStackTraceGetUser(&gVcpu->Regs,
2073  Process,
2074  ARRAYSIZE(stackElements),
2075  &stack);
2076  if (!INT_SUCCESS(status) &&
2077  stack.NumberOfTraces == 0)
2078  {
2079  if (Module != NULL)
2080  {
2081  ERROR("[ERROR] IntWinStackTraceGetUser failed: %08x\n", status);
2082  }
2083 
2084  return status;
2085  }
2086 
2087  if (stack.Bits64 && !isUcrtbase && !Process->ExploitGuardEnabled)
2088  {
2089  // On 64-bit we can only trust the first return
2090  if (stack.Traces[0].ReturnModule == Module)
2091  {
2092  return INT_STATUS_SUCCESS;
2093  }
2094 
2095  Originator->Return.Rip = stack.Traces[0].ReturnAddress;
2096  Originator->Return.Library = stack.Traces[0].ReturnModule;
2097  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->NameHash;
2098 
2099  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[0].ReturnModule)->Path->Name;
2100 
2101  return INT_STATUS_SUCCESS;
2102  }
2103 
2104  // Dirty little hack for Exploit Guard. Some hooks are set by payloadrestrictions.dll using ucrtbase!memset
2105  // In these cases we can see other modules on the stack, besides payloadrestrictions.dll so first we search for it
2106  // and if that fails, we go with the first module we found
2107  if (isUcrtbase && Process->ExploitGuardEnabled)
2108  {
2109  for (DWORD i = 0; i < stack.NumberOfTraces; i++)
2110  {
2112 
2113  if (stack.Traces[i].ReturnModule == Module)
2114  {
2115  continue;
2116  }
2117 
2118  if (wstrcasecmp(pModule->Path->Name, u"payloadrestrictions.dll"))
2119  {
2120  continue;
2121  }
2122 
2123  Originator->Return.Rip = stack.Traces[i].ReturnAddress;
2124  Originator->Return.Library = pModule;
2125  Originator->Return.NameHash = pModule->Path->NameHash;
2126  Originator->Return.NameWide = pModule->Path->Name; // Module names are saved as WCHAR
2127 
2128  return INT_STATUS_SUCCESS;
2129  }
2130  }
2131 
2132  for (DWORD i = 0; i < stack.NumberOfTraces; i++)
2133  {
2134  // NOTE: Only on msvcr* it's relevant like this. On ntdll we must be able to know memcpy*, memset*, memmov*.
2135  if (stack.Traces[i].ReturnModule == Module)
2136  {
2137  continue;
2138  }
2139 
2140  Originator->Return.Rip = stack.Traces[i].ReturnAddress;
2141  Originator->Return.Library = stack.Traces[i].ReturnModule;
2142  Originator->Return.NameHash = ((PWIN_PROCESS_MODULE)stack.Traces[i].ReturnModule)->Path->NameHash;
2143  Originator->Return.NameWide = ((PWIN_PROCESS_MODULE)stack.Traces[i].ReturnModule)->Path->Name;
2144 
2145  break;
2146  }
2147 
2148  return INT_STATUS_SUCCESS;
2149 
2150 #undef MEMORY_FUNC_SIZE
2151 }
2152 
2153 
2154 INTSTATUS
2156  _In_ void *Process,
2157  _In_ BOOLEAN ModuleWrite,
2158  _In_ QWORD Address,
2159  _In_opt_ INSTRUX *Instrux,
2160  _Out_ EXCEPTION_UM_ORIGINATOR *Originator
2161  )
2175 {
2176  if (NULL == Process)
2177  {
2179  }
2180 
2181  if (NULL == Originator)
2182  {
2184  }
2185 
2186  Originator->Process = Process;
2187  Originator->Library = NULL;
2188  Originator->Execute = FALSE;
2189 
2190  if (ModuleWrite && gGuest.OSType == introGuestWindows)
2191  {
2192  INTSTATUS status;
2193  WIN_PROCESS_MODULE *pMod = IntWinUmModFindByAddress(Process, Address);
2194 
2195  Originator->Rip = Address;
2196  Originator->Instruction = Instrux;
2197 
2198  Originator->Library = pMod;
2199  if (NULL != Originator->Library)
2200  {
2201  Originator->NameHash = Originator->WinLib->Path->NameHash;
2202  Originator->NameWide = Originator->WinLib->Path->Name;
2203  }
2204  else
2205  {
2206  Originator->NameHash = INITIAL_CRC_VALUE;
2207  Originator->Name = NULL;
2208  }
2209 
2210  status = IntExceptUserHandleMemoryFunctions(Process, pMod, Originator);
2211  if (!INT_SUCCESS(status))
2212  {
2213  WARNING("[WARNING] IntExceptUserHandleMemoryFunctions failed: %08x\n", status);
2214  }
2215  }
2216  else if (ModuleWrite && gGuest.OSType == introGuestLinux)
2217  {
2218  Originator->Rip = Address;
2219  Originator->Instruction = Instrux;
2220 
2221  Originator->NameHash = INITIAL_CRC_VALUE;
2222  Originator->Name = NULL;
2223  }
2224  else if (!ModuleWrite)
2225  {
2226  Originator->SourceVA = Address;
2227 
2229  {
2230  Originator->NameHash = ((WIN_PROCESS_OBJECT *)Process)->NameHash;
2231  Originator->Name = ((WIN_PROCESS_OBJECT *)Process)->Name; // Process names are saved as char
2232  }
2233  else if (gGuest.OSType == introGuestLinux)
2234  {
2235  Originator->NameHash = ((LIX_TASK_OBJECT *)Process)->CommHash;
2236  Originator->Name = ((LIX_TASK_OBJECT *)Process)->Comm; // Linux uses only char
2237  }
2238  }
2239 
2240  return INT_STATUS_SUCCESS;
2241 }
2242 
2243 
2244 INTSTATUS
2246  _In_ void *Process,
2247  _In_ INTRO_OBJECT_TYPE ObjectType,
2249  )
2263 {
2264  if (Process == NULL)
2265  {
2267  }
2268 
2269  if (ObjectType != introObjectTypeProcessCreation && ObjectType != introObjectTypeProcessCreationDpi)
2270  {
2272  }
2273 
2274  if (Victim == NULL)
2275  {
2277  }
2278 
2279  Victim->Object.Type = ObjectType;
2280  Victim->Object.Process = Process;
2281 
2282  Victim->ZoneFlags = ZONE_EXECUTE;
2283  Victim->ZoneType = exceptionZoneProcess;
2284 
2286  {
2287  WIN_PROCESS_OBJECT *pProcess = (WIN_PROCESS_OBJECT *)(Process);
2288 
2289  Victim->Object.BaseAddress = pProcess->Cr3;
2290  Victim->Object.NameHash = pProcess->NameHash;
2291  Victim->Object.Name = pProcess->Name;
2292  }
2293  else if (gGuest.OSType == introGuestLinux)
2294  {
2295  LIX_TASK_OBJECT *pTask = (LIX_TASK_OBJECT *)(Process);
2296 
2297  Victim->Object.BaseAddress = pTask->Cr3;
2298  Victim->Object.NameHash = pTask->CommHash;
2299  Victim->Object.Name = pTask->Comm;
2300  }
2301 
2302  return INT_STATUS_SUCCESS;
2303 }
2304 
2305 
2306 INTSTATUS
2308  _In_ void *Process,
2309  _In_ QWORD DestinationGva,
2310  _In_ DWORD Length,
2311  _In_ QWORD ZoneFlags,
2313  )
2327 {
2328  if (NULL == Process)
2329  {
2331  }
2332 
2333  if (NULL == Victim)
2334  {
2336  }
2337 
2338  Victim->ZoneType = exceptionZoneProcess;
2339 
2340  Victim->ZoneFlags = ZoneFlags;
2341 
2342  Victim->Injection.Gva = DestinationGva;
2343  Victim->Injection.Length = Length;
2344 
2345  Victim->Object.Process = Process;
2346 
2348  {
2349  WIN_PROCESS_OBJECT *pProc = Process;
2350 
2351  Victim->Object.BaseAddress = pProc->Cr3;
2352  Victim->Object.NameHash = pProc->NameHash;
2353  Victim->Object.Name = pProc->Name; // Process names are saved as CHAR
2354 
2355  if (pProc->MonitorVad)
2356  {
2357  Victim->Object.Vad = IntWinVadFindAndUpdateIfNecessary(pProc, DestinationGva, Length);
2358  }
2359 
2360  if (pProc->MonitorModules && (!pProc->MonitorVad || Victim->Object.Vad))
2361  {
2362  WIN_PROCESS_MODULE *pMod = IntWinUmModFindByAddress(pProc, DestinationGva);
2363  Victim->Object.Library.Module = pMod;
2364 
2365  if (pMod != NULL)
2366  {
2367  Victim->Object.Library.Export = IntWinUmCacheGetExportFromRange(pMod, DestinationGva, 0x20);
2368  }
2369  }
2370  }
2371  else if (gGuest.OSType == introGuestLinux)
2372  {
2373  LIX_TASK_OBJECT *pTask = Process;
2374 
2375  Victim->Object.BaseAddress = pTask->Cr3;
2376  Victim->Object.NameHash = pTask->CommHash;
2377  Victim->Object.Name = pTask->Comm; // Linux uses only CHAR
2378  }
2379 
2380  return INT_STATUS_SUCCESS;
2381 }
2382 
2383 
2384 INTSTATUS
2386  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2387  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2388  _In_ UM_EXCEPTION *Exception
2389  )
2400 {
2402  {
2403  if ((Exception->Type == umObjProcess) &&
2404  (Exception->Flags & EXCEPTION_FLG_INIT))
2405  {
2406  return IntWinUmCheckInitializationInjection(Victim, Originator);
2407  }
2408  }
2409 
2411 }
2412 
2413 
2414 INTSTATUS
2416  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2417  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2418  _In_ UM_EXCEPTION_GLOB *Exception
2419  )
2430 {
2432  {
2433  if ((Exception->Type == umObjProcess) &&
2434  (Exception->Flags & EXCEPTION_FLG_INIT))
2435  {
2436  return IntWinUmCheckInitializationInjection(Victim, Originator);
2437  }
2438  }
2439 
2441 }
2442 
2443 
2444 INTSTATUS
2446  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2447  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2448  _In_ void *Exception,
2449  _In_ EXCEPTION_TYPE ExceptionType
2450  )
2472 {
2473  switch (ExceptionType)
2474  {
2475  case exceptionTypeUm:
2476  if (!IntExceptUserMatchZoneFlags(Victim, ((UM_EXCEPTION *)Exception)->Flags))
2477  {
2479  }
2480  break;
2481  case exceptionTypeUmGlob:
2482  if (!IntExceptUserMatchZoneFlags(Victim, ((UM_EXCEPTION_GLOB *)Exception)->Flags))
2483  {
2485  }
2486  break;
2487 
2488  default:
2489  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2490  return INT_STATUS_NOT_SUPPORTED;
2491  }
2492 
2493  switch (ExceptionType)
2494  {
2495  case exceptionTypeUm:
2496  if (!IntExceptUserMatchNameHash(Victim, Exception))
2497  {
2499  }
2500  break;
2501 
2502  case exceptionTypeUmGlob:
2503  if (!IntExceptUserMatchNameGlob(Victim, Exception))
2504  {
2506  }
2507  break;
2508 
2509  default:
2510  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2511  return INT_STATUS_NOT_SUPPORTED;
2512  }
2513 
2514  // Check if we are in the right process. This makes sense only for EPT violations (injections are cross-process,
2515  // so the ProcessHash will be forced to umExcNameAny). In cases of EPT violations, the originator process and
2516  // modified process are the same, so take the process name from the originator.
2517  switch (ExceptionType)
2518  {
2519  case exceptionTypeUm:
2520  if (!IntExceptUserMatchProcessHash(Originator, Exception))
2521  {
2523  }
2524  break;
2525 
2526  case exceptionTypeUmGlob:
2527  if (!IntExceptUserMatchProcessGlob(Originator, (UM_EXCEPTION_GLOB *)(Exception)))
2528  {
2530  }
2531  break;
2532 
2533  default:
2534  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2535  return INT_STATUS_NOT_SUPPORTED;
2536  }
2537 
2538  switch (ExceptionType)
2539  {
2540  case exceptionTypeUm:
2541  if (!IntExceptUserMatchZoneType(Victim, ((UM_EXCEPTION *)(Exception))->Type))
2542  {
2544  }
2545  break;
2546 
2547  case exceptionTypeUmGlob:
2548  if (!IntExceptUserMatchZoneType(Victim, ((UM_EXCEPTION_GLOB *)(Exception))->Type))
2549  {
2551  }
2552  break;
2553 
2554  default:
2555  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2556  return INT_STATUS_NOT_SUPPORTED;
2557  }
2558 
2559  switch (ExceptionType)
2560  {
2561  case exceptionTypeUm:
2562  if (!IntExceptUserMatchArchitecture(Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2563  {
2565  }
2566  break;
2567 
2568  case exceptionTypeUmGlob:
2569  if (!IntExceptUserMatchArchitecture(Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2570  {
2572  }
2573  break;
2574 
2575  default:
2576  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2577  return INT_STATUS_NOT_SUPPORTED;
2578  }
2579 
2580  switch (ExceptionType)
2581  {
2582  case exceptionTypeUm:
2583  if (!IntExceptUserMatchChild(Victim, Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2584  {
2586  }
2587  break;
2588 
2589  case exceptionTypeUmGlob:
2590  if (!IntExceptUserMatchChild(Victim, Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2591  {
2593  }
2594  break;
2595 
2596  default:
2597  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2598  return INT_STATUS_NOT_SUPPORTED;
2599  }
2600 
2601  switch (ExceptionType)
2602  {
2603  case exceptionTypeUm:
2604  if (!IntExceptUserMatchSystemProcess(Victim, Originator, ((UM_EXCEPTION *)(Exception))->Flags))
2605  {
2607  }
2608  break;
2609 
2610  case exceptionTypeUmGlob:
2611  if (!IntExceptUserMatchSystemProcess(Victim, Originator, ((UM_EXCEPTION_GLOB *)(Exception))->Flags))
2612  {
2614  }
2615  break;
2616 
2617  default:
2618  ERROR("[ERROR] Shouldn't reach here. Exception Type is %d...\n", ExceptionType);
2619  return INT_STATUS_NOT_SUPPORTED;
2620  }
2621 
2622  // If we get here, then allow the action. Anyway, the extra checks & signatures mechanism will actually allow it
2624 }
2625 
2626 
2627 INTSTATUS
2629  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2630  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2631  _Out_ INTRO_ACTION *Action,
2632  _Out_ INTRO_ACTION_REASON *Reason
2633  )
2652 {
2653  INTSTATUS status;
2654  static BOOLEAN showNotLoadedWarning = TRUE;
2655  BYTE id;
2656 
2657  if (NULL == Victim)
2658  {
2660  }
2661 
2662  if (NULL == Originator)
2663  {
2665  }
2666 
2667  if (NULL == Action)
2668  {
2670  }
2671 
2672  if (NULL == Reason)
2673  {
2675  }
2676 
2677  if (NULL == gGuest.Exceptions || !gGuest.Exceptions->Loaded)
2678  {
2679  if (showNotLoadedWarning)
2680  {
2681  LOG("**************************************************\n");
2682  LOG("************Exceptions are not loaded*************\n");
2683  LOG("**************************************************\n");
2684 
2685  showNotLoadedWarning = FALSE;
2686  }
2687 
2688  *Action = introGuestAllowed;
2690 
2692  }
2693 
2694  *Action = introGuestNotAllowed;
2695  *Reason = introReasonNoException;
2696 
2698 
2700  {
2701  if (pEx->OriginatorNameHash == umExcNameAny)
2702  {
2703  // For now, we do not support exceptions from the alert that has originator umExcNameAny.
2704  // If an exception from the alert has no originator, umExcNoName will be used as the exception originator
2705  goto _match_ex_alert;
2706  }
2707 
2708  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
2709  {
2710  goto _match_ex_alert;
2711  }
2712 
2713  if (pEx->OriginatorNameHash > Originator->NameHash)
2714  {
2715  break;
2716  }
2717  else if (pEx->OriginatorNameHash != Originator->NameHash)
2718  {
2719  continue;
2720  }
2721 
2722 _match_ex_alert:
2723  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2724  if (status == INT_STATUS_EXCEPTION_ALLOW)
2725  {
2726  return status;
2727  }
2728  }
2729 
2730  if (Victim->Object.Type == introObjectTypeProcessCreation)
2731  {
2733  {
2734  if (pEx->OriginatorNameHash == umExcNameAny)
2735  {
2736  goto _match_ex_alert_process;
2737  }
2738 
2739  // Every list is ordered, so break when we got to a hash bigger than ours
2740  if (pEx->OriginatorNameHash > Originator->NameHash)
2741  {
2742  break;
2743  }
2744  else if (pEx->OriginatorNameHash < Originator->NameHash)
2745  {
2746  continue;
2747  }
2748 
2749 _match_ex_alert_process:
2750  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2751  if (status == INT_STATUS_EXCEPTION_ALLOW)
2752  {
2753  return status;
2754  }
2755  }
2756 
2758  {
2759  if (pEx->OriginatorNameHash == umExcNameAny)
2760  {
2761  goto _match_ex_process;
2762  }
2763 
2764  // Every list is ordered, so break when we got to a hash bigger than ours
2765  if (pEx->OriginatorNameHash > Originator->NameHash)
2766  {
2767  break;
2768  }
2769  else if (pEx->OriginatorNameHash < Originator->NameHash)
2770  {
2771  continue;
2772  }
2773 
2774 _match_ex_process:
2775  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2776  if (status == INT_STATUS_EXCEPTION_ALLOW)
2777  {
2778  return status;
2779  }
2780  }
2781  }
2782 
2783  if (Originator->NameHash == INITIAL_CRC_VALUE)
2784  {
2785  // Check the no name exceptions
2787  {
2788  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2789  if (status == INT_STATUS_EXCEPTION_ALLOW)
2790  {
2791  RemoveEntryList(&pEx->Link);
2793 
2794  return status;
2795  }
2796  }
2797  }
2798  else
2799  {
2800  // Check the generic exceptions (all of them, since originator matches anything)
2802  {
2803  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2804  if (status == INT_STATUS_EXCEPTION_ALLOW)
2805  {
2806  RemoveEntryList(&pEx->Link);
2808 
2809  return status;
2810  }
2811  }
2812  }
2813 
2814  if (Originator->Name != NULL)
2815  {
2817 
2819  {
2820  if ((Originator->Name[0] < pEx->OriginatorNameGlob[0]) &&
2821  !IntExceptUserIsGlobItem(pEx->OriginatorNameGlob[0]))
2822  {
2823  break;
2824  }
2825 
2826  if ((Originator->Name[0] != pEx->OriginatorNameGlob[0]) &&
2827  !IntExceptUserIsGlobItem(pEx->OriginatorNameGlob[0]))
2828  {
2829  continue;
2830  }
2831 
2832  if (Originator->Library == NULL && Originator->Name != NULL)
2833  {
2834  if (!glob_match_utf8(pEx->OriginatorNameGlob, Originator->Name, TRUE, TRUE))
2835  {
2836  continue;
2837  }
2838  }
2839  else if (Originator->Library != NULL && Originator->NameWide != NULL)
2840  {
2841  if (!glob_match_utf16(pEx->OriginatorNameGlob, Originator->NameWide, TRUE, TRUE))
2842  {
2843  continue;
2844  }
2845  }
2846  else
2847  {
2848  continue;
2849  }
2850 
2851  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUmGlob, Action, Reason);
2852  if (status == INT_STATUS_EXCEPTION_ALLOW)
2853  {
2854  TRACE("[EXCEPTION] IntExceptMatchException (GLOB) returned INT_STATUS_EXCEPTION_ALLOW.");
2855  return status;
2856  }
2857  }
2858 
2860  }
2861 
2862  if (Originator->NameHash != INITIAL_CRC_VALUE)
2863  {
2864  id = EXCEPTION_TABLE_ID(Originator->NameHash);
2865 
2867  {
2868  // Every list is ordered, so break when we got to a hash bigger than ours
2869  if (pEx->OriginatorNameHash > Originator->NameHash)
2870  {
2871  break;
2872  }
2873  else if (pEx->OriginatorNameHash < Originator->NameHash)
2874  {
2875  continue;
2876  }
2877 
2878  if (pEx->Flags & EXCEPTION_FLG_RETURN)
2879  {
2880  continue;
2881  }
2882 
2883  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2884  if (status == INT_STATUS_EXCEPTION_ALLOW)
2885  {
2886  return status;
2887  }
2888  }
2889  }
2890 
2891  if (Originator->Library && Originator->Return.Library &&
2892  (Originator->Rip == Originator->Return.Rip))
2893  {
2894  goto _beta_exceptions;
2895  }
2896 
2897  id = EXCEPTION_TABLE_ID(Originator->Return.NameHash);
2899  {
2900  // Every list is ordered, so break when we got to a hash bigger than ours
2901  if (pEx->OriginatorNameHash > Originator->Return.NameHash)
2902  {
2903  break;
2904  }
2905  else if (pEx->OriginatorNameHash < Originator->Return.NameHash)
2906  {
2907  continue;
2908  }
2909 
2910  if (0 == (pEx->Flags & EXCEPTION_FLG_RETURN))
2911  {
2912  continue;
2913  }
2914 
2915  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2916  if (status == INT_STATUS_EXCEPTION_ALLOW)
2917  {
2918  return status;
2919  }
2920  }
2921 
2922 _beta_exceptions:
2924  {
2925  if (pEx->OriginatorNameHash == umExcNameAny)
2926  {
2927  goto _match_ex;
2928  }
2929 
2930  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
2931  {
2932  goto _match_ex;
2933  }
2934 
2935  if (pEx->Flags & EXCEPTION_FLG_RETURN)
2936  {
2937  if (pEx->OriginatorNameHash != Originator->Return.NameHash)
2938  {
2939  continue;
2940  }
2941  }
2942  else
2943  {
2944  if (pEx->OriginatorNameHash != Originator->NameHash)
2945  {
2946  continue;
2947  }
2948  }
2949 
2950 _match_ex:
2951  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2952  if (status == INT_STATUS_EXCEPTION_ALLOW)
2953  {
2954  return status;
2955  }
2956  }
2957 
2959  {
2960  if (pEx->OriginatorNameHash == umExcNameAny)
2961  {
2962  goto _match_process_beta_ex;
2963  }
2964 
2965  if (Originator->NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == umExcNameNone)
2966  {
2967  goto _match_process_beta_ex;
2968  }
2969 
2970  if (pEx->Flags & EXCEPTION_FLG_RETURN)
2971  {
2972  if (pEx->OriginatorNameHash != Originator->Return.NameHash)
2973  {
2974  continue;
2975  }
2976  }
2977  else
2978  {
2979  if (pEx->OriginatorNameHash != Originator->NameHash)
2980  {
2981  continue;
2982  }
2983  }
2984 
2985 _match_process_beta_ex:
2986  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeUm, Action, Reason);
2987  if (status == INT_STATUS_EXCEPTION_ALLOW)
2988  {
2989  return status;
2990  }
2991  }
2992 
2993  return status;
2994 }
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:219
#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
_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.
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:161
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:1531
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:207
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
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
#define STATS_EXIT(id)
Definition: stats.h:148
#define ZONE_LIB_RESOURCES
Used for the resources section (usually .rsrc inside a driver or dll).
Definition: exceptions.h:691
User-mode exception.
Definition: exceptions.h:61
User-mode non executable zone.
Definition: intro_types.h:244
LIST_HEAD GenericUserExceptions
Linked list used for user-mode exceptions that have a generic originator(*).
Definition: exceptions.h:92
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:259
The modified object is anything inside the structure CONTEXT (valid only for windows).
Definition: exceptions.h:211
QWORD Wow64StackLimit
The known stack limit in WoW64 mode. Valid only if the process is WoW64.
Definition: windpi.h:44
LIST_HEAD ProcessCreationAlertExceptions
Linked list used for process-creation exceptions that are added from alert.
Definition: exceptions.h:123
QWORD NewEnabled
The new value from parent&#39;s token Privileges.Enabled field, which was deemed malicious.
Definition: windpi.h:74
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:764
The exception will take into consideration the return driver/dll.
Definition: exceptions.h:591
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:718
#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
#define ARRAYSIZE(A)
Definition: introdefs.h:101
#define INT_STATUS_EXCEPTION_CHECKS_OK
Definition: introstatus.h:396
Describe a user-mode glob exception.
Definition: exceptions.h:326
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:595
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
Process creation violation DPI.
Definition: intro_types.h:262
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:125
Describes a user-mode originator.
Definition: exceptions.h:933
#define for_each_um_exception(_ex_head, _var_name)
Definition: exceptions.h:1002
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:652
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:110
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:3127
int INTSTATUS
The status data type.
Definition: introstatus.h:24
BOOLEAN Loaded
True if the exceptions are loaded.
Definition: exceptions.h:147
DWORD NameHash
Name hash, as used by the exceptions module.
Definition: winprocess.h:99
The exception will match only for the init phase of a driver/process.
Definition: exceptions.h:589
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:611
#define ONE_KILOBYTE
Definition: introdefs.h:89
QWORD DebuggerEprocess
This will keep the EPROCESS of the debugger process (if any).
Definition: winprocess.h:278
#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:63
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...
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:274
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:596
#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:657
#define LOG(fmt,...)
Definition: glue.h:61
The modified object is only another process (injection basically).
Definition: exceptions.h:205
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:1975
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:96
struct _DPI_EXTRA_INFO::@202 DpiHeapSprayExtraInfo
enum _INTRO_OBJECT_TYPE INTRO_OBJECT_TYPE
The type of the object protected by an EPT hook.
#define _Inout_
Definition: intro_sal.h:20
struct _DPI_EXTRA_INFO::@200 DpiPivotedStackExtraInfo
#define ZONE_LIB_CODE
Used for a generic code zone.
Definition: exceptions.h:688
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:388
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:141
#define MEMORY_FUNC_SIZE
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:700
The parent of a process has a stolen access token when it created the child.
Definition: intro_types.h:1528
#define memzero(a, s)
Definition: introcrt.h:35
The exception is valid only for execute violation.
Definition: exceptions.h:597
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:286
#define ZONE_PROC_THREAD_APC
Used for the APC thread hijacking technique.
Definition: exceptions.h:694
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:106
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:1534
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:1525
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.
#define TRACE(fmt,...)
Definition: glue.h:58
Executions inside the SharedUserData region.
Definition: intro_types.h:264
#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:292
QWORD ReturnAddress
The address where the current stack frame will return (@ ret)
Definition: guest_stack.h:34
QWORD NewPresent
The new value from parent&#39;s token Privileges.Present field, which was deemed malicious.
Definition: windpi.h:77
struct _DPI_EXTRA_INFO::@204 DpiThreadStartExtraInfo
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:694
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:363
The modified object is anything inside of the PEB32 structure.
Definition: exceptions.h:212
#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:98
#define ZONE_LIB_EXPORTS
Used for the exports of a dll, driver, etc.
Definition: exceptions.h:687
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:53
The modified object is inside the process module&#39;s IAT.
Definition: exceptions.h:207
Describes the modified zone.
Definition: exceptions.h:847
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
Definition: winumpath.h:23
QWORD OldEnabled
Definition: windpi.h:72
#define __forceinline
Definition: introtypes.h:61
Describe a user-mode exception.
Definition: exceptions.h:298
DWORD Rva
The RVA of this export.
Definition: winumcache.h:23
uint16_t WCHAR
Definition: intro_types.h:63
uint32_t DWORD
Definition: intro_types.h:49
QWORD StackBase
The known stack base present in TIB at the moment of process creation.
Definition: windpi.h:37
LIST_HEAD GlobUserExceptions
Linked list used for user-mode exceptions that contains glob content.
Definition: exceptions.h:106
#define EXCEPTION_NO_WNAME
Definition: exceptions.h:29
struct _DPI_EXTRA_INFO::@202::@205 HeapPages[HEAP_SPRAY_NR_PAGES]
User-mode library.
Definition: intro_types.h:245
#define for_each_um_glob_exception(_ex_head, _var_name)
Definition: exceptions.h:1004
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:111
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...
struct _DPI_EXTRA_INFO::@201 DpiStolenTokenExtraInfo
struct _DPI_EXTRA_INFO::@203 DpiTokenPrivsExtraInfo
The exception is valid only if the modified process is a child of the originator process.
Definition: exceptions.h:613
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:221
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
__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:689
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:370
struct _WIN_PROCESS_OBJECT::@227 CreationInfo
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:88
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:1522
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
The modified object is inside a process.
Definition: exceptions.h:714
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:2106
The modified object is inside the process modules.
Definition: exceptions.h:206
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:249
LIST_HEAD ProcessCreationFeedbackExceptions
Linked list used for process-creation exceptions that have the feedback flag.
Definition: exceptions.h:120
#define EXCEPTION_TABLE_ID(H)
Definition: exceptions.h:51
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:23
TIMER_FRIENDLY void IntDumpBuffer(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
LIST_HEAD UserFeedbackExceptions
Linked list used for user-mode exceptions that have the feedback flag.
Definition: exceptions.h:114
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1537
Virtual SYSCALL (user-mode, Linux-only)
Definition: intro_types.h:254
#define PROC_OPT_BETA
Process is monitored, but in log-only mode so no actions will be blocked.
Definition: intro_types.h:363
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:699
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:160
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:2938
Virtual dynamic shared object (user-mode, Linux-only)
Definition: intro_types.h:253
The modified object is any with the modified name.
Definition: exceptions.h:204
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:1023
#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:57
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:215
#define ZONE_PROC_THREAD_CTX
Used for the CONTEXT structure of a thread.
Definition: exceptions.h:693
#define ZONE_LIB_IMPORTS
Used for the imports of a dll, driver, etc.
Definition: exceptions.h:686
Structure that describes a stack trace.
Definition: guest_stack.h:42
The exception is valid only on 32 bit systems/process.
Definition: exceptions.h:586
#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:616
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:696
#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:698
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
The exception is valid only once.
Definition: exceptions.h:615
LIST_HEAD NoNameUserExceptions
Linked list used for user-mode exceptions that don&#39;t have a valid originator (-). ...
Definition: exceptions.h:100
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:1502
The process object creates another process using DPI flags.
Definition: exceptions.h:220
The object that has a NX zone is executed.
Definition: exceptions.h:208
#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:81
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