Bitdefender Hypervisor Memory Introspection
exceptions_kern.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
10 
11 #include "exceptions.h"
12 #include "guests.h"
13 #include "lixstack.h"
14 #include "winpe.h"
15 #include "winstack.h"
16 #include "lixksym.h"
17 
18 
19 extern char gExcLogLine[2 * ONE_KILOBYTE];
20 
21 
22 static int
24  _In_ KERNEL_DRIVER *Driver,
25  _In_ char *Header,
26  _Out_ char *Line,
27  _In_ int MaxLength,
28  _In_opt_ DWORD NameAlignment
29  )
41 {
42  int ret, total = 0;
43 
44  if (NULL == Driver)
45  {
46  return snprintf(Line, MaxLength, "%s(%s)", Header, EXCEPTION_NO_NAME);
47  }
48 
49  if (*(char *)Driver->Name)
50  {
51  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, (char *)Driver->Name);
52  }
53  else
54  {
55  ret = snprintf(Line, MaxLength, "%s(%s", Header, EXCEPTION_NO_NAME);
56  }
57 
58  if (ret < 0)
59  {
60  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
61  }
62  else
63  {
64  Line += ret;
65  total += ret;
66  MaxLength -= ret;
67  }
68 
69  ret = snprintf(Line, MaxLength, " [0x%08x], %016llx", Driver->NameHash, Driver->BaseVa);
70 
71  if (ret < 0)
72  {
73  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
74  }
75  else
76  {
77  Line += ret;
78  total += ret;
79  MaxLength -= ret;
80  }
81 
82  ret = snprintf(Line, MaxLength, ")");
83  total += ret;
84 
85  return total;
86 }
87 
88 
89 int
91  _In_ KERNEL_DRIVER *Module,
92  _In_ char *Header,
93  _Out_ char *Line,
94  _In_ int MaxLength,
95  _In_opt_ DWORD NameAlignment
96  )
108 {
109  int ret, total = 0;
110  WCHAR *wName;
111  char name[MAX_PATH];
112 
113  if (NULL == Module)
114  {
115  return snprintf(Line, MaxLength, "%s(%s)", Header, EXCEPTION_NO_NAME);
116  }
117 
118  wName = Module->Win.Path ? Module->Win.Path : Module->Name ? Module->Name : NULL;
119 
120  if (wName)
121  {
122  utf16toutf8(name, wName, sizeof(name));
123  }
124  else
125  {
126  memcpy(name, EXCEPTION_NO_NAME, sizeof(EXCEPTION_NO_NAME));
127  }
128 
129  if (NameAlignment)
130  {
131  ret = snprintf(Line, MaxLength, "%s(%-*s", Header, NameAlignment, name);
132  }
133  else
134  {
135  ret = snprintf(Line, MaxLength, "%s(%s", Header, name);
136  }
137 
138  if (ret < 0)
139  {
140  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
141  }
142  else
143  {
144  Line += ret;
145  total += ret;
146  MaxLength -= ret;
147  }
148 
149  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx", Module->NameHash, gGuest.WordSize * 2, Module->BaseVa);
150  if (ret < 0)
151  {
152  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
153  }
154  else
155  {
156  Line += ret;
157  total += ret;
158  MaxLength -= ret;
159  }
160 
161  if (Module->Win.TimeDateStamp)
162  {
163  ret = snprintf(Line, MaxLength, ", VerInfo: %x:%llx", Module->Win.TimeDateStamp, Module->Size);
164 
165  if (ret < 0)
166  {
167  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
168  }
169  else
170  {
171  Line += ret;
172  total += ret;
173  MaxLength -= ret;
174  }
175  }
176 
177  ret = snprintf(Line, MaxLength, ")");
178  total += ret;
179 
180  return total;
181 }
182 
183 
184 static int
186  _In_ EXCEPTION_VICTIM_ZONE *Victim,
187  _In_ char *Header,
188  _Out_ char *Line,
189  _In_ int MaxLength
190  )
201 {
202  const char *msrName = NULL;
203  int ret = 0, total = 0;
204 
205  ret = snprintf(Line, MaxLength, "%s: (%08x", Header, Victim->Msr.Msr);
206 
207  if (ret < 0)
208  {
209  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
210  }
211  else
212  {
213  MaxLength -= ret;
214  Line += ret;
215  total += ret;
216  }
217 
218  if (Victim->Msr.Msr == IG_IA32_SYSENTER_CS)
219  {
220  msrName = "SYSENTER_CS";
221  }
222  else if (Victim->Msr.Msr == IG_IA32_SYSENTER_ESP)
223  {
224  msrName = "SYSENTER_ESP";
225  }
226  else if (Victim->Msr.Msr == IG_IA32_SYSENTER_EIP)
227  {
228  msrName = "SYSENTER_EIP";
229  }
230  else if (Victim->Msr.Msr == IG_IA32_STAR)
231  {
232  msrName = "STAR";
233  }
234  else if (Victim->Msr.Msr == IG_IA32_LSTAR)
235  {
236  msrName = "LSTAR";
237  }
238 
239  if (msrName)
240  {
241  ret = snprintf(Line, MaxLength, ", %s", msrName);
242 
243  if (ret < 0)
244  {
245  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
246  }
247  else
248  {
249  MaxLength -= ret;
250  Line += ret;
251  total += ret;
252  }
253  }
254 
255  ret = snprintf(Line, MaxLength, ")");
256 
257  if (ret < 0)
258  {
259  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
260  }
261  else
262  {
263  MaxLength -= ret;
264  Line += ret;
265  total += ret;
266  }
267 
268  ret = snprintf(Line, MaxLength, ", WriteInfo: (%016llx -> %016llx)",
269  Victim->WriteInfo.OldValue[0],
270  Victim->WriteInfo.NewValue[0]);
271  if (ret < 0)
272  {
273  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
274  }
275  else
276  {
277  MaxLength -= ret;
278  Line += ret;
279  total += ret;
280  }
281 
282  if (Victim->Msr.NewDriverBase)
283  {
284  KERNEL_DRIVER *pMsrDrv = IntDriverFindByAddress(Victim->Msr.NewDriverBase);
285 
287  {
288  ret = IntExceptPrintWinKmModInfo(pMsrDrv, ", Module: ", Line, MaxLength, 0);
289  MaxLength -= ret;
290  Line += ret;
291  total += ret;
292  }
293  else if (gGuest.OSType == introGuestLinux)
294  {
295  ret = IntExceptPrintLixKmDrvInfo(pMsrDrv, ", Module: ", Line, MaxLength, 0);
296  MaxLength -= ret;
297  Line += ret;
298  total += ret;
299 
300  if (pMsrDrv == gGuest.KernelDriver)
301  {
302  char symbol[LIX_SYMBOL_NAME_LEN];
303 
304  INTSTATUS status = IntKsymFindByAddress(Victim->WriteInfo.NewValue[0],
305  sizeof(symbol),
306  symbol,
307  NULL,
308  NULL);
309  if (!INT_SUCCESS(status))
310  {
311  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
312  }
313 
314  ret = snprintf(Line, MaxLength, ", %s", symbol);
315 
316  if (ret < 0)
317  {
318  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
319  }
320  else
321  {
322  MaxLength -= ret;
323  Line += ret;
324  total += ret;
325  }
326  }
327  }
328  }
329 
330  return total;
331 }
332 
333 
334 static int
336  _In_ EXCEPTION_VICTIM_ZONE *Victim,
337  _In_ char *Header,
338  _Out_ char *Line,
339  _In_ int MaxLength
340  )
351 {
352  int ret = 0, total = 0;
353 
354  ret = snprintf(Line, MaxLength, "%s%u", Header, Victim->Cr.Cr);
355 
356  if (ret < 0)
357  {
358  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
359  }
360  else
361  {
362  MaxLength -= ret;
363  Line += ret;
364  total += ret;
365  }
366 
367  if (Victim->Cr.Smep && Victim->Cr.Smap)
368  {
369  ret = snprintf(Line, MaxLength, ", (SMAP, SMEP)");
370 
371  if (ret < 0)
372  {
373  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
374  }
375  else
376  {
377  MaxLength -= ret;
378  Line += ret;
379  total += ret;
380  }
381  }
382  else if (Victim->Cr.Smap)
383  {
384  ret = snprintf(Line, MaxLength, ", (SMEP)");
385 
386  if (ret < 0)
387  {
388  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
389  }
390  else
391  {
392  MaxLength -= ret;
393  Line += ret;
394  total += ret;
395  }
396  }
397  else if (Victim->Cr.Smep)
398  {
399  ret = snprintf(Line, MaxLength, ", (SMAP)");
400 
401  if (ret < 0)
402  {
403  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
404  }
405  else
406  {
407  MaxLength -= ret;
408  Line += ret;
409  total += ret;
410  }
411  }
412 
413  ret = snprintf(Line, MaxLength, ", WriteInfo: (%u, %016llx -> %016llx)",
414  Victim->WriteInfo.AccessSize,
415  Victim->WriteInfo.OldValue[0],
416  Victim->WriteInfo.NewValue[0]);
417  if (ret < 0)
418  {
419  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
420  }
421  else
422  {
423  MaxLength -= ret;
424  Line += ret;
425  total += ret;
426  }
427 
428  return total;
429 }
430 
431 
432 static int
434  _In_ EXCEPTION_VICTIM_ZONE *Victim,
435  _In_ char *Header,
436  _Out_ char *Line,
437  _In_ int MaxLength
438  )
449 {
450  int ret = 0, total = 0;
451  QWORD entry, entryNo;
452  char *prot;
453 
454  if (Victim->ZoneType == exceptionZoneIntegrity)
455  {
456  entry = Victim->Object.BaseAddress + Victim->Integrity.Offset;
457  entryNo = Victim->Integrity.Offset / (gGuest.Guest64 ? DESCRIPTOR_SIZE_64 : DESCRIPTOR_SIZE_32);
458  prot = "INTEGRITY";
459  }
460  else
461  {
462  entry = Victim->Ept.Gva;
463  entryNo = (Victim->Ept.Gva - Victim->Object.BaseAddress) /
465  prot = "EPT";
466  }
467 
468  ret = snprintf(Line, MaxLength, "%s (IDT Base Address: %llx, IDT Entry modified: %llu (0x%016llx) (%s)",
469  Header, Victim->Object.BaseAddress, entryNo, entry, prot);
470  if (ret < 0)
471  {
472  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
473  }
474  else
475  {
476  MaxLength -= ret;
477  Line += ret;
478  total += ret;
479  }
480 
481  ret = snprintf(Line, MaxLength, ", WriteInfo: (%u", Victim->WriteInfo.AccessSize);
482  if (ret < 0)
483  {
484  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
485  }
486  else
487  {
488  MaxLength -= ret;
489  Line += ret;
490  total += ret;
491  }
492 
493  for (DWORD i = 0; i * sizeof(Victim->WriteInfo.NewValue[0]) < Victim->WriteInfo.AccessSize; i++)
494  {
495  ret = snprintf(Line, MaxLength, ", %016llx -> 0x%016llx",
496  Victim->WriteInfo.OldValue[i],
497  Victim->WriteInfo.NewValue[i]);
498  if (ret < 0)
499  {
500  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
501  }
502  else
503  {
504  MaxLength -= ret;
505  Line += ret;
506  total += ret;
507  }
508  }
509 
510  ret = snprintf(Line, MaxLength, ")");
511  if (ret < 0)
512  {
513  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
514  }
515  else
516  {
517  MaxLength -= ret;
518  Line += ret;
519  total += ret;
520  }
521 
522  return total;
523 }
524 
525 
526 static int
528  _In_ EXCEPTION_VICTIM_ZONE *Victim,
529  _In_ char *Header,
530  _Out_ char *Line,
531  _In_ int MaxLength
532  )
543 {
544  const char *dtrName = NULL;
545  int ret = 0, total = 0;
546 
547  ret = snprintf(Line, MaxLength, "%s(", Header);
548 
549  if (ret < 0)
550  {
551  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
552  }
553  else
554  {
555  MaxLength -= ret;
556  Line += ret;
557  total += ret;
558  }
559 
560  if (Victim->Dtr.Type == introObjectTypeIdtr)
561  {
562  dtrName = "IDTR";
563  }
564  else if (Victim->Dtr.Type == introObjectTypeGdtr)
565  {
566  dtrName = "GDTR";
567  }
568  else
569  {
570  dtrName = "Unknown";
571  }
572 
573  ret = snprintf(Line, MaxLength, "%s", dtrName);
574 
575  if (ret < 0)
576  {
577  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
578  }
579  else
580  {
581  MaxLength -= ret;
582  Line += ret;
583  total += ret;
584  }
585 
586  ret = snprintf(Line, MaxLength, ")");
587 
588  if (ret < 0)
589  {
590  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
591  }
592  else
593  {
594  MaxLength -= ret;
595  Line += ret;
596  total += ret;
597  }
598 
599  ret = snprintf(Line, MaxLength, ", WriteInfo: (%016llx -> %016llx)",
600  Victim->WriteInfo.OldValue[0],
601  Victim->WriteInfo.NewValue[0]);
602  if (ret < 0)
603  {
604  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
605  }
606  else
607  {
608  MaxLength -= ret;
609  Line += ret;
610  total += ret;
611  }
612 
613  ret = snprintf(Line, MaxLength, ", DtrLimit: (%04llx -> %04llx)",
614  Victim->WriteInfo.OldValue[1],
615  Victim->WriteInfo.NewValue[1]);
616  if (ret < 0)
617  {
618  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
619  }
620  else
621  {
622  MaxLength -= ret;
623  Line += ret;
624  total += ret;
625  }
626 
627  return total;
628 }
629 
630 
631 static void
633  _In_ EXCEPTION_VICTIM_ZONE *Victim,
634  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
635  _In_ INTRO_ACTION Action,
637  )
646 {
647  KERNEL_DRIVER *pDriver, *pRetDriver;
648  char symbol[LIX_SYMBOL_NAME_LEN];
649  DWORD modNameAlignment;
650  INTSTATUS status;
651  char *l;
652  int ret, rem;
653 
654  pDriver = Originator->Original.Driver;
655  pRetDriver = Originator->Return.Driver;
656 
657  modNameAlignment = 0;
658  if (Victim->Object.Type == introObjectTypeKmModule)
659  {
660  KERNEL_DRIVER *pModDriver = Victim->Object.Module.Module;
661 
662  if (pModDriver && pDriver && pRetDriver)
663  {
664  modNameAlignment = (DWORD)MIN(MAX_PATH, MAX(pModDriver->NameLength, pDriver->NameLength));
665  }
666 
667  if (pModDriver && pRetDriver)
668  {
669  if (modNameAlignment > 0)
670  {
671  modNameAlignment = (DWORD)MIN(MAX_PATH, MAX(pRetDriver->NameLength, modNameAlignment));
672  }
673  else
674  {
675  modNameAlignment = (DWORD)MIN(MAX_PATH, MAX(pModDriver->NameLength, pRetDriver->NameLength));
676  }
677  }
678  }
679 
680  l = gExcLogLine;
681  rem = sizeof(gExcLogLine);
682 
683  if (Victim->ZoneType == exceptionZoneIntegrity)
684  {
685  // No point in logging anything else, since the RIP is unknown
686  IntExceptPrintLixKmDrvInfo(pDriver, "Originator-> Module: ", l, rem, modNameAlignment);
687 
688  LOG("%s\n", gExcLogLine);
689  }
690  else
691  {
692  char instr[ND_MIN_BUF_SIZE];
693  LIX_TASK_OBJECT *pTask;
694 
695  if (Originator->Instruction)
696  {
697  NDSTATUS s = NdToText(Originator->Instruction, Originator->Original.Rip, sizeof(instr), instr);
698  if (!ND_SUCCESS(s))
699  {
700  memcpy(instr, EXPORT_NAME_UNKNOWN, sizeof(EXPORT_NAME_UNKNOWN));
701  }
702  }
703  else
704  {
705  memcpy(instr, EXCEPTION_NO_INSTRUCTION, sizeof(EXCEPTION_NO_INSTRUCTION));
706  }
707 
708  if (pDriver == gGuest.KernelDriver)
709  {
710  status = IntKsymFindByAddress(Originator->Original.Rip, sizeof(symbol), symbol, NULL, NULL);
711  if (!INT_SUCCESS(status))
712  {
713  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
714  }
715  }
716  else
717  {
718  symbol[0] = 0;
719  }
720 
721  ret = IntExceptPrintLixKmDrvInfo(pDriver, "Originator-> Module: ", l, rem, modNameAlignment);
722  rem -= ret;
723  l += ret;
724 
725  ret = snprintf(l, rem, ", RIP %016llx", Originator->Original.Rip);
726 
727  if (ret < 0)
728  {
729  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
730  }
731  else
732  {
733  rem -= ret;
734  l += ret;
735  }
736 
737  if (Originator->Original.Section[0] != 0)
738  {
739  ret = snprintf(l, rem, " (%s)", Originator->Original.Section);
740 
741  if (ret < 0)
742  {
743  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
744  }
745  else
746  {
747  rem -= ret;
748  l += ret;
749  }
750  }
751 
752  if (symbol[0] != 0)
753  {
754  ret = snprintf(l, rem, " (%s)", symbol);
755 
756  if (ret < 0)
757  {
758  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
759  }
760  else
761  {
762  rem -= ret;
763  l += ret;
764  }
765  }
766 
767  if (instr[0] != 0)
768  {
769  ret = snprintf(l, rem, ", Instr: %s", instr);
770 
771  if (ret < 0)
772  {
773  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
774  }
775  else
776  {
777  rem -= ret;
778  l += ret;
779  }
780  }
781 
783  if (NULL != pTask)
784  {
785  LIX_TASK_OBJECT *pParent = IntLixTaskFindByGva(pTask->Parent);
786 
787  ret = IntExceptPrintLixTaskInfo(pTask, ", Process: ", l, rem, 0);
788  rem -= ret;
789  l += ret;
790 
791  ret = IntExceptPrintLixTaskInfo(pParent, ", Parent: ", l, rem, 0);
792  rem -= ret;
793  l += ret;
794 
795  }
796 
797  LOG("%s\n", gExcLogLine);
798 
799  // Log the return driver too, if we have one and the rip is different
800  if (pRetDriver && Originator->Original.Rip != Originator->Return.Rip)
801  {
802  l = gExcLogLine;
803  rem = sizeof(gExcLogLine);
804 
805  if (pRetDriver == gGuest.KernelDriver)
806  {
807  status = IntKsymFindByAddress(Originator->Return.Rip, sizeof(symbol), symbol, NULL, NULL);
808  if (!INT_SUCCESS(status))
809  {
810  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
811  }
812  }
813  else
814  {
815  symbol[0] = 0;
816  }
817 
818  ret = IntExceptPrintLixKmDrvInfo(pRetDriver, "Return -> Module: ", l, rem, modNameAlignment);
819  rem -= ret;
820  l += ret;
821 
822  ret = snprintf(l, rem, ", RIP %016llx", Originator->Return.Rip);
823 
824  if (ret < 0)
825  {
826  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
827  }
828  else
829  {
830  rem -= ret;
831  l += ret;
832  }
833 
834  if (Originator->Return.Section[0] != 0)
835  {
836  ret = snprintf(l, rem, "(%s)", Originator->Return.Section);
837 
838  if (ret < 0)
839  {
840  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
841  }
842  else
843  {
844  rem -= ret;
845  l += ret;
846  }
847  }
848 
849  if (symbol[0] != 0)
850  {
851  ret = snprintf(l, rem, " (%s)", symbol);
852 
853  if (ret < 0)
854  {
855  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
856  }
857  else
858  {
859  rem -= ret;
860  l += ret;
861  }
862  }
863 
864  LOG("%s\n", gExcLogLine);
865  }
866  }
867 
868  l = gExcLogLine;
869  rem = sizeof(gExcLogLine);
870 
871  if (Victim->ZoneType == exceptionZoneMsr)
872  {
873  IntExceptPrintMsrInfo(Victim, "Victim -> Msr: ", l, rem);
874 
875  LOG("%s\n", gExcLogLine);
876  }
877  else if ((Victim->Object.Type == introObjectTypeKmModule) ||
878  (Victim->Object.Type == introObjectTypeVdso) ||
879  (Victim->Object.Type == introObjectTypeVsyscall))
880  {
881  pDriver = Victim->Object.Module.Module;
882 
883  if (pDriver)
884  {
885  ret = IntExceptPrintLixKmDrvInfo(pDriver, "Victim -> Module: ", l, rem, modNameAlignment);
886  rem -= ret;
887  l += ret;
888  }
889  else if (Victim->Object.Type == introObjectTypeVdso)
890  {
891  ret = snprintf(l, rem, "Victim -> Module: %*s", modNameAlignment, "[vdso]");
892  rem -= ret;
893  l += ret;
894  }
895  else if (Victim->Object.Type == introObjectTypeVsyscall)
896  {
897  ret = snprintf(l, rem, "Victim -> Module: %*s", modNameAlignment, "[vsyscall]");
898  rem -= ret;
899  l += ret;
900  }
901 
902  ret = snprintf(l, rem, ", Address: (%0llx, %0llx)",
903  Victim->Ept.Gva, Victim->Ept.Gpa);
904 
905  if (ret < 0)
906  {
907  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
908  }
909  else
910  {
911  rem -= ret;
912  l += ret;
913  }
914 
915  if (pDriver == gGuest.KernelDriver)
916  {
917  status = IntKsymFindByAddress(Victim->Ept.Gva, sizeof(symbol), symbol, NULL, NULL);
918  if (!INT_SUCCESS(status))
919  {
920  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
921  }
922 
923  ret = snprintf(l, rem, ", %s", symbol);
924 
925  if (ret < 0)
926  {
927  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
928  }
929  else
930  {
931  rem -= ret;
932  l += ret;
933  }
934  }
935 
936  ret = 0;
937  if (Victim->ZoneFlags & ZONE_WRITE)
938  {
939  ret = snprintf(l, rem, ", WriteInfo: (%u, %016llx -> %016llx)", Victim->WriteInfo.AccessSize,
940  Victim->WriteInfo.OldValue[0], Victim->WriteInfo.NewValue[0]);
941  }
942  else if (Victim->ZoneFlags & ZONE_READ)
943  {
944  ret = snprintf(l, rem, ", ReadInfo: (%u, %016llx)", Victim->ReadInfo.AccessSize, Victim->ReadInfo.Value[0]);
945  }
946 
947  if (ret < 0)
948  {
949  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
950  }
951  else
952  {
953  rem -= ret;
954  l += ret;
955  }
956 
957  if (Victim->ZoneFlags)
958  {
959  ret = snprintf(l, rem, ", Flags:%s%s%s%s%s (0x%llx)",
960  (Victim->ZoneFlags & ZONE_LIB_IMPORTS) ? " IMPORTS" : "",
961  (Victim->ZoneFlags & ZONE_LIB_EXPORTS) ? " EXPORTS" : "",
962  (Victim->ZoneFlags & ZONE_LIB_CODE) ? " CODE" : "",
963  (Victim->ZoneFlags & ZONE_LIB_DATA) ? " DATA" : "",
964  (Victim->ZoneFlags & ZONE_LIB_RESOURCES) ? " RSRC" : "",
965  (unsigned long long)Victim->ZoneFlags);
966 
967  if (ret < 0)
968  {
969  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
970  }
971  else
972  {
973  rem -= ret;
974  l += ret;
975  }
976  }
977 
978  LOG("%s\n", gExcLogLine);
979  }
980  else if (Victim->ZoneType == exceptionZoneCr)
981  {
982  IntExceptPrintCrInfo(Victim, "Victim -> Cr", l, rem);
983 
984  LOG("%s\n", gExcLogLine);
985  }
986  else if (Victim->Object.Type == introObjectTypeIdt)
987  {
988  IntExceptPrintIdtInfo(Victim, "Victim -> Idt: ", l, rem);
989 
990  LOG("%s\n", gExcLogLine);
991  }
992 
993  if (Action == introGuestNotAllowed)
994  {
995  l = gExcLogLine;
996  rem = sizeof(gExcLogLine);
997 
998  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sROOTKIT (kernel-mode) ",
999  gGuest.KernelBetaDetections ? " (B) " : " ");
1000 
1001  if (ret < 0)
1002  {
1003  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1004  }
1005  else
1006  {
1007  rem -= ret;
1008  l += ret;
1009  }
1010 
1011  switch (Reason)
1012  {
1014  ret = snprintf(l, rem, "(no sig)");
1015  break;
1017  ret = snprintf(l, rem, "(no exc)");
1018  break;
1020  ret = snprintf(l, rem, "(extra)");
1021  break;
1023  ret = snprintf(l, rem, "(error)");
1024  break;
1026  ret = snprintf(l, rem, "(value)");
1027  break;
1029  ret = snprintf(l, rem, "(export)");
1030  break;
1032  ret = snprintf(l, rem, "(value code)");
1033  break;
1035  ret = snprintf(l, rem, "(idt)");
1036  break;
1038  ret = snprintf(l, rem, "(version os)");
1039  break;
1041  ret = snprintf(l, rem, "(version intro)");
1042  break;
1044  ret = snprintf(l, rem, "(process creation)");
1045  break;
1046  case introReasonUnknown:
1047  ret = snprintf(l, rem, "(unknown)");
1048  break;
1049  default:
1050  ret = snprintf(l, rem, "(%d)", Reason);
1051  break;
1052  }
1053 
1054  if (ret < 0)
1055  {
1056  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1057  }
1058  else
1059  {
1060  rem -= ret;
1061  l += ret;
1062  }
1063 
1064  snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1065  LOG("%s\n\n", gExcLogLine);
1066  }
1067 
1068  for (DWORD t = 0; t < Originator->StackTrace.NumberOfTraces; t++)
1069  {
1070  if (NULL != Originator->StackTrace.Traces[t].ReturnModule)
1071  {
1072 
1073  if (Originator->StackTrace.Traces[t].ReturnModule == gGuest.KernelDriver)
1074  {
1075  status = IntKsymFindByAddress(Originator->StackTrace.Traces[t].CurrentRip,
1076  sizeof(symbol),
1077  symbol,
1078  NULL,
1079  NULL);
1080  if (!INT_SUCCESS(status))
1081  {
1082  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
1083  }
1084  }
1085  else
1086  {
1087  memcpy(symbol, EXCEPTION_NO_SYMBOL, sizeof(EXCEPTION_NO_SYMBOL));
1088  }
1089 
1090  LOG("[STACK TRACE] [at %llx] returning to [%s at %llx] %s",
1091  Originator->StackTrace.Traces[t].CurrentRip,
1092  (char *)((KERNEL_DRIVER *)Originator->StackTrace.Traces[t].ReturnModule)->Name,
1093  Originator->StackTrace.Traces[t].ReturnAddress, symbol);
1094  }
1095  else
1096  {
1097  LOG("[STACK TRACE] [at %llx]", Originator->StackTrace.Traces[t].CurrentRip);
1098  }
1099  }
1100 
1101 }
1102 
1103 
1104 static int
1106  _In_ WIN_DRIVER_OBJECT *DrvObj,
1107  _In_ char *Header,
1108  _Out_ char *Line,
1109  _In_ int MaxLength
1110  )
1121 {
1122  int ret, total = 0;
1123  char name[MAX_PATH];
1124 
1125  if (NULL == DrvObj)
1126  {
1127  return snprintf(Line, MaxLength, "%s(%s)", Header, EXCEPTION_NO_NAME);
1128  }
1129 
1130  utf16toutf8(name, DrvObj->Name, sizeof(name));
1131 
1132  ret = snprintf(Line, MaxLength, "%s(%s", Header, name);
1133 
1134  if (ret < 0)
1135  {
1136  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1137  }
1138  else
1139  {
1140  Line += ret;
1141  total += ret;
1142  MaxLength -= ret;
1143  }
1144 
1145  ret = snprintf(Line, MaxLength, " [0x%08x], %0*llx, %0llx",
1146  DrvObj->NameHash, gGuest.WordSize * 2, DrvObj->DriverObjectGva, DrvObj->DriverObjectGpa);
1147 
1148  if (ret < 0)
1149  {
1150  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1151  }
1152  else
1153  {
1154  Line += ret;
1155  total += ret;
1156  MaxLength -= ret;
1157  }
1158 
1159  if (DrvObj->FastIOTableAddress)
1160  {
1161  ret = snprintf(Line, MaxLength, ", %0*llx", gGuest.WordSize * 2, DrvObj->FastIOTableAddress);
1162 
1163  if (ret < 0)
1164  {
1165  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1166  }
1167  else
1168  {
1169  Line += ret;
1170  total += ret;
1171  MaxLength -= ret;
1172  }
1173  }
1174 
1175  ret = snprintf(Line, MaxLength, ")");
1176 
1177  if (ret < 0)
1178  {
1179  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1180  }
1181  else
1182  {
1183  total += ret;
1184  }
1185 
1186  return total;
1187 }
1188 
1189 
1190 static void
1192  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1193  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
1194  _In_ INTRO_ACTION Action,
1195  _In_ INTRO_ACTION_REASON Reason
1196  )
1205 {
1206  KERNEL_DRIVER *pDriver, *pRetDriver;
1207  DWORD modNameAlignment;
1208  char *l;
1209  int ret, rem;
1210 
1211  pDriver = Originator->Original.Driver;
1212  pRetDriver = Originator->Return.Driver;
1213 
1214  modNameAlignment = 0;
1215  if (Victim->Object.Type == introObjectTypeKmModule || Victim->Object.Type == introObjectTypeVeAgent)
1216  {
1217  KERNEL_DRIVER *pModDriver = Victim->Object.Module.Module;
1218 
1219  if (pModDriver && pDriver)
1220  {
1221  modNameAlignment = MIN(MAX_PATH, MAX(pModDriver->Win.PathLength, pDriver->Win.PathLength));
1222  }
1223 
1224  if (pModDriver && pRetDriver)
1225  {
1226  if (modNameAlignment > 0)
1227  {
1228  modNameAlignment = MIN(MAX_PATH, MAX(pRetDriver->Win.PathLength, modNameAlignment));
1229  }
1230  else
1231  {
1232  modNameAlignment = MIN(MAX_PATH, MAX(pModDriver->Win.PathLength, pRetDriver->Win.PathLength));
1233  }
1234  }
1235  }
1236 
1237  l = gExcLogLine;
1238  rem = sizeof(gExcLogLine);
1239 
1240  if (Victim->ZoneType == exceptionZoneIntegrity)
1241  {
1242  // For token privileges integrity detection, originator will always be invalid, there is
1243  // no reason to just log a "Originator no name" line.
1244  if (Victim->Object.Type != introObjectTypeTokenPrivs)
1245  {
1246  // No point in logging anything else, since the RIP is unknown
1247  IntExceptPrintWinKmModInfo(pDriver, "Originator-> Module: ", l, rem, 0);
1248 
1249  LOG("%s\n", gExcLogLine);
1250  }
1251  }
1252  else
1253  {
1254  char instr[ND_MIN_BUF_SIZE];
1255 
1256  if (Originator->Instruction)
1257  {
1258  NDSTATUS ndstatus = NdToText(Originator->Instruction, Originator->Original.Rip, sizeof(instr), instr);
1259  if (!ND_SUCCESS(ndstatus))
1260  {
1261  memcpy(instr, EXPORT_NAME_UNKNOWN, sizeof(EXPORT_NAME_UNKNOWN));
1262  }
1263  }
1264  else
1265  {
1266  memcpy(instr, EXCEPTION_NO_INSTRUCTION, sizeof(EXCEPTION_NO_INSTRUCTION));
1267  }
1268 
1269  ret = IntExceptPrintWinKmModInfo(pDriver, "Originator-> Module: ", l, rem, modNameAlignment);
1270  rem -= ret;
1271  l += ret;
1272 
1273  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Original.Rip);
1274 
1275  if (ret < 0)
1276  {
1277  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1278  }
1279  else
1280  {
1281  rem -= ret;
1282  l += ret;
1283  }
1284 
1285  if (Originator->Original.Section[0] != 0)
1286  {
1287  ret = snprintf(l, rem, " (%s)", Originator->Original.Section);
1288 
1289  if (ret < 0)
1290  {
1291  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1292  }
1293  else
1294  {
1295  rem -= ret;
1296  l += ret;
1297  }
1298  }
1299 
1300  if (instr[0] != 0)
1301  {
1302  ret = snprintf(l, rem, ", Instr: %s", instr);
1303 
1304  if (ret < 0)
1305  {
1306  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1307  }
1308  else
1309  {
1310  rem -= ret;
1311  l += ret;
1312  }
1313  }
1314 
1315  LOG("%s\n", gExcLogLine);
1316 
1317  if (Originator->Return.Driver && Originator->Original.Rip != Originator->Return.Rip)
1318  {
1319  l = gExcLogLine;
1320  rem = sizeof(gExcLogLine);
1321 
1322  ret = IntExceptPrintWinKmModInfo(pRetDriver, "Return -> Module: ", l, rem, modNameAlignment);
1323  rem -= ret;
1324  l += ret;
1325 
1326  ret = snprintf(l, rem, ", RIP %0*llx", gGuest.WordSize * 2, Originator->Return.Rip);
1327 
1328  if (ret < 0)
1329  {
1330  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1331  }
1332  else
1333  {
1334  rem -= ret;
1335  l += ret;
1336  }
1337 
1338  if (Originator->Return.Section[0] != 0)
1339  {
1340  ret = snprintf(l, rem, "(%s)", Originator->Return.Section);
1341 
1342  if (ret < 0)
1343  {
1344  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1345  }
1346  else
1347  {
1348  rem -= ret;
1349  l += ret;
1350  }
1351  }
1352 
1353  LOG("%s\n", gExcLogLine);
1354  }
1355  }
1356 
1357  l = gExcLogLine;
1358  rem = sizeof(gExcLogLine);
1359 
1360  if (Victim->ZoneType == exceptionZoneMsr)
1361  {
1362  IntExceptPrintMsrInfo(Victim, "Victim -> Msr: ", l, rem);
1363 
1364  LOG("%s\n", gExcLogLine);
1365  }
1366  else if (Victim->Object.Type == introObjectTypeKmModule ||
1367  Victim->Object.Type == introObjectTypeSsdt ||
1368  Victim->Object.Type == introObjectTypeVeAgent)
1369  {
1370  pDriver = Victim->Object.Module.Module;
1371 
1372  ret = IntExceptPrintWinKmModInfo(pDriver, "Victim -> Module: ", l, rem, modNameAlignment);
1373  rem -= ret;
1374  l += ret;
1375 
1376  ret = snprintf(l, rem, ", Address: (%0*llx, %0*llx)",
1377  gGuest.WordSize * 2, Victim->Ept.Gva,
1378  gGuest.WordSize * 2, Victim->Ept.Gpa);
1379  if (ret < 0)
1380  {
1381  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1382  }
1383  else
1384  {
1385  rem -= ret;
1386  l += ret;
1387  }
1388 
1389  if (Victim->ZoneFlags & ZONE_WRITE)
1390  {
1391  ret = snprintf(l, rem, ", WriteInfo: (%u, %016llx -> %016llx)", Victim->WriteInfo.AccessSize,
1392  Victim->WriteInfo.OldValue[0], Victim->WriteInfo.NewValue[0]);
1393  }
1394  else if (Victim->ZoneFlags & ZONE_READ)
1395  {
1396  ret = snprintf(l, rem, ", ReadInfo: (%u, %016llx)", Victim->ReadInfo.AccessSize, Victim->ReadInfo.Value[0]);
1397  }
1398 
1399  if (ret < 0)
1400  {
1401  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1402  }
1403  else
1404  {
1405  rem -= ret;
1406  l += ret;
1407  }
1408 
1409  if (Victim->ZoneFlags)
1410  {
1411  ret = snprintf(l, rem, ", Flags:%s%s%s%s%s (0x%llx)",
1412  (Victim->ZoneFlags & ZONE_LIB_IMPORTS) ? " IMPORTS" : "",
1413  (Victim->ZoneFlags & ZONE_LIB_EXPORTS) ? " EXPORTS" : "",
1414  (Victim->ZoneFlags & ZONE_LIB_CODE) ? " CODE" : "",
1415  (Victim->ZoneFlags & ZONE_LIB_DATA) ? " DATA" : "",
1416  (Victim->ZoneFlags & ZONE_LIB_RESOURCES) ? " RSRC" : "",
1417  (unsigned long long)Victim->ZoneFlags);
1418  if (ret < 0)
1419  {
1420  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1421  }
1422  else
1423  {
1424  rem -= ret;
1425  l += ret;
1426  }
1427  }
1428 
1429  LOG("%s\n", gExcLogLine);
1430  }
1431  else if ((Victim->Object.Type == introObjectTypeDriverObject) ||
1432  (Victim->Object.Type == introObjectTypeFastIoDispatch))
1433  {
1434  BOOLEAN fastIo = (Victim->Object.Type == introObjectTypeFastIoDispatch);
1435 
1436  if (fastIo)
1437  {
1438  ret = IntExceptPrintDrvObjInfo(Victim->Object.DriverObject, "Victim -> FastIo: ", l, rem);
1439  }
1440  else
1441  {
1442  ret = IntExceptPrintDrvObjInfo(Victim->Object.DriverObject, "Victim -> DrvObj: ", l, rem);
1443  }
1444 
1445  rem -= ret;
1446  l += ret;
1447 
1448  pDriver = IntDriverFindByBase(Victim->Object.DriverObject->Owner);
1449  if (pDriver)
1450  {
1451  ret = IntExceptPrintWinKmModInfo(pDriver, ", Owner: ", l, rem, 0);
1452  rem -= ret;
1453  l += ret;
1454  }
1455 
1456  ret = snprintf(l, rem, ", WriteInfo: (%u, %016llx -> %016llx)",
1457  Victim->WriteInfo.AccessSize,
1458  Victim->WriteInfo.OldValue[0],
1459  Victim->WriteInfo.NewValue[0]);
1460  if (ret < 0)
1461  {
1462  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1463  }
1464  else
1465  {
1466  rem -= ret;
1467  l += ret;
1468  }
1469 
1470  if (Victim->ZoneType == exceptionZoneIntegrity)
1471  {
1472  ret = snprintf(l, rem, ", INTEGRITY");
1473 
1474  if (ret < 0)
1475  {
1476  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1477  }
1478  else
1479  {
1480  rem -= ret;
1481  l += ret;
1482  }
1483  }
1484 
1485  LOG("%s\n", gExcLogLine);
1486  }
1487  else if (Victim->ZoneType == exceptionZoneCr)
1488  {
1489  IntExceptPrintCrInfo(Victim, "Victim -> Cr", l, rem);
1490 
1491  LOG("%s\n", gExcLogLine);
1492  }
1493  else if (Victim->Object.Type == introObjectTypeHalIntController)
1494  {
1495  LOG("Victim -> Hal interrupt controller: (%0*llx, %0*llx), WriteInfo: (%d, %016llx -> %016llx)\n",
1496  gGuest.WordSize * 2, Victim->Ept.Gva, gGuest.WordSize * 2, Victim->Ept.Gpa,
1497  Victim->WriteInfo.AccessSize,
1498  Victim->WriteInfo.OldValue[0], Victim->WriteInfo.NewValue[0]);
1499  }
1500  else if (Victim->Object.Type == introObjectTypeHalHeap)
1501  {
1502  LOG("Victim -> Hal heap execute: (%0*llx, %0*llx)\n",
1503  gGuest.WordSize * 2, Victim->Ept.Gva, gGuest.WordSize * 2, Victim->Ept.Gpa);
1504  }
1505  else if (Victim->Object.Type == introObjectTypeSharedUserData)
1506  {
1507  LOG("Victim -> SharedUserData execute: (%0*llx, %0*llx)\n",
1508  gGuest.WordSize * 2, Victim->Ept.Gva, gGuest.WordSize * 2, Victim->Ept.Gpa);
1509  }
1510  else if (Victim->Object.Type == introObjectTypeIdt)
1511  {
1512  IntExceptPrintIdtInfo(Victim, "Victim -> Idt: ", l, rem);
1513 
1514  LOG("%s\n", gExcLogLine);
1515  }
1516  else if (Victim->Object.Type == introObjectTypeSelfMapEntry)
1517  {
1518  LOG("Victim -> Self map entry: %s [0x%08x] (%016llx, %016llx), "
1519  "WriteInfo: (%d, %016llx -> %016llx), Index: %08x\n",
1520  Victim->Object.Name, Victim->Object.NameHash,
1521  Victim->Ept.Gva, Victim->Ept.Gpa,
1522  Victim->WriteInfo.AccessSize,
1523  Victim->WriteInfo.OldValue[0],
1524  Victim->WriteInfo.NewValue[0],
1526  }
1527  else if (Victim->Object.Type == introObjectTypeKmLoggerContext)
1528  {
1529  if (Victim->ZoneType == exceptionZoneIntegrity)
1530  {
1531  LOG("Victim -> Circular Kernel Context Logger (%016llx, %016llx), "
1532  "WriteInfo: (%d, %016llx -> %016llx), INTEGRITY\n",
1533  Victim->Integrity.StartVirtualAddress,
1534  Victim->Integrity.StartVirtualAddress + Victim->Integrity.TotalLength,
1535  Victim->WriteInfo.AccessSize,
1536  Victim->WriteInfo.OldValue[0],
1537  Victim->WriteInfo.NewValue[0]);
1538  }
1539  else
1540  {
1541  LOG("Victim -> Circular Kernel Context Logger (%016llx, %016llx), "
1542  "WriteInfo: (%d, %016llx -> %016llx), EPT\n",
1543  Victim->Ept.Gva, Victim->Ept.Gpa,
1544  Victim->WriteInfo.AccessSize,
1545  Victim->WriteInfo.OldValue[0],
1546  Victim->WriteInfo.NewValue[0]);
1547  }
1548  }
1549  else if (Victim->Object.Type == introObjectTypeGdtr ||
1550  Victim->Object.Type == introObjectTypeIdtr)
1551  {
1552  IntExceptPrintDtrInfo(Victim, "Victim -> Dtr: ", l, rem);
1553 
1554  LOG("%s\n", gExcLogLine);
1555  }
1556  else if (Victim->Object.Type == introObjectTypeTokenPrivs)
1557  {
1558  if (Victim->ZoneType == exceptionZoneIntegrity)
1559  {
1560  LOG("Victim -> Token privileges (%s [0x%08x] %d), WriteInfo: (Present: 0x%016llx, "
1561  "Enabled: 0x%016llx -> Present: 0x%016llx, Enabled: 0x%016llx), INTEGRITY\n",
1562  Victim->Object.WinProc->Name,
1563  Victim->Object.WinProc->NameHash,
1564  Victim->Object.WinProc->Pid,
1565  Victim->WriteInfo.OldValue[0],
1566  Victim->WriteInfo.OldValue[1],
1567  Victim->WriteInfo.NewValue[0],
1568  Victim->WriteInfo.NewValue[1]);
1569  }
1570  else
1571  {
1572  LOG("Victim -> Token privileges (%s [0x%08x] %d), WriteInfo: (%d, %016llx -> %016llx), EPT\n",
1573  Victim->Object.WinProc->Name,
1574  Victim->Object.WinProc->NameHash,
1575  Victim->Object.WinProc->Pid,
1576  Victim->WriteInfo.AccessSize,
1577  Victim->WriteInfo.OldValue[0],
1578  Victim->WriteInfo.NewValue[0]);
1579  }
1580  }
1581 
1582  if (Action == introGuestNotAllowed)
1583  {
1584  l = gExcLogLine;
1585  rem = sizeof(gExcLogLine);
1586 
1587  ret = snprintf(l, rem, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%sROOTKIT (kernel-mode) ",
1588  gGuest.KernelBetaDetections ? " (B) " : " ");
1589  if (ret < 0)
1590  {
1591  ERROR("[ERROR] Encoding error with snprintf: %d\n", ret);
1592  }
1593  else
1594  {
1595  rem -= ret;
1596  l += ret;
1597  }
1598 
1599  switch (Reason)
1600  {
1602  ret = snprintf(l, rem, "(no sig)");
1603  break;
1605  ret = snprintf(l, rem, "(no exc)");
1606  break;
1608  ret = snprintf(l, rem, "(extra)");
1609  break;
1611  ret = snprintf(l, rem, "(error)");
1612  break;
1614  ret = snprintf(l, rem, "(value)");
1615  break;
1617  ret = snprintf(l, rem, "(export)");
1618  break;
1620  ret = snprintf(l, rem, "(value code)");
1621  break;
1623  ret = snprintf(l, rem, "(idt)");
1624  break;
1626  ret = snprintf(l, rem, "(version os)");
1627  break;
1629  ret = snprintf(l, rem, "(version intro)");
1630  break;
1632  ret = snprintf(l, rem, "(process creation)");
1633  break;
1634  case introReasonUnknown:
1635  ret = snprintf(l, rem, "(unknown)");
1636  break;
1637  default:
1638  ret = snprintf(l, rem, "(%d)", Reason);
1639  break;
1640  }
1641 
1642  rem -= ret;
1643  l += ret;
1644 
1645  snprintf(l, rem, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1646 
1647  LOG("%s\n\n", gExcLogLine);
1648  }
1649  for (DWORD t = 0; t < Originator->StackTrace.NumberOfTraces; t++)
1650  {
1651  if (NULL != Originator->StackTrace.Traces[t].ReturnModule)
1652  {
1653  LOG("[STACK TRACE] [at 0x%016llx] returning to [%s at 0x%016llx]\n",
1654  Originator->StackTrace.Traces[t].CurrentRip,
1655  utf16_for_log(((KERNEL_DRIVER *)Originator->StackTrace.Traces[t].ReturnModule)->Name),
1656  Originator->StackTrace.Traces[t].ReturnAddress);
1657  }
1658  else
1659  {
1660  LOG("[STACK TRACE] [at 0x%016llx]\n", Originator->StackTrace.Traces[t].CurrentRip);
1661  }
1662  }
1663 }
1664 
1665 
1666 void
1668  _In_ EXCEPTION_VICTIM_ZONE *Victim,
1669  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
1670  _In_ INTRO_ACTION Action,
1671  _In_ INTRO_ACTION_REASON Reason
1672  )
1681 {
1682  if ((introGuestNotAllowed != Action) && (introReasonAllowedFeedback != Reason))
1683  {
1684  return;
1685  }
1686 
1688  {
1689  IntExceptKernelLogWindowsInformation(Victim, Originator, Action, Reason);
1690  }
1691  else if (gGuest.OSType == introGuestLinux)
1692  {
1693  IntExceptKernelLogLinuxInformation(Victim, Originator, Action, Reason);
1694  }
1695 
1696  if (!(Victim->ZoneFlags & ZONE_INTEGRITY))
1697  {
1698  IntExceptDumpSignatures(Originator, Victim, TRUE, FALSE);
1699  IntExceptDumpSignatures(Originator, Victim, TRUE, TRUE);
1700  }
1701 }
1702 
1703 
1704 static BOOLEAN
1706  _In_ QWORD Rip
1707  )
1716 {
1717  for (DWORD i = 0; i < ARRAYSIZE(gLixGuest->MemoryFunctions); i++)
1718  {
1719  if (gLixGuest->MemoryFunctions[i].Start == 0 || gLixGuest->MemoryFunctions[i].End == 0)
1720  {
1721  continue;
1722  }
1723 
1724  if (Rip >= gLixGuest->MemoryFunctions[i].Start && Rip < gLixGuest->MemoryFunctions[i].End)
1725  {
1726  return TRUE;
1727  }
1728  }
1729 
1730  return FALSE;
1731 }
1732 
1733 
1734 static INTSTATUS
1736  _Out_ EXCEPTION_KM_ORIGINATOR *Originator
1737  )
1747 {
1748  INTSTATUS status;
1749  PIG_ARCH_REGS pRegs;
1750  KERNEL_DRIVER *pDriver;
1751  QWORD rip;
1752 
1753  pRegs = &gVcpu->Regs;
1754  Originator->StackTrace.Traces = Originator->StackElements;
1755 
1756  Originator->Original.Driver = IntDriverFindByAddress(pRegs->Rip);
1757 
1758  status = IntLixStackTraceGetReg(0, pRegs, ARRAYSIZE(Originator->StackElements), 0, &Originator->StackTrace);
1759  if (!INT_SUCCESS(status) && 0 == Originator->StackTrace.NumberOfTraces)
1760  {
1761  WARNING("[WARNING] Failed getting a stack trace: 0x%08x. Skip checking for exported functions!\n",
1762  status);
1763  }
1764 
1765  for (DWORD t = 0; t < Originator->StackTrace.NumberOfTraces; t++)
1766  {
1767  KERNEL_DRIVER *pRetMod = IntDriverFindByAddress(Originator->StackTrace.Traces[t].ReturnAddress);
1768  if (NULL == pRetMod)
1769  {
1770  continue;
1771  }
1772 
1773  Originator->Return.Driver = pRetMod;
1774  Originator->Return.Rip = Originator->StackTrace.Traces[t].ReturnAddress;
1775 
1776  break;
1777  }
1778 
1779  if (NULL == Originator->Return.Driver)
1780  {
1781  for (DWORD t = 0; t < Originator->StackTrace.NumberOfTraces; t++)
1782  {
1783  KERNEL_DRIVER *pRetMod = IntDriverFindByAddress(Originator->StackTrace.Traces[t].ReturnAddress);
1784  if (NULL == pRetMod)
1785  {
1786  continue;
1787  }
1788 
1789  // Skip mem* functions
1790  if (pRetMod == gGuest.KernelDriver &&
1791  IntExceptLixKernelIsMemoryFunc(Originator->StackTrace.Traces[t].ReturnAddress))
1792  {
1793  continue;
1794  }
1795 
1796  Originator->Return.Driver = pRetMod;
1797  Originator->Return.Rip = Originator->StackTrace.Traces[t].ReturnAddress;
1798 
1799  break;
1800  }
1801  }
1802 
1803  if (NULL == Originator->Original.Driver && NULL == Originator->Return.Driver)
1804  {
1805  // We have nothing to check, and we don't except this (yet?)
1806  return INT_STATUS_SUCCESS;
1807  }
1808 
1809  if (NULL != Originator->Original.Driver)
1810  {
1811  rip = Originator->Original.Rip;
1812  pDriver = Originator->Original.Driver;
1813 
1814  if (pDriver->BaseVa == gGuest.KernelVa)
1815  {
1816  Originator->Original.NameHash = kmExcNameKernel;
1817  }
1818  else
1819  {
1820  Originator->Original.NameHash = pDriver->NameHash;
1821  }
1822 
1823  IntLixDrvGetSecName(pDriver, rip, Originator->Original.Section);
1824  }
1825  else
1826  {
1827  Originator->Original.NameHash = INITIAL_CRC_VALUE;
1828  }
1829 
1830  if (NULL != Originator->Return.Driver)
1831  {
1832  rip = Originator->Return.Rip;
1833  pDriver = Originator->Return.Driver;
1834 
1835  if (pDriver->BaseVa == gGuest.KernelVa)
1836  {
1837  Originator->Return.NameHash = kmExcNameKernel;
1838  }
1839  else
1840  {
1841  Originator->Return.NameHash = pDriver->NameHash;
1842  }
1843 
1844  IntLixDrvGetSecName(pDriver, rip, Originator->Return.Section);
1845  }
1846  else
1847  {
1848  Originator->Return.NameHash = INITIAL_CRC_VALUE;
1849  }
1850 
1851  return INT_STATUS_SUCCESS;
1852 }
1853 
1854 
1855 static INTSTATUS
1857  _Out_ EXCEPTION_KM_ORIGINATOR *Originator,
1858  _In_ DWORD Options
1859  )
1873 {
1874  INTSTATUS status;
1875  KERNEL_DRIVER *pDriver, *pOriginalDriver;
1876 
1877  IG_ARCH_REGS *pRegs = &gVcpu->Regs;
1878  DWORD currentTrace = 0;
1879  QWORD stackFrame = gGuest.Guest64 ? pRegs->Rsp : pRegs->Rbp;
1880  DWORD stackDepth;
1881 
1882  // Find the original driver that's modifying the memory
1883  Originator->Original.Driver = IntDriverFindByAddress(Originator->Original.Rip);
1884 
1885  stackDepth = (NULL == Originator->Original.Driver) ? 3 : 1;
1886 
1887  // Reset the stack trace
1888  Originator->StackTrace.Traces = Originator->StackElements;
1889 
1890  status = IntWinStackTraceGet(stackFrame, pRegs->Rip, stackDepth, 0, &Originator->StackTrace);
1891  if (!INT_SUCCESS(status) && (Originator->StackTrace.NumberOfTraces == 0))
1892  {
1893  WARNING("[WARNING] Failed getting a stack trace: 0x%08x. Skip checking for exported functions!\n",
1894  status);
1895  }
1896 
1897  // This is a RIP that isn't inside any driver... We have special exceptions
1898  // for this case, so get the first return driver.
1899  if (NULL == Originator->Original.Driver)
1900  {
1901  DWORD t;
1902 
1903  for (t = 0; t < Originator->StackTrace.NumberOfTraces; t++)
1904  {
1905  if (NULL == Originator->StackTrace.Traces[t].ReturnModule)
1906  {
1907  continue;
1908  }
1909 
1910  Originator->Return.Driver = Originator->StackTrace.Traces[t].ReturnModule;
1911 
1912  Originator->Return.Rip = Originator->StackTrace.Traces[t].ReturnAddress;
1913 
1914  break;
1915  }
1916  }
1917  else
1918  {
1919  // They are the same, unless we will found otherwise
1920  Originator->Return.Driver = Originator->Original.Driver;
1921  }
1922 
1923  if (NULL == Originator->Original.Driver && NULL != Originator->Return.Driver)
1924  {
1925  TRACE("[WARNING] The RIP 0x%016llx is not inside any module, but it returns to one 0x%016llx "
1926  "(BaseVa 0x%016llx).\n",
1927  Originator->Original.Rip,
1928  Originator->Return.Rip,
1929  Originator->Return.Driver->BaseVa);
1930  }
1931  else if (NULL == Originator->Original.Driver && NULL == Originator->Return.Driver)
1932  {
1933  // We have nothing to check, and we don't except this (yet?)
1934  Originator->Original.NameHash = INITIAL_CRC_VALUE;
1935  Originator->Return.NameHash = INITIAL_CRC_VALUE;
1936  return INT_STATUS_SUCCESS;
1937  }
1938 
1939  pDriver = Originator->Return.Driver;
1940  pOriginalDriver = Originator->Original.Driver;
1941 
1942  do
1943  {
1944  IMAGE_SECTION_HEADER sectionHeader;
1945  DRIVER_EXPORT_CACHE_ENTRY *pCache = NULL;
1946 
1947  BOOLEAN found = FALSE;
1948 
1949  // Get the section header for the current RIP
1950  status = IntPeGetSectionHeaderByRva(pDriver->BaseVa,
1951  pDriver->Win.MzPeHeaders,
1952  (DWORD)(Originator->Return.Rip - pDriver->BaseVa),
1953  &sectionHeader);
1954  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
1955  {
1956  ERROR("[ERROR] Failed getting section details for Rip 0x%016llx: 0x%08x\n",
1957  Originator->Original.Rip, status);
1958  goto _cleanup_and_break;
1959  }
1960  else if (status == INT_STATUS_NOT_FOUND)
1961  {
1962  WARNING("[WARNING] Rip 0x%016llx isn't inside any section. ModuleBase: 0x%016llx\n",
1963  Originator->Original.Rip, pDriver->BaseVa);
1964  if (0 == (Options & EXCEPTION_KM_ORIGINATOR_OPT_DO_NOT_BLOCK))
1965  {
1966  status = INT_STATUS_EXCEPTION_BLOCK;
1967  }
1968  goto _cleanup_and_break;
1969  }
1970 
1971  // Will only happen once
1972  if (Originator->Original.Driver != NULL &&
1973  0 == Originator->Original.Section[0])
1974  {
1975  memcpy(Originator->Original.Section, sectionHeader.Name, sizeof(sectionHeader.Name));
1976  }
1977 
1978  memcpy(Originator->Return.Section, sectionHeader.Name, sizeof(sectionHeader.Name));
1979 
1980  // See if this is the verifier
1981  if (pDriver->BaseVa == gGuest.KernelVa &&
1982  0 == memcmp(Originator->Return.Section, "PAGEVRF", 7))
1983  {
1984  WARNING("[WARNING] The RIP is inside the kernel section %s, the VERIFIER is active...\n",
1985  Originator->Return.Section);
1986  }
1987 
1988  // See if the section is writable and not discardable or doesn't have the CODE or EXEC flags
1989  if (0 == (sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) &&
1990  0 == (sectionHeader.Characteristics & IMAGE_SCN_MEM_EXECUTE) &&
1991  0 != (sectionHeader.Characteristics & IMAGE_SCN_MEM_WRITE))
1992  {
1993  WARNING("[WARNING] Code executed from a section that doesn't contain code (RIP 0x%016llx). " \
1994  "Characteristics: 0x%08x, Name: %s\n",
1995  Originator->Return.Rip, sectionHeader.Characteristics, Originator->Return.Section);
1996  if (0 == (Options & EXCEPTION_KM_ORIGINATOR_OPT_DO_NOT_BLOCK))
1997  {
1998  status = INT_STATUS_EXCEPTION_BLOCK;
1999  }
2000  goto _cleanup_and_break;
2001  }
2002  if (Originator->Return.Rip - pDriver->EntryPoint < PAGE_SIZE &&
2003  0 == memcmp(Originator->Return.Section, "INIT", 4))
2004  {
2005  found = TRUE;
2006 
2007  Originator->IsEntryPoint = TRUE;
2008 
2009  // The entry point can be exported. This ensures that it won't go further (to IopInitializeDriver & co.)
2010  goto _cleanup_and_break;
2011  }
2012 
2013  if (0 == Originator->StackTrace.NumberOfTraces ||
2014  NULL == Originator->Original.Driver)
2015  {
2016  // There is no point in going further
2017  found = TRUE;
2018  goto _cleanup_and_break;
2019  }
2020 
2021 
2022  // See if this RIP is inside an exported function
2023  pCache = IntDriverCacheExportFind(Originator->Return.Rip);
2024  if (pCache == NULL)
2025  {
2026  if (pDriver->BaseVa != gGuest.KernelVa)
2027  {
2028  status = IntPeFindExportByRva(pDriver->BaseVa,
2029  pDriver->Win.MzPeHeaders,
2030  (DWORD)(Originator->Return.Rip - pDriver->BaseVa));
2031  }
2032  else
2033  {
2034  status = IntPeFindExportByRvaInBuffer(pDriver->BaseVa,
2037  (DWORD)(Originator->Return.Rip - pDriver->BaseVa));
2038  }
2039 
2040  if (INT_STATUS_NOT_FOUND == status)
2041  {
2042  IntDriverCacheCreateUnknown(Originator->Return.Rip);
2043  found = TRUE;
2044  goto _cleanup_and_break;
2045  }
2046  else if (!INT_SUCCESS(status))
2047  {
2048  // Don't compare the status to specific values since on XEN it will be different.
2049  // If a driver is calling a function in another driver, than assume that function is exported, in case
2050  // we had an error, which usually happens when the export directory is paged out.
2051  if (pDriver == Originator->StackTrace.Traces[currentTrace].ReturnModule)
2052  {
2053  found = TRUE;
2054  goto _cleanup_and_break;
2055  }
2056  }
2057  else
2058  {
2059  IntDriverCacheCreateExport(Originator->Return.Rip);
2060  }
2061  }
2062  else
2063  {
2064  if (pCache->Type.Unknown)
2065  {
2066  found = TRUE;
2067  goto _cleanup_and_break;
2068  }
2069  }
2070 
2071  // We are done analyzing current RIP, go further if needed
2072  if (NULL == Originator->StackTrace.Traces[currentTrace].ReturnModule)
2073  {
2074  WARNING("[WARNING] RIP 0x%016llx returning to an address that isn't inside a driver 0x%016llx. "
2075  "Block the attempt\n",
2076  Originator->Original.Rip,
2077  Originator->StackTrace.Traces[currentTrace].ReturnAddress);
2078 
2079  if (0 == (Options & EXCEPTION_KM_ORIGINATOR_OPT_DO_NOT_BLOCK))
2080  {
2081  status = INT_STATUS_EXCEPTION_BLOCK;
2082  }
2083  }
2084  else
2085  {
2086  status = INT_STATUS_SUCCESS; // go to the next one
2087  }
2088 
2089 _cleanup_and_break:
2090  // Unmap the current module base if needed (we found our function, or the return is in another module)
2091  if (found)
2092  {
2093  break;
2094  }
2095 
2096  // if we had an error the we must get out now
2097  if (!INT_SUCCESS(status))
2098  {
2099  return status;
2100  }
2101 
2102  // Modify the Rip and Driver to the return address and analyze that too
2103  Originator->Return.Rip = Originator->StackTrace.Traces[currentTrace].ReturnAddress;
2104 
2105  pDriver = Originator->StackTrace.Traces[currentTrace].ReturnModule;
2106  if (NULL == pDriver)
2107  {
2108  return INT_STATUS_NOT_FOUND;
2109  }
2110 
2111  Originator->Return.Driver = pDriver;
2112 
2113  currentTrace++;
2114  } while (currentTrace < Originator->StackTrace.NumberOfTraces);
2115 
2116  // Now get the hashes
2117  if (pDriver->BaseVa == gGuest.KernelVa)
2118  {
2119  Originator->Return.NameHash = kmExcNameKernel;
2120  }
2121  else if (0 == wstrcasecmp(pDriver->Name, u"hal.dll") ||
2122  0 == wstrcasecmp(pDriver->Name, u"halmacpi.dll") ||
2123  0 == wstrcasecmp(pDriver->Name, u"halacpi.dll"))
2124  {
2125  Originator->Return.NameHash = kmExcNameHal;
2126  }
2127  else
2128  {
2129  Originator->Return.NameHash = pDriver->NameHash;
2130  }
2131 
2132  // In case we had one (there is at least one case [virtualbox] where we don't)
2133  if (pOriginalDriver)
2134  {
2135  if (pOriginalDriver->BaseVa == gGuest.KernelVa)
2136  {
2137  Originator->Original.NameHash = kmExcNameKernel;
2138  }
2139  else if (0 == wstrcasecmp(pOriginalDriver->Name, u"hal.dll") ||
2140  0 == wstrcasecmp(pOriginalDriver->Name, u"halmacpi.dll") ||
2141  0 == wstrcasecmp(pOriginalDriver->Name, u"halacpi.dll"))
2142  {
2143  Originator->Original.NameHash = kmExcNameHal;
2144  }
2145  else
2146  {
2147  Originator->Original.NameHash = pOriginalDriver->NameHash;
2148  }
2149  }
2150  else
2151  {
2152  Originator->Original.NameHash = INITIAL_CRC_VALUE;
2153  }
2154 
2155  return INT_STATUS_SUCCESS;
2156 }
2157 
2158 
2159 INTSTATUS
2161  _Out_ EXCEPTION_KM_ORIGINATOR *Originator,
2162  _In_ DWORD Options
2163  )
2174 {
2175  if (NULL == Originator)
2176  {
2178  }
2179 
2180  // Save the original RIP; the current RIP is the same until we found otherwise
2181  Originator->Original.Rip = gVcpu->Regs.Rip;
2182  Originator->Return.Rip = gVcpu->Regs.Rip;
2183 
2185  {
2186  Originator->Instruction = &gVcpu->Instruction;
2187  }
2188  else
2189  {
2190  Originator->Instruction = NULL;
2191  }
2192 
2194  {
2195  return IntExceptWinKernelGetOriginator(Originator, Options);
2196  }
2197  else if (gGuest.OSType == introGuestLinux)
2198  {
2199  return IntExceptLixKernelGetOriginator(Originator);
2200  }
2201 
2202  return INT_STATUS_NOT_SUPPORTED;
2203 }
2204 
2205 
2206 INTSTATUS
2208  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2209  _Out_ EXCEPTION_KM_ORIGINATOR *Originator
2210  )
2229 {
2230  INTSTATUS status;
2231 
2232  if (NULL == Victim)
2233  {
2235  }
2236 
2237  if (NULL == Originator)
2238  {
2240  }
2241 
2243  {
2244  ERROR("[ERROR] Integrity alerts are not supported on guests %d\n", gGuest.OSType);
2245  return INT_STATUS_NOT_SUPPORTED;
2246  }
2247 
2248  Originator->IsIntegrity = TRUE;
2249 
2250  if (!IS_KERNEL_POINTER_WIN(gGuest.Guest64, Victim->WriteInfo.NewValue[0]) &&
2251  (Victim->Object.Type == introObjectTypeFastIoDispatch))
2252  {
2253  if ((gGuest.Guest64 && FIELD_OFFSET(FAST_IO_DISPATCH64, SizeOfFastIoDispatch) == Victim->Integrity.Offset) ||
2254  (!gGuest.Guest64 && FIELD_OFFSET(FAST_IO_DISPATCH32, SizeOfFastIoDispatch) == Victim->Integrity.Offset))
2255  {
2256  if (Victim->WriteInfo.NewValue[0] < 0x60 || Victim->WriteInfo.NewValue[0] > 0x200)
2257  {
2258  WARNING("[WARNING] The new size 0x%016llx is too big...\n", Victim->WriteInfo.NewValue[0]);
2260  }
2261 
2263  }
2264 
2265  WARNING("[WARNING] Not writing on size field & writing non-pointer value: 0x%016llx\n",
2266  Victim->WriteInfo.NewValue[0]);
2267  }
2268 
2269  if (Victim->Object.Type == introObjectTypeDriverObject ||
2270  Victim->Object.Type == introObjectTypeFastIoDispatch ||
2271  Victim->Object.Type == introObjectTypeHalDispatchTable ||
2272  Victim->Object.Type == introObjectTypeKmLoggerContext ||
2273  Victim->Object.Type == introObjectTypeIdt)
2274  {
2275  QWORD addr = 0;
2276 
2277  if (Victim->Object.Type == introObjectTypeIdt)
2278  {
2279  if (gGuest.Guest64)
2280  {
2281  IDT_ENTRY64 *pDescr = (IDT_ENTRY64 *)(Victim->WriteInfo.NewValue);
2282  addr = ((QWORD)pDescr->Offset63_32 << 32)
2283  | ((pDescr->Offset31_16 << 16) & 0xFFFF0000) | pDescr->Offset15_0;
2284  }
2285  else
2286  {
2287  IDT_ENTRY32 *pDescr = (IDT_ENTRY32 *)(Victim->WriteInfo.NewValue);
2288  addr = ((pDescr->Offset31_16 << 16) & 0xFFFF0000) | pDescr->Offset15_0;
2289  }
2290  }
2291  else
2292  {
2293  addr = Victim->WriteInfo.NewValue[0];
2294  }
2295 
2297  {
2298  Originator->Return.Driver = IntDriverFindByAddress(addr);
2299  }
2300 
2301  if (NULL == Originator->Return.Driver)
2302  {
2303  if (introObjectTypeIdt != Victim->Object.Type)
2304  {
2305  WARNING("[WARNING] Written value is not a kernel pointer or inside any driver: 0x%016llx\n", addr);
2307  }
2308 
2309  Originator->Return.NameHash = INITIAL_CRC_VALUE;
2310  }
2311  else if (Originator->Return.Driver->BaseVa == gGuest.KernelVa)
2312  {
2313  Originator->Return.NameHash = kmExcNameKernel;
2314  }
2315  else if (0 == wstrcasecmp(Originator->Return.Driver->Name, u"hal.dll") ||
2316  0 == wstrcasecmp(Originator->Return.Driver->Name, u"halmacpi.dll") ||
2317  0 == wstrcasecmp(Originator->Return.Driver->Name, u"halacpi.dll"))
2318  {
2319  Originator->Return.NameHash = kmExcNameHal;
2320  }
2321  else
2322  {
2323  Originator->Return.NameHash = Originator->Return.Driver->NameHash;
2324  }
2325 
2326  // And now, copy everything into the original field too
2327  Originator->Original.NameHash = Originator->Return.NameHash;
2328  Originator->Original.Driver = Originator->Return.Driver;
2329 
2330  status = INT_STATUS_SUCCESS;
2331  }
2332  else
2333  {
2334  status = INT_STATUS_NOT_SUPPORTED;
2335  }
2336 
2337  return status;
2338 }
2339 
2340 
2341 INTSTATUS
2343  _In_ DTR *NewValue,
2344  _In_ DTR *OldValue,
2345  _In_ INTRO_OBJECT_TYPE Type,
2347  )
2361 {
2362  if (NULL == NewValue)
2363  {
2365  }
2366 
2367  if (NULL == OldValue)
2368  {
2370  }
2371 
2372  if (NULL == Victim)
2373  {
2375  }
2376 
2377  Victim->Object.Type = Type;
2378  Victim->ZoneType = exceptionZoneDtr;
2379 
2380  Victim->WriteInfo.NewValue[0] = NewValue->Base;
2381  Victim->WriteInfo.NewValue[1] = NewValue->Limit;
2382  Victim->Dtr.Type = Type;
2383  Victim->WriteInfo.OldValue[0] = OldValue->Base;
2384  Victim->WriteInfo.OldValue[1] = OldValue->Limit;
2385  Victim->WriteInfo.AccessSize = gGuest.WordSize + 2;
2386 
2387  Victim->ZoneFlags |= ZONE_WRITE;
2388 
2389  return INT_STATUS_SUCCESS;
2390 }
2391 
2392 
2393 INTSTATUS
2395  _In_ QWORD NewValue,
2396  _In_ QWORD OldValue,
2397  _In_ DWORD Msr,
2399  )
2411 {
2412  if (NULL == Victim)
2413  {
2415  }
2416 
2417  // Type is relevant only in EPT zone, where we don't know what zone it is. Here we know it's a MSR.
2418  Victim->Object.Type = 0;
2419  Victim->ZoneType = exceptionZoneMsr;
2420 
2421  Victim->WriteInfo.NewValue[0] = NewValue;
2422  Victim->Msr.Msr = Msr;
2423  Victim->WriteInfo.OldValue[0] = OldValue;
2424  Victim->WriteInfo.AccessSize = gGuest.WordSize;
2425 
2426  Victim->Msr.NewDriverBase = 0;
2427  Victim->ZoneFlags |= ZONE_WRITE;
2428 
2429  KERNEL_DRIVER *pDriver = IntDriverFindByAddress(NewValue);
2430  if (pDriver)
2431  {
2432  Victim->Msr.NewDriverBase = pDriver->BaseVa;
2433  }
2434 
2435  return INT_STATUS_SUCCESS;
2436 }
2437 
2438 
2439 INTSTATUS
2441  _In_ INTEGRITY_REGION *IntegrityRegion,
2442  _Inout_ DWORD *Offset,
2444  )
2464 {
2465  INTSTATUS status;
2466  BYTE *pPage, *pOriginal;
2467  DWORD i;
2468  BOOLEAN found;
2469 
2470  if (NULL == IntegrityRegion)
2471  {
2473  }
2474 
2475  if (NULL == Offset)
2476  {
2478  }
2479 
2480  if (NULL == Victim)
2481  {
2483  }
2484 
2486  {
2487  ERROR("[ERROR] Integrity alerts are not supported on guests %d\n", gGuest.OSType);
2488  return INT_STATUS_NOT_SUPPORTED;
2489  }
2490 
2491  pOriginal = IntegrityRegion->OriginalContent;
2492  found = FALSE;
2493 
2494  status = IntVirtMemMap(IntegrityRegion->Gva, IntegrityRegion->Length, gGuest.Mm.SystemCr3, 0, &pPage);
2495  if (!INT_SUCCESS(status))
2496  {
2497  ERROR("[ERROR] Failed mapping/reading at GVA 0x%016llx, with length %x: 0x%08x\n",
2498  IntegrityRegion->Gva, IntegrityRegion->Length, status);
2499  return status;
2500  }
2501 
2502  // Search for the first modification, starting at the given offset.
2503  for (i = *Offset; i < IntegrityRegion->Length; i++)
2504  {
2505  if (pPage[i] != pOriginal[i])
2506  {
2507  found = TRUE;
2508  break;
2509  }
2510  }
2511 
2512  if (!found)
2513  {
2514  status = INT_STATUS_NOT_FOUND;
2515  *Offset = IntegrityRegion->Length;
2516  goto _cleanup_and_leave;
2517  }
2518 
2519  // On idt, the offset at which the write occurred must be considered the start of the entry.
2520  // On x64, if a write occurs, let's say, at offset 15 inside the entry, we would wrongfully
2521  // take the offset to be equal to entry + 8, leading to possible misleading information, and
2522  // if it is the last entry, the modification might be deemed "outside the integrity region",
2523  // which should not occur.
2524  switch (IntegrityRegion->Type)
2525  {
2526  case introObjectTypeIdt:
2528  break;
2529  default:
2530  i = ALIGN_DOWN(i, gGuest.WordSize);
2531  break;
2532  }
2533 
2534  *Offset = i + gGuest.WordSize; // the next word
2535 
2536  Victim->ZoneType = exceptionZoneIntegrity;
2537  Victim->Object.Type = IntegrityRegion->Type;
2538  Victim->ZoneFlags |= ZONE_WRITE | ZONE_INTEGRITY;
2539 
2540  Victim->Integrity.StartVirtualAddress = IntegrityRegion->Gva;
2541  Victim->Integrity.TotalLength = IntegrityRegion->Length;
2542  Victim->Integrity.Offset = i;
2543 
2544  switch (IntegrityRegion->Type)
2545  {
2546  case introObjectTypeIdt:
2547  if (gGuest.Guest64)
2548  {
2549  Victim->WriteInfo.AccessSize = sizeof(IDT_ENTRY64);
2550  }
2551  else
2552  {
2553  Victim->WriteInfo.AccessSize = sizeof(IDT_ENTRY32);
2554  }
2555 
2556  *Offset += gGuest.WordSize;
2557  break;
2558 
2559  default:
2560  Victim->WriteInfo.AccessSize = gGuest.WordSize;
2561  break;
2562  }
2563 
2564  // Don't exit if the access size has not filled the whole buffer. Note that for a region
2565  // with size 4, there might be a write at offset 1 of size gGuest.WordSize == 8. We should
2566  // fit in the buffer the interesting values, the ones in the integrity region which were
2567  // accessed at least.
2568  if (i + Victim->WriteInfo.AccessSize > IntegrityRegion->Length)
2569  {
2570  Victim->WriteInfo.AccessSize = IntegrityRegion->Length - i;
2571  }
2572 
2573  memcpy(Victim->WriteInfo.OldValue, pOriginal + i, Victim->WriteInfo.AccessSize);
2574  memcpy(Victim->WriteInfo.NewValue, pPage + i, Victim->WriteInfo.AccessSize);
2575 
2576  switch (IntegrityRegion->Type)
2577  {
2580  {
2581  WIN_DRIVER_OBJECT *pDrvObj = IntegrityRegion->Context;
2582 
2583  if (NULL == pDrvObj)
2584  {
2585  LOG("We must have a integrity context (a driver object)\n");
2587  goto _cleanup_and_leave;
2588  }
2589 
2590  Victim->Object.NameHash = pDrvObj->NameHash;
2591  Victim->Object.DriverObject = pDrvObj;
2592  Victim->Object.BaseAddress = pDrvObj->DriverObjectGva;
2593 
2594  break;
2595  }
2598  {
2599  break;
2600  }
2601  case introObjectTypeIdt:
2602  {
2603  Victim->Object.BaseAddress = IntegrityRegion->Gva;
2604  break;
2605  }
2606 
2607  default:
2608  LOG("Invalid integrity region type: %d\n", IntegrityRegion->Type);
2609  break;
2610  }
2611 
2612 _cleanup_and_leave:
2613  IntVirtMemUnmap(&pPage);
2614 
2615  return status;
2616 }
2617 
2618 
2619 INTSTATUS
2621  _In_ QWORD NewValue,
2622  _In_ QWORD OldValue,
2623  _In_ DWORD Cr,
2625  )
2639 {
2640  if (NULL == Victim)
2641  {
2643  }
2644 
2645  if (4 != Cr)
2646  {
2647  return INT_STATUS_NOT_SUPPORTED;
2648  }
2649 
2650  Victim->ZoneType = exceptionZoneCr;
2651  Victim->ZoneFlags |= ZONE_WRITE;
2652  Victim->Object.Type = (DWORD) -1;
2653 
2654  Victim->WriteInfo.NewValue[0] = NewValue;
2655  Victim->WriteInfo.OldValue[0] = OldValue;
2656  Victim->Cr.Cr = Cr;
2657 
2658  Victim->WriteInfo.AccessSize = sizeof(QWORD);
2659 
2660  Victim->Cr.Smap = ((OldValue & CR4_SMAP) != 0) && ((NewValue & CR4_SMAP) == 0);
2661  Victim->Cr.Smep = ((OldValue & CR4_SMEP) != 0) && ((NewValue & CR4_SMEP) == 0);
2662 
2663  return INT_STATUS_SUCCESS;
2664 }
2665 
2666 
2667 INTSTATUS
2669  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2670  _In_ EXCEPTION_UM_ORIGINATOR *Originator,
2671  _In_ UM_EXCEPTION *Exception
2672  )
2682 {
2683  UNREFERENCED_PARAMETER(Victim);
2684  UNREFERENCED_PARAMETER(Originator);
2685  UNREFERENCED_PARAMETER(Exception);
2686 
2688 }
2689 
2690 
2691 INTSTATUS
2693  _In_ EXCEPTION_VICTIM_ZONE *Victim,
2694  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
2695  _In_ KM_EXCEPTION *Exception
2696  )
2717 {
2718  BOOLEAN match = FALSE;
2719 
2720  if ((Exception->Flags & EXCEPTION_FLG_READ) &&
2721  (Victim->ZoneFlags & ZONE_READ))
2722  {
2723  match = TRUE;
2724  }
2725 
2726  if ((Exception->Flags & EXCEPTION_FLG_EXECUTE) &&
2727  (Victim->ZoneFlags & ZONE_EXECUTE))
2728  {
2729  match = TRUE;
2730  }
2731 
2732  if ((Exception->Flags & EXCEPTION_FLG_WRITE) &&
2733  (Victim->ZoneFlags & ZONE_WRITE))
2734  {
2735  match = TRUE;
2736  }
2737 
2738  if (!match)
2739  {
2741  }
2742 
2743  if ((Exception->Flags & EXCEPTION_KM_FLG_INTEGRITY) &&
2744  (Victim->ZoneType != exceptionZoneIntegrity))
2745  {
2747  }
2748 
2749  if ((Exception->Flags & EXCEPTION_KM_FLG_NON_DRIVER) &&
2750  (Originator->Original.Driver != NULL))
2751  {
2753  }
2754 
2755  match = FALSE;
2756 
2757  if ((Exception->Flags & EXCEPTION_FLG_32) &&
2758  (Exception->Flags & EXCEPTION_FLG_64))
2759  {
2760  match = TRUE;
2761  }
2762  else if ((Exception->Flags & EXCEPTION_FLG_64) &&
2763  gGuest.Guest64)
2764  {
2765  match = TRUE;
2766  }
2767  else if ((Exception->Flags & EXCEPTION_FLG_32) &&
2768  !gGuest.Guest64)
2769  {
2770  match = TRUE;
2771  }
2772 
2773  if (!match)
2774  {
2776  }
2777 
2778  match = FALSE;
2779 
2780  if (Exception->VictimNameHash == kmExcNameAny ||
2781  Exception->VictimNameHash == Victim->Object.NameHash)
2782  {
2783  match = TRUE;
2784  }
2785  else if (Exception->VictimNameHash == kmExcNameOwn)
2786  {
2787  KERNEL_DRIVER *pDriver = (Exception->Flags & EXCEPTION_KM_FLG_RETURN_DRV) ?
2788  Originator->Return.Driver : Originator->Original.Driver;
2789 
2790  if (pDriver && gGuest.OSType == introGuestWindows)
2791  {
2792  if (Victim->Object.Type == introObjectTypeKmModule)
2793  {
2794  match = Victim->Object.BaseAddress == pDriver->BaseVa;
2795  }
2796  else if ((Victim->Object.Type == introObjectTypeDriverObject) ||
2797  (Victim->Object.Type == introObjectTypeFastIoDispatch))
2798  {
2799  // Do this check, since some drivers don't have a DriverObject
2800  if (Victim->Object.DriverObject && pDriver->Win.DriverObject)
2801  {
2802  // Also, check by Gpa since a driver object may be pointed from different Gva
2803  match = Victim->Object.DriverObject->DriverObjectGpa == pDriver->Win.DriverObject->DriverObjectGpa;
2804  }
2805  }
2806  }
2807  else if (pDriver && gGuest.OSType == introGuestLinux)
2808  {
2809  if (Victim->Object.Type == introObjectTypeKmModule)
2810  {
2811  match = Victim->Object.BaseAddress == pDriver->Lix.CoreLayout.Base;
2812  }
2813  }
2814  }
2815 
2816  if (!match)
2817  {
2819  }
2820 
2821  match = FALSE;
2822 
2823  switch (Exception->Type)
2824  {
2825  case kmObjAny:
2826  match = TRUE;
2827  break;
2828 
2829  case kmObjDriver:
2830  if (Victim->Object.Type == introObjectTypeKmModule)
2831  {
2832  match = TRUE;
2833  }
2834  break;
2835 
2836  case kmObjDriverImports:
2837  if ((Victim->Object.Type == introObjectTypeKmModule) &&
2838  (Victim->ZoneFlags & ZONE_LIB_IMPORTS))
2839  {
2840  match = TRUE;
2841  }
2842  break;
2843 
2844  case kmObjDriverExports:
2845  if ((Victim->Object.Type == introObjectTypeKmModule) &&
2846  (Victim->ZoneFlags & ZONE_LIB_EXPORTS))
2847  {
2848  match = TRUE;
2849  }
2850  break;
2851 
2852  case kmObjDriverCode:
2853  if ((Victim->Object.Type == introObjectTypeKmModule &&
2854  (Victim->ZoneFlags & ZONE_LIB_CODE)) ||
2855  Victim->Object.Type == introObjectTypeVsyscall ||
2856  Victim->Object.Type == introObjectTypeVdso)
2857  {
2858  match = TRUE;
2859  }
2860  break;
2861 
2862  case kmObjDriverData:
2863  if ((Victim->Object.Type == introObjectTypeKmModule) &&
2864  (Victim->ZoneFlags & ZONE_LIB_DATA))
2865  {
2866  match = TRUE;
2867  }
2868  break;
2869 
2870  case kmObjDriverResources:
2871  if ((Victim->Object.Type == introObjectTypeKmModule) &&
2872  (Victim->ZoneFlags & ZONE_LIB_RESOURCES))
2873  {
2874  match = TRUE;
2875  }
2876  break;
2877 
2878  case kmObjSsdt:
2879  if (Victim->Object.Type == introObjectTypeSsdt)
2880  {
2881  match = TRUE;
2882  }
2883  break;
2884 
2885  case kmObjDrvObj:
2886  if (Victim->Object.Type == introObjectTypeDriverObject)
2887  {
2888  match = TRUE;
2889  }
2890  break;
2891 
2892  case kmObjFastIo:
2893  if (Victim->Object.Type == introObjectTypeFastIoDispatch)
2894  {
2895  match = TRUE;
2896  }
2897  break;
2898 
2899  case kmObjMsr:
2900  if (Victim->ZoneType == exceptionZoneMsr)
2901  {
2902  match = TRUE;
2903  }
2904  break;
2905 
2906  case kmObjCr4:
2907  if (Victim->ZoneType == exceptionZoneCr)
2908  {
2909  match = TRUE;
2910  }
2911  break;
2912 
2913  case kmObjHalHeap:
2914  if ((Victim->ZoneType == exceptionZoneEpt) &&
2915  ((Victim->Object.Type == introObjectTypeHalIntController) ||
2916  (Victim->Object.Type == introObjectTypeHalHeap)))
2917  {
2918  match = TRUE;
2919  }
2920  break;
2921 
2922  case kmObjSharedUserData:
2923  if ((Victim->ZoneType == exceptionZoneEpt) &&
2924  (Victim->Object.Type == introObjectTypeSharedUserData))
2925  {
2926  match = TRUE;
2927  }
2928  break;
2929 
2930  case kmObjSelfMapEntry:
2931  if ((Victim->ZoneType == exceptionZoneEpt) &&
2932  (Victim->Object.Type == introObjectTypeSelfMapEntry))
2933  {
2934  match = TRUE;
2935  }
2936  break;
2937 
2938  case kmObjIdt:
2939  if ((Victim->ZoneType == exceptionZoneEpt ||
2940  Victim->ZoneType == exceptionZoneIntegrity) &&
2941  Victim->Object.Type == introObjectTypeIdt)
2942  {
2943  match = TRUE;
2944  }
2945  break;
2946 
2947  case kmObjIdtr:
2948  if ((Victim->ZoneType == exceptionZoneDtr) &&
2949  (Victim->Object.Type == introObjectTypeIdtr))
2950  {
2951  match = TRUE;
2952  }
2953  break;
2954 
2955  case kmObjGdtr:
2956  if ((Victim->ZoneType == exceptionZoneDtr) &&
2957  (Victim->Object.Type == introObjectTypeGdtr))
2958  {
2959  match = TRUE;
2960  }
2961  break;
2962 
2963  case kmObjLoggerCtx:
2964  if (Victim->Object.Type == introObjectTypeKmLoggerContext)
2965  {
2966  match = TRUE;
2967  }
2968  break;
2969 
2970  case kmObjTokenPrivs:
2971  if (Victim->Object.Type == introObjectTypeTokenPrivs)
2972  {
2973  match = TRUE;
2974  }
2975  break;
2976 
2977  default:
2978  LOG("[ERROR] This is a corruption in the update/exception. Type = %d!\n", Exception->Type);
2979  break;
2980  }
2981 
2982  if (!match)
2983  {
2985  }
2986 
2987  if (Exception->Flags & EXCEPTION_FLG_INIT)
2988  {
2989  match = FALSE;
2990 
2991  // a. On integrity zones, this is all we can check
2992  if ((Victim->ZoneType == exceptionZoneIntegrity) &&
2993  (Victim->WriteInfo.OldValue[0] == 0))
2994  {
2995  match = TRUE;
2996  }
2997  // b. Kernel's INIT section writes
2998  else if ((Exception->Flags & EXCEPTION_KM_FLG_RETURN_DRV) &&
2999  (Originator->Return.NameHash == kmExcNameKernel))
3000  {
3001  // match anything that starts with init/INIT
3003  {
3004  match = 0 == memcmp(Originator->Return.Section, "INIT", 4);
3005  }
3006  else
3007  {
3008  match = 0 == memcmp(Originator->Return.Section, "init", 4);
3009  }
3010  }
3011  else if (Originator->Original.NameHash == kmExcNameKernel)
3012  {
3013  // match anything that starts with init/INIT
3015  {
3016  match = 0 == memcmp(Originator->Original.Section, "INIT", 4);
3017  }
3018  else
3019  {
3020  match = 0 == memcmp(Originator->Original.Section, "init", 4);
3021  }
3022  }
3023  // c. RIP is in EntryPoint
3024  else if (Originator->IsEntryPoint)
3025  {
3026  match = TRUE;
3027  }
3028  // d. Old value was 0
3029  else if (Victim->WriteInfo.OldValue[0] == 0)
3030  {
3031  match = TRUE;
3032  }
3033 
3034  if (!match)
3035  {
3037  }
3038  }
3039 
3040  if (kmObjCr4 == Exception->Type)
3041  {
3042  // We don't care about the activation of these flags (we allow it). But the deactivation is another story...
3043  match = FALSE;
3044 
3045  if ((Exception->Flags & EXCEPTION_KM_FLG_SMAP) &&
3046  (Exception->Flags & EXCEPTION_KM_FLG_SMEP))
3047  {
3048  match = TRUE;
3049  }
3050  else if ((Exception->Flags & EXCEPTION_KM_FLG_SMAP) &&
3051  (Victim->Cr.Smap))
3052  {
3053  match = TRUE;
3054  }
3055  else if ((Exception->Flags & EXCEPTION_KM_FLG_SMEP) &&
3056  Victim->Cr.Smep)
3057  {
3058  match = TRUE;
3059  }
3060 
3061  if (!match)
3062  {
3064  }
3065  }
3066 
3067  // If we get here, then allow the action. Anyway, the extra checks & signatures mechanism will actually allow it
3069 }
3070 
3071 
3072 INTSTATUS
3074  _In_ EXCEPTION_VICTIM_ZONE *Victim,
3075  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
3076  _Out_ INTRO_ACTION *Action,
3077  _Out_ INTRO_ACTION_REASON *Reason
3078  )
3095 {
3097  BOOLEAN sameRip = FALSE;
3098  BYTE id;
3099 
3100  if (NULL == Victim)
3101  {
3103  }
3104 
3105  if (NULL == Originator)
3106  {
3108  }
3109 
3110  if (NULL == Action)
3111  {
3113  }
3114 
3115  if (NULL == Reason)
3116  {
3118  }
3119 
3120  *Action = introGuestNotAllowed;
3121  *Reason = introReasonNoException;
3122 
3124  {
3125  if (pEx->OriginatorNameHash == kmExcNameAny)
3126  {
3127  // For now, we do not support exceptions from the alert that has originator kmExcNameAny.
3128  // If an exception from the alert has no originator, kmExcNameNone will be used as the exception originator
3129  goto _match_ex_alert;
3130  }
3131 
3132  if (Originator->Original.NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == kmExcNameNone)
3133  {
3134  goto _match_ex_alert;
3135  }
3136 
3137  if (pEx->OriginatorNameHash > Originator->Original.NameHash)
3138  {
3139  break;
3140  }
3141  else if (pEx->OriginatorNameHash != Originator->Original.NameHash)
3142  {
3143  continue;
3144  }
3145 
3146 _match_ex_alert:
3147  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3148  if (status == INT_STATUS_EXCEPTION_ALLOW)
3149  {
3150  return status;
3151  }
3152  }
3153 
3154  if (Originator->Original.NameHash == INITIAL_CRC_VALUE)
3155  {
3156  // Check the no name exceptions, and skip the generic ones
3158  {
3159  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3160  if (status == INT_STATUS_EXCEPTION_ALLOW)
3161  {
3162  return status;
3163  }
3164  }
3165  }
3166  else
3167  {
3168  // Check the generic exceptions (all of them, since originator matches anything)
3170  {
3171  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3172  if (status == INT_STATUS_EXCEPTION_ALLOW)
3173  {
3174  return status;
3175  }
3176  }
3177  }
3178 
3179  if (Originator->Original.Driver && Originator->Return.Driver &&
3180  (Originator->Original.Rip == Originator->Return.Rip))
3181  {
3182  // Don't check by RIP since it may be in different sections
3183  sameRip = TRUE;
3184  }
3185 
3186  if (Originator->Original.NameHash != INITIAL_CRC_VALUE)
3187  {
3188  id = EXCEPTION_TABLE_ID(Originator->Original.NameHash);
3189 
3191  {
3192  // Here we only check exceptions by the name, so that cannot be missing.
3193  // And the return flag must be missing.
3194  if (pEx->OriginatorNameHash == INITIAL_CRC_VALUE ||
3195  ((pEx->Flags & EXCEPTION_KM_FLG_RETURN_DRV) &&
3196  !sameRip))
3197  {
3198  continue;
3199  }
3200 
3201  // Every list is ordered, so break when we got to a hash bigger than ours
3202  if (pEx->OriginatorNameHash > Originator->Original.NameHash)
3203  {
3204  break;
3205  }
3206  else if (pEx->OriginatorNameHash != Originator->Original.NameHash)
3207  {
3208  continue;
3209  }
3210 
3211  // The EXCEPTION_KM_FLG_RETURN_DRV will be deleted, so do the same verification again
3212  if ((pEx->Flags & EXCEPTION_FLG_RETURN) && !sameRip)
3213  {
3214  continue;
3215  }
3216 
3217  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3218  if (status == INT_STATUS_EXCEPTION_ALLOW)
3219  {
3220  return status;
3221  }
3222  }
3223 
3224  if (sameRip)
3225  {
3226  // No point in doing the same thing again
3227  goto _beta_exceptions;
3228  }
3229  }
3230 
3231  // Try and match the original driver by name
3232  if (Originator->Return.NameHash != INITIAL_CRC_VALUE)
3233  {
3234  id = EXCEPTION_TABLE_ID(Originator->Return.NameHash);
3236  {
3237  // Here we only check exceptions by the name, so that cannot be missing
3238  // And the return flag must be set
3239  if (pEx->OriginatorNameHash == INITIAL_CRC_VALUE ||
3240  (0 == (pEx->Flags & EXCEPTION_KM_FLG_RETURN_DRV)))
3241  {
3242  continue;
3243  }
3244 
3245  // Every list is ordered, so break when we got to a hash bigger than ours
3246  if (pEx->OriginatorNameHash > Originator->Return.NameHash)
3247  {
3248  break;
3249  }
3250  else if (pEx->OriginatorNameHash != Originator->Return.NameHash)
3251  {
3252  continue;
3253  }
3254 
3255  // The EXCEPTION_KM_FLG_RETURN_DRV will be deleted, so do the same verification again
3256  if (0 == (pEx->Flags & EXCEPTION_FLG_RETURN))
3257  {
3258  continue;
3259  }
3260 
3261  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3262  if (status == INT_STATUS_EXCEPTION_ALLOW)
3263  {
3264  return status;
3265  }
3266  }
3267  }
3268 
3269 _beta_exceptions:
3271  {
3272  if (pEx->OriginatorNameHash == kmExcNameAny)
3273  {
3274  goto _match_ex;
3275  }
3276 
3277  if (Originator->Original.NameHash == INITIAL_CRC_VALUE && pEx->OriginatorNameHash == kmExcNameNone)
3278  {
3279  goto _match_ex;
3280  }
3281 
3282  if (pEx->Flags & EXCEPTION_FLG_RETURN)
3283  {
3284  if (pEx->OriginatorNameHash != Originator->Return.NameHash)
3285  {
3286  continue;
3287  }
3288  }
3289  else
3290  {
3291  if (pEx->OriginatorNameHash != Originator->Original.NameHash)
3292  {
3293  continue;
3294  }
3295  }
3296 _match_ex:
3297  status = IntExceptMatchException(Victim, Originator, pEx, exceptionTypeKm, Action, Reason);
3298  if (status == INT_STATUS_EXCEPTION_ALLOW)
3299  {
3300  return status;
3301  }
3302  }
3303 
3304  return status;
3305 }
#define IMAGE_SCN_MEM_EXECUTE
Definition: winpe.h:472
WORD Offset15_0
Definition: processor.h:134
INTSTATUS IntExceptKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator, DWORD Options)
This function is used to get the information about the kernel-mode originator.
#define _In_opt_
Definition: intro_sal.h:16
#define EXCEPTION_NO_INSTRUCTION
Definition: exceptions.h:30
QWORD DriverObjectGva
The guest virtual address of the guest _DRIVER_OBJECT represented by this structure.
Definition: windrvobj.h:18
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
#define DESCRIPTOR_SIZE_32
Definition: processor.h:101
#define INT_STATUS_EXCEPTION_NOT_MATCHED
Definition: introstatus.h:406
INTSTATUS IntPeGetSectionHeaderByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD GuestRva, IMAGE_SECTION_HEADER *SectionHeader)
Given a relative virtual address, return the section header which describes the section the RVA lies ...
Definition: winpe.c:682
_Bool BOOLEAN
Definition: intro_types.h:58
static int IntExceptPrintDrvObjInfo(WIN_DRIVER_OBJECT *DrvObj, char *Header, char *Line, int MaxLength)
Print the information about the WIN_DRIVER_OBJECT.
#define _Out_
Definition: intro_sal.h:22
#define IG_IA32_SYSENTER_ESP
Definition: glueiface.h:139
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
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
INTSTATUS IntExceptGetVictimMsr(QWORD NewValue, QWORD OldValue, DWORD Msr, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the MSR victim.
QWORD End
The end guest virtual address of ksym (exclusive).
Definition: lixguest.h:436
Kernel module (ntoskrnl.exe, hal.dll, etc.)
Definition: intro_types.h:235
uint8_t BYTE
Definition: intro_types.h:47
BYTE Unknown
Set if the function at this RIP is not exported.
Definition: drivers.h:20
INTSTATUS IntExceptGetVictimIntegrity(INTEGRITY_REGION *IntegrityRegion, DWORD *Offset, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the modified zone from the integrity region...
static int IntExceptPrintIdtInfo(EXCEPTION_VICTIM_ZONE *Victim, char *Header, char *Line, int MaxLength)
Print the information about the modified IDT entry.
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
Definition: winguest.c:35
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
The modified object is anything inside the HAL heap zone.
Definition: exceptions.h:168
#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
Fast IO Dispatch (Windows only)
Definition: intro_types.h:233
LIST_HEAD NoNameKernelExceptions
Linked list used for kernel-mode exceptions that don&#39;t have a valid originator (-).
Definition: exceptions.h:98
The name can be any string.
Definition: exceptions.h:626
INTSTATUS IntExceptGetVictimCr(QWORD NewValue, QWORD OldValue, DWORD Cr, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the CR victim.
Infinity hook modifications of WMI_LOGGER_CONTEXT.GetCpuClock.
Definition: intro_types.h:261
WIN_KERNEL_DRIVER Win
Valid only for Windows guests.
Definition: drivers.h:70
The modified object is only the driver&#39;s EAT.
Definition: exceptions.h:159
struct _IDT_ENTRY32 IDT_ENTRY32
INTSTATUS IntLixStackTraceGetReg(QWORD Cr3, PIG_ARCH_REGS Registers, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace)
Retrieves a Kernel stack backtrace based on the register values.
Definition: lixstack.c:225
#define ZONE_LIB_RESOURCES
Used for the resources section (usually .rsrc inside a driver or dll).
Definition: exceptions.h:691
QWORD Start
The start guest virtual address of ksym.
Definition: lixguest.h:435
INTSTATUS IntKsymFindByAddress(QWORD Gva, DWORD Length, char *SymName, QWORD *SymStart, QWORD *SymEnd)
Finds the symbol which is located at the given address.
Definition: lixksym.c:1245
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
Definition: drivers.h:41
The exception will take into consideration the return driver/dll.
Definition: exceptions.h:591
#define IMAGE_SCN_MEM_WRITE
Definition: winpe.h:474
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
#define EXCEPTION_NO_NAME
Definition: exceptions.h:28
#define ARRAYSIZE(A)
Definition: introdefs.h:101
WORD Offset31_16
Definition: processor.h:148
The modified object is inside an EPT hook.
Definition: exceptions.h:710
BOOLEAN KernelBetaDetections
True if the kernel protection is in beta (log-only) mode.
Definition: guests.h:299
WORD Offset31_16
Definition: processor.h:137
#define INT_STATUS_EXCEPTION_CHECKS_OK
Definition: introstatus.h:396
void IntDriverCacheCreateExport(const QWORD Rip)
Adds a new export entry to the gDriverExportCache.
Definition: drivers.c:432
static INTSTATUS IntExceptLixKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator)
This function is used to get the information about the kernel-mode originator (Linux guest)...
DWORD PathLength
The driver`s path length (number of WCHARS).
Definition: windriver.h:26
The exception is valid only for read violation.
Definition: exceptions.h:595
#define EXCEPTION_KM_ORIGINATOR_OPT_DO_NOT_BLOCK
Flags that can be passed to IntExceptKernelGetOriginator if the action should not be blocked...
Definition: exceptions.h:992
PBYTE MzPeHeaders
The driver`s MZ/PE headers (cached internally).
Definition: windriver.h:34
QWORD Parent
Depends if this is a thread or a process.
Definition: lixprocess.h:57
#define IG_IA32_SYSENTER_EIP
Definition: glueiface.h:140
#define ERROR(fmt,...)
Definition: glue.h:62
Describes a user-mode originator.
Definition: exceptions.h:933
INTSTATUS IntPeFindExportByRvaInBuffer(QWORD ImageBase, BYTE *Buffer, DWORD BufferSize, DWORD Rva)
Check if the indicated Rva belongs to an exported function.
Definition: winpe.c:1198
INTSTATUS IntExceptGetVictimDtr(DTR *NewValue, DTR *OldValue, INTRO_OBJECT_TYPE Type, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the DTR victim.
The modified object is only the driver&#39;s data sections.
Definition: exceptions.h:161
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
The _FAST_IO_DISPATCH structure used by 32-bit guests.
Definition: wddefs.h:280
LIX_MODULE_LAYOUT CoreLayout
The layout of the core section.
Definition: lixmodule.h:40
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
The exception will match only for the init phase of a driver/process.
Definition: exceptions.h:589
#define ONE_KILOBYTE
Definition: introdefs.h:89
LIST_HEAD KernelAlertExceptions
Linked list used for kernel-mode exceptions that are added from alert.
Definition: exceptions.h:127
The name is missing.
Definition: exceptions.h:630
#define MAX_PATH
The maximum size of a path (260 characters on windows).
Definition: winpe.h:579
INTSTATUS IntExceptGetOriginatorFromModification(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator)
This function is used for integrity violations to get the information about the kernel-mode originato...
Describes a kernel-mode originator.
Definition: exceptions.h:897
The modified object is only the driver&#39;s IAT.
Definition: exceptions.h:175
DWORD Offset63_32
Definition: processor.h:138
int IntExceptPrintWinKmModInfo(KERNEL_DRIVER *Module, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the information about the provided KERNEL_DRIVER (windows guest).
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:274
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
Definition: guests.h:88
struct _DRIVER_EXPORT_CACHE_ENTRY::@23 Type
The exception is valid only for write violation.
Definition: exceptions.h:596
#define MIN(a, b)
Definition: introdefs.h:146
The modified object is anything inside the driver.
Definition: exceptions.h:158
#define LOG(fmt,...)
Definition: glue.h:61
Describes a kernel driver.
Definition: drivers.h:30
#define ZONE_INTEGRITY
Used for integrity zone.
Definition: exceptions.h:702
DWORD NameHash
The hash of the name.
Definition: drivers.h:59
the modified object is IDTR/GDTR.
Definition: exceptions.h:715
Token privileges.
Definition: intro_types.h:263
enum _INTRO_OBJECT_TYPE INTRO_OBJECT_TYPE
The type of the object protected by an EPT hook.
#define _Inout_
Definition: intro_sal.h:20
The exception is valid only for CR4.SMEP write.
Definition: exceptions.h:606
static int IntExceptPrintMsrInfo(EXCEPTION_VICTIM_ZONE *Victim, char *Header, char *Line, int MaxLength)
Print the information about the modified MSR.
#define ZONE_LIB_CODE
Used for a generic code zone.
Definition: exceptions.h:688
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
#define INT_STATUS_EXCEPTION_BLOCK
Definition: introstatus.h:421
Hal interrupt controller.
Definition: intro_types.h:250
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:388
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
Definition: glueiface.h:324
The modified object is inside an integrity hook.
Definition: exceptions.h:713
The exception is valid only for CR4.SMAP write.
Definition: exceptions.h:605
SIZE_T NameLength
The length of the Name. This is the number of characters in the Name buffer.
Definition: drivers.h:56
#define CR4_SMEP
Definition: processor.h:61
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:700
LIST_HEAD KernelFeedbackExceptions
Linked list used for kernel-mode exceptions that have the feedback flag.
Definition: exceptions.h:116
Holds information about a driver object.
Definition: windrvobj.h:13
CPU_STATE State
The state of this VCPU. Describes what action is the VCPU currently doing.
Definition: guests.h:173
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
unsigned long long QWORD
Definition: intro_types.h:53
The modified object is only the driver&#39;s code sections.
Definition: exceptions.h:160
Handling a LIDT or LGDT.
Definition: guests.h:26
The name is the operating system kernel name.
Definition: exceptions.h:628
DWORD NameHash
Hash of the Name.
Definition: windrvobj.h:34
DRIVER_EXPORT_CACHE_ENTRY * IntDriverCacheExportFind(const QWORD Rip)
Finds an entry inside the gDriverExportCache.
Definition: drivers.c:484
INTSTATUS IntExceptKernelMatchVictim(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, KM_EXCEPTION *Exception)
This function checks if the exception matches the originator and the modified zone.
#define IG_IA32_STAR
Definition: glueiface.h:145
#define TRUE
Definition: intro_types.h:30
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
static BOOLEAN IntExceptLixKernelIsMemoryFunc(QWORD Rip)
This function is used to check if the write has been made using any of "memcpy","__memcpy", "memset", "__memset", "memmove" function.
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
#define TRACE(fmt,...)
Definition: glue.h:58
Executions inside the SharedUserData region.
Definition: intro_types.h:264
Allow modification of it&#39;s own driver object.
Definition: exceptions.h:627
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
The modified object is SSDT (valid only on windows x86).
Definition: exceptions.h:163
static int IntExceptPrintCrInfo(EXCEPTION_VICTIM_ZONE *Victim, char *Header, char *Line, int MaxLength)
Print the information about the modified CR.
The modified object is the self map entry inside PDBR.
Definition: exceptions.h:169
void * Name
The name of the driver.
Definition: drivers.h:54
QWORD KernelVa
The guest virtual address at which the kernel image.
Definition: guests.h:279
struct _IDT_ENTRY64 IDT_ENTRY64
Kernel-mode exception.
Definition: exceptions.h:62
LIX_SYMBOL MemoryFunctions[5]
The guest virtual address of memcpy, __memcpy, memset, __memset, memmove.
Definition: lixguest.h:510
#define IG_IA32_LSTAR
Definition: glueiface.h:146
QWORD DriverObjectGpa
The guest physical address of the guest _DRIVER_OBJECT represented by this structure.
Definition: windrvobj.h:25
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:363
INTSTATUS IntWinStackTraceGet(QWORD StackFrame, QWORD Rip, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace)
Get a kernel stack trace starting from the current stack pointer for 64 bit systems.
Definition: winstack.c:1210
#define DESCRIPTOR_SIZE_64
Definition: processor.h:102
void IntLixDrvGetSecName(KERNEL_DRIVER *Driver, QWORD Gva, CHAR *SectionName)
Get the section of the driver that contains the provided guest virtual address.
Definition: lixmodule.c:913
The modified object is a MSR.
Definition: exceptions.h:711
void IntExceptKernelLogInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a kernel-mode violation and dumps the code-blocks.
LIX_KERNEL_MODULE Lix
Valid only for Linux guests.
Definition: drivers.h:71
#define WARNING(fmt,...)
Definition: glue.h:60
#define EXCEPTION_NO_SYMBOL
Definition: exceptions.h:31
The exception will take into consideration the return driver.
Definition: exceptions.h:604
#define ZONE_LIB_EXPORTS
Used for the exports of a dll, driver, etc.
Definition: exceptions.h:687
DWORD SelfMapIndex
The self map index.
Definition: guests.h:216
#define CR4_SMAP
Definition: processor.h:62
The modified object is the privileges field inside the nt!_TOKEN structure.
Definition: exceptions.h:176
The modified object is SMEP and/or SMAP bits of CR4.
Definition: exceptions.h:167
#define IDT_DESC_SIZE64
The size of a 64-bit interrupt descriptor.
Definition: wddefs.h:32
A descriptor table register. Valid for IDTR and GDTR.
Definition: introcpu.h:71
#define LIX_SYMBOL_NAME_LEN
The max length of the ksym as defined by Linux kernel.
Definition: lixguest.h:582
#define PAGE_SIZE
Definition: common.h:53
Describes the modified zone.
Definition: exceptions.h:847
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
The modified object is IDTR.
Definition: exceptions.h:171
Describe a kernel-mode exception.
Definition: exceptions.h:248
#define for_each_km_exception(_ex_head, _var_name)
Definition: exceptions.h:998
static int IntExceptPrintLixKmDrvInfo(KERNEL_DRIVER *Driver, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the information about the provided KERNEL_DRIVER (Linux guest).
Describe a user-mode exception.
Definition: exceptions.h:298
uint16_t WCHAR
Definition: intro_types.h:63
The Virtualization exception agent injected inside the guest.
Definition: intro_types.h:256
uint32_t DWORD
Definition: intro_types.h:49
DWORD KernelBufferSize
The size of the KernelBuffer.
Definition: winguest.h:838
The exception is valid only for integrity zone.
Definition: exceptions.h:608
UINT32 Characteristics
Definition: winpe.h:92
The modified object is anything inside the driver&#39;s fast IO dispatch table.
Definition: exceptions.h:165
The modified object is any with the modified name.
Definition: exceptions.h:157
enum _INTRO_ACTION INTRO_ACTION
Event actions.
#define IMAGE_SCN_CNT_CODE
Definition: winpe.h:425
INTSTATUS IntExceptKernelVerifyExtra(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, UM_EXCEPTION *Exception)
This function is used as an extra step in exception mechanism.
LIST_HEAD GenericKernelExceptions
Linked list used for kernel-mode exceptions that have a generic originator (*).
Definition: exceptions.h:90
The action was allowed, but it has the BETA flag (Introcore is in log-only mode). ...
Definition: intro_types.h:185
#define MAX(a, b)
Definition: introdefs.h:151
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
Definition: introcore.c:2134
#define ZONE_LIB_DATA
Definition: exceptions.h:689
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:370
The modified object represents an execution inside SharedUserData.
Definition: exceptions.h:177
Self mapping index in PDBR.
Definition: intro_types.h:251
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
The _FAST_IO_DISPATCH structure used by 64-bit guests.
Definition: wddefs.h:315
The modified object is any IDT entry.
Definition: exceptions.h:170
char gExcLogLine[2 *ONE_KILOBYTE]
The exception log line.
Definition: exceptions.c:40
SSDT (Windows only)
Definition: intro_types.h:232
Hal dispatch table.
Definition: intro_types.h:249
KERNEL_DRIVER * IntDriverFindByBase(QWORD Gva)
Searches a driver object by its module base.
Definition: drivers.c:211
#define EXCEPTION_TABLE_ID(H)
Definition: exceptions.h:51
#define FIELD_OFFSET(type, field)
Definition: introdefs.h:239
Virtual SYSCALL (user-mode, Linux-only)
Definition: intro_types.h:254
static INTSTATUS IntExceptWinKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator, DWORD Options)
This function is used to get the information about the kernel-mode originator (windows guest)...
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
LIST_HEAD KernelExceptions[EXCEPTION_TABLE_SIZE]
Array of linked lists used for kernel-mode exceptions.
Definition: exceptions.h:108
INTSTATUS IntPeFindExportByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD Rva)
Check if a RVA lies inside an exported function.
Definition: winpe.c:1078
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
Definition: drivers.c:164
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:699
The modified object is WMI_LOGGER_CONTEXT.GetCpuClock used by InfinityHook (valid only on windows)...
Definition: exceptions.h:172
static void IntExceptKernelLogLinuxInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a kernel-mode violation (Linux guest).
The action was blocked because no exception signature matched.
Definition: intro_types.h:187
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
BYTE * KernelBuffer
A buffer containing the entire kernel image.
Definition: winguest.h:837
KERNEL_DRIVER * KernelDriver
Points to the driver object that describes the kernel image.
Definition: guests.h:381
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
int IntExceptPrintLixTaskInfo(const LIX_TASK_OBJECT *Task, char *Header, char *Line, int MaxLength, DWORD NameAlignment)
Print the information about the provided LIX_TASK_OBJECT.
LIX_TASK_OBJECT * IntLixTaskFindByGva(QWORD TaskStruct)
Finds Linux process with the provided "task_struct" guest virtual address.
Definition: lixprocess.c:1023
The modified object is a CR.
Definition: exceptions.h:712
#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
void IntDriverCacheCreateUnknown(const QWORD Rip)
Adds a new entry to the gDriverExportCache.
Definition: drivers.c:458
LIX_TASK_OBJECT * IntLixTaskGetCurrent(DWORD CpuNumber)
Finds the task that is currently running on the given CPU.
Definition: lixprocess.c:856
UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: winpe.h:79
Describes an entry in the gDriverExportCache.
Definition: drivers.h:14
QWORD Base
The base GVA of the section.
Definition: lixmodule.h:19
#define ZONE_LIB_IMPORTS
Used for the imports of a dll, driver, etc.
Definition: exceptions.h:686
The original RIP is outside a driver and it returns into a driver (which is the originator name)...
Definition: exceptions.h:602
static void IntExceptKernelLogWindowsInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a kernel-mode violation (windows guest).
Holds register state.
Definition: glueiface.h:30
QWORD EntryPoint
The entry point of this driver.
Definition: drivers.h:45
PWIN_DRIVER_OBJECT DriverObject
The driver object.
Definition: windriver.h:36
The exception is valid only on 32 bit systems/process.
Definition: exceptions.h:586
#define EXPORT_NAME_UNKNOWN
Definition: exceptions.h:34
The modified object is anything inside the driver object.
Definition: exceptions.h:164
INTSTATUS IntExceptKernel(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_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...
#define IDT_DESC_SIZE32
The size of a 32-bit interrupt descriptor.
Definition: wddefs.h:31
The modified object is only the driver&#39;s resources sections.
Definition: exceptions.h:162
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:698
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
static int IntExceptPrintDtrInfo(EXCEPTION_VICTIM_ZONE *Victim, char *Header, char *Line, int MaxLength)
Print the information about the modified IDTR/GDTR.
The name is the operating system HAL name (valid only for windows).
Definition: exceptions.h:629
#define IG_IA32_SYSENTER_CS
Definition: glueiface.h:138
LINUX_GUEST * gLixGuest
Global variable holding the state of a Linux guest.
Definition: lixguest.c:29
WORD Offset15_0
Definition: processor.h:144
The modified object is a MSR.
Definition: exceptions.h:166
#define INT_STATUS_EXCEPTION_ALLOW
Definition: introstatus.h:391
#define FALSE
Definition: intro_types.h:34
#define ALIGN_DOWN(x, a)
Definition: introdefs.h:165
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
Handling EPT violation.
Definition: guests.h:22