Bitdefender Hypervisor Memory Introspection
windrvobj.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "windrvobj.h"
6 #include "windrv_protected.h"
7 #include "alerts.h"
8 #include "crc32.h"
9 #include "decoder.h"
10 #include "hook.h"
11 #include "winpe.h"
12 
14 static LIST_HEAD gWinDriverObjects = LIST_HEAD_INIT(gWinDriverObjects);
15 
16 static INTSTATUS
18  _Inout_ WIN_DRIVER_OBJECT *DriverObject
19  );
20 
21 static INTSTATUS
23  _Inout_ WIN_DRIVER_OBJECT *DriverObject
24  );
25 
26 
27 BOOLEAN
29  _In_ QWORD DriverObjectAddress
30  )
50 {
51  INTSTATUS status;
52  PBYTE pObject, pModule;
53  BOOLEAN valid;
54  VA_TRANSLATION translation;
55 
56  valid = FALSE;
57 
58  pObject = NULL;
59  pModule = NULL;
60 
61  if (!IS_KERNEL_POINTER_WIN(gGuest.Guest64, DriverObjectAddress))
62  {
63  return FALSE;
64  }
65 
66  status = IntVirtMemMap(DriverObjectAddress,
67  WIN_KM_FIELD(DrvObj, Size),
69  0,
70  &pObject);
71  if (!INT_SUCCESS(status))
72  {
73  return FALSE;
74  }
75 
76  if (gGuest.Guest64)
77  {
78  DRIVER_OBJECT64 const *pDrvObj = (DRIVER_OBJECT64 *)pObject;
79  INTRO_PE_INFO peInfo = {0};
80 
81  if (pDrvObj->Type != DRIVER_OBJECT_TYPE)
82  {
83  goto cleanup_and_exit;
84  }
85 
86  if (pDrvObj->Size != WIN_KM_FIELD(DrvObj, Size))
87  {
88  goto cleanup_and_exit;
89  }
90 
91  if (pDrvObj->DriverStart % PAGE_SIZE != 0)
92  {
93  goto cleanup_and_exit;
94  }
95 
96  // Try to translate the driver start, in order to see if it leads to a valid address.
97  status = IntTranslateVirtualAddressEx(pDrvObj->DriverStart, gGuest.Mm.SystemCr3, TRFLG_NONE, &translation);
98  if (!INT_SUCCESS(status))
99  {
100  goto cleanup_and_exit;
101  }
102 
103  if (!(translation.Flags & PT_P))
104  {
105  goto cleanup_and_exit;
106  }
107 
108  if (translation.Flags & PT_US)
109  {
110  goto cleanup_and_exit;
111  }
112 
113  if (translation.Flags & PT_PCD)
114  {
115  // We shouldn't touch non-cacheable pages.
116  goto cleanup_and_exit;
117  }
118 
119  status = IntPhysMemMap(translation.PhysicalAddress, PAGE_SIZE, 0, &pModule);
120  if (!INT_SUCCESS(status))
121  {
122  goto cleanup_and_exit;
123  }
124 
125  status = IntPeValidateHeader(pDrvObj->DriverStart, pModule, PAGE_SIZE, &peInfo, 0);
126  if (!INT_SUCCESS(status))
127  {
128  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
129  goto cleanup_and_exit;
130  }
131 
132  if (peInfo.SizeOfImage != pDrvObj->DriverSize)
133  {
134  goto cleanup_and_exit;
135  }
136 
137  if (peInfo.EntryPoint != (pDrvObj->DriverInit - pDrvObj->DriverStart))
138  {
139  goto cleanup_and_exit;
140  }
141  }
142  else
143  {
144  DRIVER_OBJECT32 const *pDrvObj = (DRIVER_OBJECT32 *)pObject;
145  INTRO_PE_INFO peInfo = {0};
146 
147  if (pDrvObj->Type != DRIVER_OBJECT_TYPE)
148  {
149  goto cleanup_and_exit;
150  }
151 
152  if (pDrvObj->Size != WIN_KM_FIELD(DrvObj, Size))
153  {
154  goto cleanup_and_exit;
155  }
156 
157  if (pDrvObj->DriverStart % PAGE_SIZE != 0)
158  {
159  goto cleanup_and_exit;
160  }
161 
162  // Try to translate the driver start, in order to see if it leads to a valid address.
163  status = IntTranslateVirtualAddressEx(pDrvObj->DriverStart, gGuest.Mm.SystemCr3, TRFLG_NONE, &translation);
164  if (!INT_SUCCESS(status))
165  {
166  goto cleanup_and_exit;
167  }
168 
169  if (!(translation.Flags & PT_P))
170  {
171  goto cleanup_and_exit;
172  }
173 
174  if (translation.Flags & PT_US)
175  {
176  goto cleanup_and_exit;
177  }
178 
179  if (translation.Flags & PT_PCD)
180  {
181  // We shouldn't touch non-cacheable pages.
182  goto cleanup_and_exit;
183  }
184 
185  status = IntPhysMemMap(translation.PhysicalAddress, PAGE_SIZE, 0, &pModule);
186  if (!INT_SUCCESS(status))
187  {
188  goto cleanup_and_exit;
189  }
190 
191  status = IntPeValidateHeader(pDrvObj->DriverStart, pModule, PAGE_SIZE, &peInfo, 0);
192  if (!INT_SUCCESS(status))
193  {
194  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
195  goto cleanup_and_exit;
196  }
197 
198  if (peInfo.SizeOfImage != pDrvObj->DriverSize)
199  {
200  goto cleanup_and_exit;
201  }
202 
203  if (peInfo.EntryPoint != (pDrvObj->DriverInit - pDrvObj->DriverStart))
204  {
205  goto cleanup_and_exit;
206  }
207  }
208 
209  valid = TRUE;
210 
211 cleanup_and_exit:
212  if (NULL != pObject)
213  {
214  IntVirtMemUnmap(&pObject);
215  }
216 
217  if (NULL != pModule)
218  {
219  IntPhysMemUnmap(&pModule);
220  }
221 
222  return valid;
223 }
224 
225 
226 INTSTATUS
228  _In_ QWORD GuestAddress,
229  _In_ BOOLEAN StaticDetected,
230  _Out_opt_ PWIN_DRIVER_OBJECT *DriverObject
231  )
250 {
251  PWIN_DRIVER_OBJECT pDrvObj;
252  KERNEL_DRIVER *pKm;
253  INTSTATUS status;
254  DWORD driverNameLen;
255  QWORD driverNameAddress;
256 
257  driverNameAddress = 0;
258  driverNameLen = 0;
259 
260  pDrvObj = IntWinDrvObjFindByDrvObj(GuestAddress);
261  if (pDrvObj)
262  {
263  WARNING("[WARNING] Driver object at 0x%016llx is already present as \"%s\", will ignore\n",
264  GuestAddress, utf16_for_log(pDrvObj->Name));
265  if (NULL != DriverObject)
266  {
267  *DriverObject = pDrvObj;
268  }
270  }
271 
272  pDrvObj = HpAllocWithTag(sizeof(*pDrvObj), IC_TAG_DOBJ);
273  if (NULL == pDrvObj)
274  {
276  }
277 
278  // Start filling in driver object info.
279  pDrvObj->DriverObjectGva = GuestAddress;
280  pDrvObj->Aligned = !StaticDetected;
281 
282  status = IntTranslateVirtualAddress(GuestAddress, gGuest.Mm.SystemCr3, &pDrvObj->DriverObjectGpa);
283  if (!INT_SUCCESS(status))
284  {
285  ERROR("[ERROR] Failed translating GVA 0x%016llx: 0x%08x\n", GuestAddress, status);
286  pDrvObj->DriverObjectGpa = 0;
287  }
288 
289  // Read the driver name length
290  if (!gGuest.Guest64)
291  {
292  status = IntKernVirtMemFetchDword(GuestAddress + OFFSET_OF(DRIVER_OBJECT32,
293  DriverName.Length), &driverNameLen);
294  }
295  else
296  {
297  status = IntKernVirtMemFetchDword(GuestAddress + OFFSET_OF(DRIVER_OBJECT64,
298  DriverName.Length), &driverNameLen);
299  }
300  if (!INT_SUCCESS(status))
301  {
302  goto cleanup_and_exit;
303  }
304 
305  // Read the driver name address
306  if (!gGuest.Guest64)
307  {
308  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT32,
309  DriverName.Buffer), &driverNameAddress);
310  }
311  else
312  {
313  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT64,
314  DriverName.Buffer), &driverNameAddress);
315  }
316  if (!INT_SUCCESS(status))
317  {
318  goto cleanup_and_exit;
319  }
320 
321  driverNameLen = (driverNameLen & 0xFFFF);
322 
323  // Validate driver name length.
324  if ((driverNameLen < 2) || (driverNameLen >= 256))
325  {
326  // To small or to long, we ignore it.
327  goto cleanup_and_exit;
328  }
329 
330  // driverNameLen + 2 OK - we just checked above to see if its below 256.
331  pDrvObj->Name = HpAllocWithTag(driverNameLen + 2ull, IC_TAG_DRNU);
332  if (NULL == pDrvObj->Name)
333  {
335  goto cleanup_and_exit;
336  }
337 
338  // Read the driver name
339  status = IntKernVirtMemRead(driverNameAddress, driverNameLen, pDrvObj->Name, NULL);
340  if (!INT_SUCCESS(status))
341  {
342  ERROR("[ERROR] Failed reading the driver name: 0x%08x\n", status);
343  goto cleanup_and_exit;
344  }
345 
346  pDrvObj->NameLen = driverNameLen / 2;
347 
348  // Lowercase the name
349  strlower_utf16(pDrvObj->Name, pDrvObj->NameLen);
350 
351  // Helps us on exceptions
352  pDrvObj->NameHash = Crc32Wstring(pDrvObj->Name, INITIAL_CRC_VALUE);
353 
354  // Read the owner driver
355  if (!gGuest.Guest64)
356  {
357  pDrvObj->Owner = 0;
358  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT32, DriverStart), &pDrvObj->Owner);
359  }
360  else
361  {
362  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT64, DriverStart), &pDrvObj->Owner);
363  }
364  if (!INT_SUCCESS(status))
365  {
366  ERROR("[ERROR] Failed reading the driver start: 0x%08x\n", status);
367  goto cleanup_and_exit;
368  }
369 
370  // Now get the pointer to the fast I/O dispatch table, if any.
371  if (!gGuest.Guest64)
372  {
373  pDrvObj->FastIOTableAddress = 0;
374  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT32, FastIoDispatch),
375  &pDrvObj->FastIOTableAddress);
376  }
377  else
378  {
379  status = IntKernVirtMemFetchWordSize(GuestAddress + OFFSET_OF(DRIVER_OBJECT64, FastIoDispatch),
380  &pDrvObj->FastIOTableAddress);
381  }
382  if (!INT_SUCCESS(status))
383  {
384  ERROR("[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
385  }
386 
387  pKm = IntDriverFindByAddress(pDrvObj->Owner);
388  if (NULL != pKm)
389  {
390  pKm->Win.DriverObject = pDrvObj;
391  }
392 
393  InsertTailList(&gWinDriverObjects, &pDrvObj->Link);
394 
395  // Once the object is allocated and added to the list, we can activate protection on it.
396  if (IntWinDrvObjIsProtected(pDrvObj))
397  {
398  // Protect the driver object, together with the fast I/O dispatch table.
399  status = IntWinDrvObjProtect(pDrvObj);
400  if (!INT_SUCCESS(status))
401  {
402  ERROR("[ERROR] IntWinHookDriverObject failed: 0x%08x\n", status);
403  }
404  }
405 
406  status = INT_STATUS_SUCCESS;
407 
408 cleanup_and_exit:
409  if (!INT_SUCCESS(status))
410  {
411  IntWinDrvObjRemove(pDrvObj);
412  }
413 
414  if (NULL != DriverObject)
415  {
416  *DriverObject = pDrvObj;
417  }
418 
419  return status;
420 }
421 
422 
425  _In_ QWORD Gva
426  )
434 {
435  LIST_ENTRY *list = gWinDriverObjects.Flink;
436  while (list != &gWinDriverObjects)
437  {
439 
440  if (pDrvObj->DriverObjectGva == Gva)
441  {
442  return pDrvObj;
443  }
444 
445  list = list->Flink;
446  }
447 
448  return NULL;
449 }
450 
451 
454  _In_ QWORD Owner
455  )
463 {
464  LIST_ENTRY *list = gWinDriverObjects.Flink;
465  while (list != &gWinDriverObjects)
466  {
468 
469  if (pDrvObj->Owner == Owner)
470  {
471  return pDrvObj;
472  }
473 
474  list = list->Flink;
475  }
476 
477  return NULL;
478 }
479 
480 
481 static INTSTATUS
483  _In_ EXCEPTION_VICTIM_ZONE const *Victim,
484  _In_ EXCEPTION_KM_ORIGINATOR const *Originator,
485  _In_ INTRO_ACTION Action,
487  )
498 {
499  INTSTATUS status;
500  PEVENT_EPT_VIOLATION pEptViol;
501  IG_ARCH_REGS const *regs;
502 
503  regs = &gVcpu->Regs;
504 
505  pEptViol = &gAlert.Ept;
506  memzero(pEptViol, sizeof(*pEptViol));
507 
508  pEptViol->Header.Action = Action;
509  pEptViol->Header.Reason = Reason;
510  pEptViol->Header.MitreID = idRootkit;
511 
513 
515 
516  IntAlertEptFillFromKmOriginator(Originator, pEptViol);
517  IntAlertEptFillFromVictimZone(Victim, pEptViol);
518 
520 
521  IntAlertFillCodeBlocks(Originator->Original.Rip, regs->Cr3, FALSE, &pEptViol->CodeBlocks);
522  IntAlertFillExecContext(0, &pEptViol->ExecContext);
523 
524  IntAlertFillVersionInfo(&pEptViol->Header);
525 
526  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
527  if (!INT_SUCCESS(status))
528  {
529  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
530  }
531 
532  return status;
533 }
534 
535 
536 static INTSTATUS
538  _In_ EXCEPTION_VICTIM_ZONE const *Victim,
539  _In_ EXCEPTION_KM_ORIGINATOR const *Originator,
540  _In_ INTRO_ACTION Action,
542  )
553 {
554  INTSTATUS status;
556 
557  pIntViol = &gAlert.Integrity;
558  memzero(pIntViol, sizeof(*pIntViol));
559 
560  pIntViol->BaseAddress = Victim->Integrity.StartVirtualAddress;
561  pIntViol->VirtualAddress = Victim->Integrity.StartVirtualAddress + Victim->Integrity.Offset;
562  pIntViol->Victim.Type = Victim->Object.Type;
563  pIntViol->Size = Victim->Integrity.TotalLength;
564 
565  // we can't know from what CPU the write was, but we know where the integrity check failed
566  pIntViol->Header.CpuContext.Valid = FALSE;
567 
569  pIntViol->Header.Flags |= ALERT_FLAG_ASYNC;
570 
571  pIntViol->Header.Action = Action;
572  pIntViol->Header.Reason = Reason;
573  pIntViol->Header.MitreID = idRootkit;
574 
575  memcpy(pIntViol->Victim.Name, VICTIM_DRIVER_OBJECT, sizeof(VICTIM_DRIVER_OBJECT));
576 
577  IntAlertFillWriteInfo(Victim, &pIntViol->WriteInfo);
578 
579  IntAlertFillWinKmModule(Originator->Original.Driver, &pIntViol->Originator.Module);
580 
581  IntAlertFillDriverObject((PWIN_DRIVER_OBJECT)Victim->Object.DriverObject, &pIntViol->Victim.DriverObject);
582 
584 
586 
587  IntAlertFillVersionInfo(&pIntViol->Header);
588 
589  status = IntNotifyIntroEvent(introEventIntegrityViolation, pIntViol, sizeof(*pIntViol));
590  if (!INT_SUCCESS(status))
591  {
592  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
593  }
594 
595  return INT_STATUS_SUCCESS;
596 }
597 
598 
599 static INTSTATUS
601  _Inout_ WIN_DRIVER_OBJECT *Context,
602  _In_ HOOK_GPA const *Hook,
603  _In_ QWORD Address,
604  _Out_ INTRO_ACTION *Action
605  )
627 {
628  INTSTATUS status;
629  EXCEPTION_VICTIM_ZONE victim;
630  EXCEPTION_KM_ORIGINATOR originator;
631 
632  WIN_DRIVER_OBJECT *pDrvObj = Context;
633  HOOK_GVA const *pGva = Hook->Header.ParentHook;
634  QWORD gva = pGva->GvaPage + (Address & PAGE_OFFSET);
635  OPERAND_VALUE writtenValue = {0};
636 
637  BOOLEAN exitAfterInformation = FALSE;
638  BOOLEAN fastIoPtrWritten = FALSE;
639  BOOLEAN fastIoWrite = FALSE;
640  QWORD gpa;
641  KERNEL_DRIVER *pKm;
642 
644 
645  IG_ARCH_REGS *regs = &gVcpu->Regs;
646  INSTRUX *pInstrux = &gVcpu->Instruction;
647 
648  // Check to see if the Fast I/O dispatch pointer is being written. If it is, hook the new
649  // Fast I/O dispatch table.
650  if (gGuest.Guest64)
651  {
652  if ((gva >= pDrvObj->DriverObjectGva + OFFSET_OF(DRIVER_OBJECT64, FastIoDispatch)) &&
653  (gva < pDrvObj->DriverObjectGva + OFFSET_OF(DRIVER_OBJECT64, FastIoDispatch) + 8))
654  {
655  fastIoPtrWritten = TRUE;
656  }
657  }
658  else
659  {
660  if ((gva >= pDrvObj->DriverObjectGva + OFFSET_OF(DRIVER_OBJECT32, FastIoDispatch)) &&
661  (gva < pDrvObj->DriverObjectGva + OFFSET_OF(DRIVER_OBJECT32, FastIoDispatch) + 4))
662  {
663  fastIoPtrWritten = TRUE;
664  }
665  }
666 
667  if (fastIoPtrWritten)
668  {
669  status = IntDecGetWrittenValueFromInstruction(pInstrux, regs, NULL, &writtenValue);
670  if (!INT_SUCCESS(status))
671  {
672  ERROR("[ERROR] IntDecGetWrittenValueFromInstruction failed: 0x%08x\n", status);
673 
675 
676  goto cleanup_and_exit;
677  }
678 
679  if ((0 != writtenValue.Value.QwordValues[0]) &&
681  {
682  ERROR("[ERROR] [DRVOBJ] Fast I/O dispatch table of driver object '%s' not in kernel: 0x%016llx\n",
683  utf16_for_log(pDrvObj->Name), writtenValue.Value.QwordValues[0]);
684 
685  status = INT_STATUS_NOT_SUPPORTED;
686 
687  goto cleanup_and_exit;
688  }
689 
690  if (pDrvObj->FastIOTableAddress != 0)
691  {
692  goto _block_fastio_reloc;
693  }
694 
695  TRACE("[DRVOBJ] Fast I/O dispatch table of driver object '%s' has been written: 0x%016llx\n",
696  utf16_for_log(pDrvObj->Name), writtenValue.Value.QwordValues[0]);
697 
698  status = IntWinDrvObjUnprotectFastIoDispatch(pDrvObj);
699  if (!INT_SUCCESS(status))
700  {
701  ERROR("[ERROR] IntWinDrvObjUnprotectFastIoDispatch failed: 0x%08x\n", status);
702  }
703 
704  // Update new entry.
705  pDrvObj->FastIOTableAddress = writtenValue.Value.QwordValues[0];
706 
707  if (0 != pDrvObj->FastIOTableAddress)
708  {
709  status = IntWinDrvObjProtectFastIoDispatch(pDrvObj);
710  if (!INT_SUCCESS(status))
711  {
712  ERROR("[ERROR] IntWinDrvObjHookFastIODispatch failed: 0x%08x\n", status);
713  }
714  }
715 
716  *Action = introGuestAllowed;
717 
718  status = INT_STATUS_SUCCESS;
719 
720  goto cleanup_and_exit;
721  }
722 
723 _block_fastio_reloc:
725 
727  if (!INT_SUCCESS(status))
728  {
729  WARNING("[WARNING] IntTranslateVirtualAddress failed: 0x%08x\n", status);
730  }
731  else if (gpa != pDrvObj->DriverObjectGpa)
732  {
733  WARNING("[WARNING] The driver object Gpa 0x%016llx is different from actual Gpa 0x%016llx!\n",
734  pDrvObj->DriverObjectGpa, gpa);
735  pDrvObj->DriverObjectGpa = gpa;
736  }
737 
738  pKm = IntDriverFindByAddress(pDrvObj->Owner);
739  if (NULL != pKm && NULL == pKm->Win.DriverObject)
740  {
741  pKm->Win.DriverObject = pDrvObj;
742  }
743 
744  memzero(&victim, sizeof(victim));
745  memzero(&originator, sizeof(originator));
746 
747  // By default we do not allow this
748  *Action = introGuestNotAllowed;
749  reason = introReasonUnknown;
750  exitAfterInformation = FALSE;
751 
752  if (pDrvObj->FastIOTableAddress &&
753  gva >= pDrvObj->FastIOTableAddress &&
754  gva < pDrvObj->FastIOTableAddress + WIN_KM_FIELD(DrvObj, FiodispSize))
755  {
756  fastIoWrite = TRUE;
757  }
758 
759  status = IntExceptKernelGetOriginator(&originator, 0);
760  if (INT_STATUS_EXCEPTION_BLOCK == status)
761  {
762  reason = introReasonNoException;
763  exitAfterInformation = TRUE;
764  }
765  else if (!INT_SUCCESS(status))
766  {
767  reason = introReasonInternalError;
768  exitAfterInformation = TRUE;
769  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
770  }
771 
772  status = IntExceptGetVictimEpt(pDrvObj,
773  Address,
774  gva,
776  ZONE_WRITE,
777  &victim);
778  if (!INT_SUCCESS(status))
779  {
780  reason = introReasonInternalError;
781  ERROR("[ERROR] Failed getting zone details: 0x%08x\n", status);
782  exitAfterInformation = TRUE;
783  }
784 
785  if (exitAfterInformation)
786  {
787  IntExceptKernelLogInformation(&victim, &originator, *Action, reason);
788  }
789  else
790  {
791  IntExcept(&victim, &originator, exceptionTypeKm, Action, &reason, introEventEptViolation);
792  }
793 
795 
797  {
798  IntWinDrvObjSendEptAlert(&victim, &originator, *Action, reason);
799  }
800 
801 cleanup_and_exit:
803 
804  return status;
805 }
806 
807 
808 static INTSTATUS
810  _Inout_ INTEGRITY_REGION *IntegrityRegion
811  )
822 {
823 #define NAMEHASH_FLTMGR 0x4283398b
824  EXCEPTION_VICTIM_ZONE victim;
825  EXCEPTION_KM_ORIGINATOR originator;
826  INTSTATUS status;
827  BOOLEAN recalculate;
828  DWORD offset;
829 
830  if (IntegrityRegion->Type != introObjectTypeDriverObject &&
831  IntegrityRegion->Type != introObjectTypeFastIoDispatch)
832  {
833  ERROR("[ERROR] Invalid integrity region type: %d\n", IntegrityRegion->Type);
835  }
836 
838 
839  offset = 0;
840  recalculate = FALSE;
841  status = INT_STATUS_SUCCESS;
842 
843  while (offset < IntegrityRegion->Length)
844  {
847  const QWORD fioDispOffset = WIN_KM_FIELD(DrvObj, Fiodisp);
848 
849  memzero(&victim, sizeof(victim));
850  memzero(&originator, sizeof(originator));
851 
852  status = IntExceptGetVictimIntegrity(IntegrityRegion, &offset, &victim);
853  if (status == INT_STATUS_NOT_FOUND)
854  {
855  // We are done with the modifications, so exit
856  status = INT_STATUS_SUCCESS;
857  break;
858  }
859  else if (!INT_SUCCESS(status))
860  {
861  ERROR("[ERROR] Failed getting integrity zone: 0x%08x\n", status);
862  break;
863  }
864 
865  status = IntExceptGetOriginatorFromModification(&victim, &originator);
866  if (status == INT_STATUS_EXCEPTION_ALLOW)
867  {
868  // In case of something that can't be excepted (like the size field, etc.)
869  action = introGuestAllowed;
870  goto _do_action;
871  }
872  else if (status == INT_STATUS_EXCEPTION_BLOCK)
873  {
874  // Or something that it's wrong (like the size filed being too big, etc.)
875  status = INT_STATUS_SUCCESS;
876  reason = introReasonInternalError;
877 
878  IntExceptKernelLogInformation(&victim, &originator, action, reason);
879 
880  goto _do_action;
881  }
882  else if (!INT_SUCCESS(status))
883  {
884  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
885  break;
886  }
887 
888  if (((gGuest.Guest64 &&
889  victim.Integrity.Offset + fioDispOffset == OFFSET_OF(DRIVER_OBJECT64, DriverUnload)) ||
890  (!gGuest.Guest64 &&
891  victim.Integrity.Offset +fioDispOffset == OFFSET_OF(DRIVER_OBJECT32, DriverUnload))) &&
892  (originator.Original.NameHash == NAMEHASH_FLTMGR))
893  {
894  action = introGuestAllowed;
895  goto _do_action;
896  }
897 
898  IntExcept(&victim, &originator, exceptionTypeKm, &action, &reason, introEventIntegrityViolation);
899 
900  if (IntPolicyCoreTakeAction(INTRO_OPT_PROT_KM_DRVOBJ, &action, &reason))
901  {
902  IntWinDrvObjSendIntegrityAlert(&victim, &originator, action, reason);
903  }
904 
906  {
907  reason = introReasonAllowed;
908  }
909 
910 _do_action:
911  if (action == introGuestAllowed)
912  {
913  recalculate = TRUE;
914  }
915  else if (action == introGuestNotAllowed)
916  {
917  QWORD original = 0;
918 
919  if (gGuest.Guest64)
920  {
921  original = *(QWORD *)((PBYTE)IntegrityRegion->OriginalContent + victim.Integrity.Offset);
922  }
923  else
924  {
925  original = *(DWORD *)((PBYTE)IntegrityRegion->OriginalContent + victim.Integrity.Offset);
926  }
927 
928  IntPauseVcpus();
929 
930  // No need to use IntVirtMemSafeWrite, as this is a protected region.
931  status = IntKernVirtMemWrite(IntegrityRegion->Gva + victim.Integrity.Offset, gGuest.WordSize, &original);
932 
933  IntResumeVcpus();
934 
935  if (!INT_SUCCESS(status))
936  {
937  ERROR("[ERROR] IntKernVirtMemWrite failed for gva 0x%016llx: 0x%08x\n",
938  IntegrityRegion->Gva + victim.Integrity.Offset, status);
939  goto _cleanup_and_exit;
940  }
941  }
942  }
943 
944  if (recalculate)
945  {
946  IntIntegrityRecalculate(IntegrityRegion);
947  }
948 
949 _cleanup_and_exit:
951 
952  return status;
953 
954 #undef NAMEHASH_FLTMGR
955 }
956 
957 
958 static INTSTATUS
960  _Inout_ WIN_DRIVER_OBJECT *DriverObject
961  )
970 {
971  INTSTATUS status;
972 
973  if (!DriverObject->FiodispProtected)
974  {
976  }
977 
978  TRACE("[DRVOBJ] Removing protection on Fast I/OP dispatch on driver object '%s' at %llx...\n",
979  utf16_for_log(DriverObject->Name), DriverObject->FastIOTableAddress);
980 
981  if (DriverObject->FiodispIntegrityObject != NULL)
982  {
983  status = IntIntegrityRemoveRegion(DriverObject->FiodispIntegrityObject);
984  if (!INT_SUCCESS(status))
985  {
986  ERROR("[ERROR] Failed removing the integrity region from structure at address 0x%016llx: 0x%08x\n",
987  DriverObject->FastIOTableAddress, status);
988  }
989  DriverObject->FiodispIntegrityObject = NULL;
990  }
991 
992  DriverObject->FiodispProtected = FALSE;
993 
994  return INT_STATUS_SUCCESS;
995 }
996 
997 
998 static INTSTATUS
1000  _Inout_ WIN_DRIVER_OBJECT *DriverObject
1001  )
1014 {
1015  INTSTATUS status;
1016 
1017  if (0 == DriverObject->FastIOTableAddress)
1018  {
1020  }
1021 
1022  TRACE("[DRVOBJ] Adding protection on Fast I/O dispatch for driver object '%s' at 0x%016llx (integrity)\n",
1023  utf16_for_log(DriverObject->Name), DriverObject->FastIOTableAddress);
1024 
1025  status = IntIntegrityAddRegion(DriverObject->FastIOTableAddress,
1026  WIN_KM_FIELD(DrvObj, FiodispSize),
1028  DriverObject,
1030  TRUE,
1031  &DriverObject->FiodispIntegrityObject);
1032  if (!INT_SUCCESS(status))
1033  {
1034  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
1035  return status;
1036  }
1037 
1038  DriverObject->FiodispProtected = TRUE;
1039 
1040  return INT_STATUS_SUCCESS;
1041 }
1042 
1043 
1044 INTSTATUS
1046  _Inout_ WIN_DRIVER_OBJECT *DriverObject
1047  )
1059 {
1060  INTSTATUS status;
1061 
1062  if (NULL == DriverObject)
1063  {
1065  }
1066 
1067  if (!DriverObject->DrvobjProtected)
1068  {
1070  }
1071 
1072  TRACE("[DRVOBJ] Removing protection on driver object '%s' at %llx...\n",
1073  utf16_for_log(DriverObject->Name), DriverObject->DriverObjectGva);
1074 
1075  status = IntWinDrvObjUnprotectFastIoDispatch(DriverObject);
1076  if (!INT_SUCCESS(status))
1077  {
1078  ERROR("[ERROR] IntWinDrvObjFiodispUnHook failed: 0x%08x\n", status);
1079  }
1080 
1081  if (DriverObject->DrvobjIntegrityObject != NULL)
1082  {
1083  status = IntIntegrityRemoveRegion(DriverObject->DrvobjIntegrityObject);
1084  if (!INT_SUCCESS(status))
1085  {
1086  ERROR("[ERROR] Failed removing the integrity region from structure at address 0x%016llx: 0x%08x\n",
1087  DriverObject->DriverObjectGva, status);
1088  }
1089  DriverObject->DrvobjIntegrityObject = NULL;
1090  }
1091 
1092  if (DriverObject->DrvobjHookObject != NULL)
1093  {
1094  status = IntHookObjectDestroy((HOOK_OBJECT_DESCRIPTOR **)&DriverObject->DrvobjHookObject, 0);
1095  if (!INT_SUCCESS(status))
1096  {
1097  ERROR("[ERROR] Failed removing the hook from structure at address 0x%016llx: 0x%08x\n",
1098  DriverObject->FastIOTableAddress, status);
1099  }
1100  }
1101 
1102  DriverObject->DrvobjProtected = FALSE;
1103 
1104  return INT_STATUS_SUCCESS;
1105 }
1106 
1107 
1108 INTSTATUS
1110  _Inout_ WIN_DRIVER_OBJECT *DriverObject
1111  )
1123 {
1124  INTSTATUS status;
1125 
1126  if (DriverObject == NULL)
1127  {
1129  }
1130 
1131  status = IntWinDrvObjProtectFastIoDispatch(DriverObject);
1132  if (!INT_SUCCESS(status))
1133  {
1134  ERROR("[ERROR] IntWinHookFastIODispatch failed: 0x%08x\n", status);
1135  }
1136 
1137  // If the protection is already activated, then we can hook the driver object since the pool size is a whole page
1138  if (!DriverObject->Aligned)
1139  {
1140  TRACE("[DRVOBJ] Adding protection on driver object '%s' at %llx (integrity)...\n",
1141  utf16_for_log(DriverObject->Name), DriverObject->DriverObjectGva);
1142 
1143  status = IntIntegrityAddRegion(DriverObject->DriverObjectGva + WIN_KM_FIELD(DrvObj, Fiodisp),
1144  WIN_KM_FIELD(DrvObj, Size) - WIN_KM_FIELD(DrvObj, Fiodisp),
1146  DriverObject,
1148  TRUE,
1149  &DriverObject->DrvobjIntegrityObject);
1150  if (!INT_SUCCESS(status))
1151  {
1152  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
1153  return status;
1154  }
1155  }
1156  else
1157  {
1158  TRACE("[DRVOBJ] Adding protection on driver object '%s' at %llx (ept)...\n",
1159  utf16_for_log(DriverObject->Name), DriverObject->DriverObjectGva);
1160 
1161  status = IntHookObjectCreate(introObjectTypeDriverObject, 0, &DriverObject->DrvobjHookObject);
1162  if (!INT_SUCCESS(status))
1163  {
1164  ERROR("[ERROR] IntHookObjectCreate failed: 0x%08x\n", status);
1165  return status;
1166  }
1167 
1168  status = IntHookObjectHookRegion(DriverObject->DrvobjHookObject,
1169  0,
1170  DriverObject->DriverObjectGva + WIN_KM_FIELD(DrvObj, Fiodisp),
1171  WIN_KM_FIELD(DrvObj, Size) - WIN_KM_FIELD(DrvObj, Fiodisp),
1174  DriverObject,
1175  0,
1176  NULL);
1177  if (!INT_SUCCESS(status))
1178  {
1179  ERROR("[ERROR] IntHookObjectHookRegion failed: 0x%08x\n", status);
1180  return status;
1181  }
1182  }
1183 
1184  DriverObject->DrvobjProtected = TRUE;
1185 
1186  return INT_STATUS_SUCCESS;
1187 }
1188 
1189 
1190 INTSTATUS
1192  _In_ QWORD DriverObjectAddress
1193  )
1202 {
1203  INTSTATUS status;
1204  LIST_ENTRY *list;
1205  BOOLEAN bFound;
1206  QWORD drvObjGpa;
1207 
1208  bFound = FALSE;
1209 
1210  status = IntTranslateVirtualAddress(DriverObjectAddress, gGuest.Mm.SystemCr3, &drvObjGpa);
1211  if (!INT_SUCCESS(status))
1212  {
1213  ERROR("[ERROR] IntTranslateVirtualAddress failed for GVA 0x%016llx: 0x%08x\n", DriverObjectAddress, status);
1214  drvObjGpa = 0;
1215  }
1216 
1217  list = gWinDriverObjects.Flink;
1218  while (list != &gWinDriverObjects)
1219  {
1221  list = list->Flink;
1222 
1223  // Search the driver corresponding to this pool
1224  if ((drvObjGpa != 0 && drvObjGpa + WIN_KM_FIELD(DrvObj, AllocationGap) == drvObj->DriverObjectGpa) ||
1225  (DriverObjectAddress + WIN_KM_FIELD(DrvObj, AllocationGap) == drvObj->DriverObjectGva))
1226 
1227  {
1228  TRACE("[DRVOBJ] Removing driver object at 0x%016llx\n", drvObj->DriverObjectGva);
1229 
1230  RemoveEntryList(&drvObj->Link);
1231 
1232  status = IntWinDrvObjRemove(drvObj);
1233  if (!INT_SUCCESS(status))
1234  {
1235  ERROR("[ERROR] IntWinDrvObjRemoveDriverObject failed: 0x%08x\n", status);
1236  }
1237 
1238  bFound = TRUE;
1239 
1240  // There can be more GVAs pointing to this gpa, so don't break!
1241  }
1242  else if (DriverObjectAddress == drvObj->FastIOTableAddress)
1243  {
1244  TRACE("[DRVOBJ] Removing Fast I/O dispatch at 0x%016llx\n", drvObj->FastIOTableAddress);
1245 
1246  status = IntWinDrvObjUnprotectFastIoDispatch(drvObj);
1247  if (!INT_SUCCESS(status))
1248  {
1249  ERROR("[ERROR] IntWinDrvObjUnprotectFastIoDispatch failed: 0x%08x\n", status);
1250  }
1251 
1252  bFound = TRUE;
1253 
1254  // If we have multiple driver objects, remove all the hooks!
1255  }
1256  }
1257 
1258  if (!bFound)
1259  {
1260  return INT_STATUS_NOT_FOUND;
1261  }
1262 
1263  return INT_STATUS_SUCCESS;
1264 }
1265 
1266 
1267 static void
1269  _Inout_ WIN_DRIVER_OBJECT *DriverObject
1270  )
1278 {
1279  if (NULL != DriverObject->Name)
1280  {
1281  HpFreeAndNullWithTag(&DriverObject->Name, IC_TAG_DRNU);
1282  }
1283 
1284  HpFreeAndNullWithTag(&DriverObject, IC_TAG_DOBJ);
1285 }
1286 
1287 
1288 INTSTATUS
1290  _Inout_ WIN_DRIVER_OBJECT *DriverObject
1291  )
1302 {
1303  KERNEL_DRIVER *pKmDriver;
1304  INTSTATUS status;
1305 
1306  if (NULL == DriverObject)
1307  {
1309  }
1310 
1311  pKmDriver = IntDriverFindByAddress(DriverObject->Owner);
1312  if (NULL != pKmDriver)
1313  {
1314  pKmDriver->Win.DriverObject = NULL;
1315  }
1316 
1317  status = IntWinDrvObjUnprotect(DriverObject);
1318  if (!INT_SUCCESS(status))
1319  {
1320  ERROR("[ERROR] IntWinDrvObjUnprotect failed: 0x%08x\n", status);
1321  }
1322 
1323  IntWinDrvObjFreeDriverObject(DriverObject);
1324 
1325  return status;
1326 }
1327 
1328 
1329 INTSTATUS
1331  void
1332  )
1338 {
1339  INTSTATUS status;
1340 
1341  TRACE("[DRVOBJ] Updating driver objects protections...\n");
1342 
1343  for (LIST_ENTRY *list = gWinDriverObjects.Flink; list != &gWinDriverObjects; list = list->Flink)
1344  {
1346  const PROTECTED_MODULE_INFO *pProtInfo;
1347 
1348  pProtInfo = IntWinDrvObjIsProtected(pDrvObj);
1349  if (!pDrvObj->DrvobjProtected && (NULL != pProtInfo))
1350  {
1351  status = IntWinDrvObjProtect(pDrvObj);
1352  if (!INT_SUCCESS(status))
1353  {
1354  ERROR("[ERROR] IntWinDrvObjProtect failed for '%s': 0x%08x\n",
1355  utf16_for_log(pDrvObj->Name), status);
1356  }
1357  }
1358  else if (pDrvObj->DrvobjProtected && (NULL == pProtInfo))
1359  {
1360  status = IntWinDrvObjUnprotect(pDrvObj);
1361  if (!INT_SUCCESS(status))
1362  {
1363  ERROR("[ERROR] IntWinDrvObjUnprotect failed for '%s': 0x%08x\n",
1364  utf16_for_log(pDrvObj->Name), status);
1365  }
1366  }
1367  }
1368 
1369  return INT_STATUS_SUCCESS;
1370 }
1371 
1372 
1373 INTSTATUS
1375  void
1376  )
1384 {
1385  INTSTATUS status;
1386 
1387  LIST_ENTRY *list = gWinDriverObjects.Flink;
1388  while (list != &gWinDriverObjects)
1389  {
1391 
1392  list = list->Flink;
1393 
1394  RemoveEntryList(&pDrvObj->Link);
1395 
1396  status = IntWinDrvObjRemove(pDrvObj);
1397  if (!INT_SUCCESS(status))
1398  {
1399  ERROR("[ERROR] IntWinDrvObjRemoveDriverObject failed: 0x%08x\n", status);
1400  }
1401  }
1402 
1403  return INT_STATUS_SUCCESS;
1404 }
Measures kernel mode exceptions checks.
Definition: stats.h:51
#define IC_TAG_DOBJ
Driver Object List Entry.
Definition: memtags.h:13
LIST_ENTRY Link
Entry inside the gWinDriverObjects list.
Definition: windrvobj.h:16
QWORD DriverObjectGva
The guest virtual address of the guest _DRIVER_OBJECT represented by this structure.
Definition: windrvobj.h:18
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
Definition: introcore.h:107
struct _EXCEPTION_KM_ORIGINATOR::@63 Original
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
INTRO_CODEBLOCKS CodeBlocks
Code blocks extracted for the alert.
Definition: intro_types.h:1145
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
PWIN_DRIVER_OBJECT IntWinDrvObjFindByOwnerAddress(QWORD Owner)
Finds a driver object in the gWinDriverObjects list by the base of the kernel module that owns it...
Definition: windrvobj.c:453
#define INTRO_OPT_PROT_KM_DRVOBJ
Enable driver object & fast I/O dispatch protection.
Definition: intro_types.h:409
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
QWORD IntAlertCoreGetFlags(QWORD ProtectionFlag, INTRO_ACTION_REASON Reason)
Returns the flags for an alert.
Definition: alerts.c:366
const PROTECTED_MODULE_INFO * IntWinDrvObjIsProtected(const WIN_DRIVER_OBJECT *DriverObject)
Get the protected module information for a kernel driver object.
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
BOOLEAN IntPolicyCoreForceBetaIfNeeded(QWORD Flag, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the log-only mode is active.
Definition: introcore.c:2803
The _DRIVER_OBJECT structure used by 64-bit guests.
Definition: wddefs.h:255
#define OFFSET_OF(Type, Member)
Definition: introlists.h:33
INTSTATUS IntKernVirtMemWrite(QWORD KernelGva, DWORD Length, void *Buffer)
Writes data to a guest kernel virtual memory range.
Definition: introcore.c:699
INTSTATUS IntHookObjectDestroy(HOOK_OBJECT_DESCRIPTOR **Object, DWORD Flags)
Destroy an entire hook object. All regions belonging to this object will be removed.
Definition: hook_object.c:357
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1088
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:207
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
BOOLEAN IntPolicyCoreTakeAction(QWORD Flag, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a core introspection option.
Definition: introcore.c:2693
Fast IO Dispatch (Windows only)
Definition: intro_types.h:233
WIN_KERNEL_DRIVER Win
Valid only for Windows guests.
Definition: drivers.h:70
static INTSTATUS IntWinDrvObjHandleWrite(WIN_DRIVER_OBJECT *Context, HOOK_GPA const *Hook, QWORD Address, INTRO_ACTION *Action)
Handles writes done over a protected driver object.
Definition: windrvobj.c:600
#define STATS_EXIT(id)
Definition: stats.h:148
Event structure for integrity violations on monitored structures.
Definition: intro_types.h:1450
INTSTATUS IntIntegrityAddRegion(QWORD VirtualAddress, DWORD Length, INTRO_OBJECT_TYPE Type, void *Context, PFUNC_IntegrityViolationCallback Callback, BOOLEAN CopyContent, void **Descriptor)
Creates an INTEGRITY_REGION object and adds it to the gIntegrityRegions list.
Definition: integrity.c:91
struct _LIST_ENTRY * Flink
Definition: introlists.h:20
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
#define DRIVER_OBJECT_TYPE
The type of a _DRIVER_OBJECT structure.
Definition: wddefs.h:37
#define PT_PCD
Definition: pgtable.h:87
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
INTRO_OBJECT_TYPE Type
Definition: intro_types.h:1462
Exposes the types, constants and functions used to describe protected Windows Kernel modules and driv...
#define PAGE_OFFSET
Definition: pgtable.h:32
The action was not allowed because there was no reason to allow it.
Definition: intro_types.h:183
#define PT_US
Definition: pgtable.h:85
QWORD DriverInit
Definition: wddefs.h:269
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
INTSTATUS IntWinDrvObjProtect(WIN_DRIVER_OBJECT *DriverObject)
Protects a driver object and its fast IO dispatch table, if one exists.
Definition: windrvobj.c:1109
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:637
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
INTSTATUS IntKernVirtMemFetchWordSize(QWORD GuestVirtualAddress, void *Data)
Reads a guest pointer from the guest kernel memory.
Definition: introcore.c:847
INTSTATUS IntWinDrvObjUnprotect(WIN_DRIVER_OBJECT *DriverObject)
Deactivates protection for a driver object and its fast IO dispatch structure.
Definition: windrvobj.c:1045
int INTSTATUS
The status data type.
Definition: introstatus.h:24
QWORD GvaPage
Guest virtual page base address, aligned to 4K.
Definition: hook_gva.h:32
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
DWORD Offset
The offset of the modification.
Definition: exceptions.h:766
#define TRFLG_NONE
No special options.
Definition: introcore.h:82
Rootkit.
Definition: intro_types.h:1033
Describes a kernel-mode originator.
Definition: exceptions.h:897
INTSTATUS IntWinDrvObjUninit(void)
Removes all the driver objects in the gWinDriverObjects.
Definition: windrvobj.c:1374
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
Definition: guests.h:88
EVENT_EPT_VIOLATION Ept
Definition: alerts.h:16
DWORD DriverSize
Definition: wddefs.h:240
Describes a kernel driver.
Definition: drivers.h:30
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
BOOLEAN IntWinDrvObjIsValidDriverObject(QWORD DriverObjectAddress)
Checks if a guest memory area contains a valid _DRIVER_OBJECT structure.
Definition: windrvobj.c:28
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1106
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1084
The _DRIVER_OBJECT structure used by 32-bit guests.
Definition: wddefs.h:233
INTSTATUS IntAlertFillCodeBlocks(QWORD Rip, QWORD Cr3, BOOLEAN Execute, INTRO_CODEBLOCKS *CodeBlocks)
Fills the code blocks pattern for an alert.
Definition: alerts.c:71
void IntAlertEptFillFromKmOriginator(const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills kernel mode originator information inside an EPT alert.
Definition: alerts.c:832
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define _Inout_
Definition: intro_sal.h:20
INTSTATUS IntIntegrityRecalculate(INTEGRITY_REGION *IntegrityRegion)
Recalculates the hash and reads the original content again for a given region.
Definition: integrity.c:242
static INTSTATUS IntWinDrvObjSendEptAlert(EXCEPTION_VICTIM_ZONE const *Victim, EXCEPTION_KM_ORIGINATOR const *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an introEventEptViolation alert for a protected driver object.
Definition: windrvobj.c:482
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
Definition: introcore.c:829
static LIST_HEAD gWinDriverObjects
List of all the loaded Windows driver objects.
Definition: windrvobj.c:14
void IntAlertFillWriteInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_WRITE_INFO *WriteInfo)
Fills the write information for an alert.
Definition: alerts.c:521
#define _Out_opt_
Definition: intro_sal.h:30
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
#define INT_STATUS_EXCEPTION_BLOCK
Definition: introstatus.h:421
DWORD Size
The size of the modified memory area.
Definition: intro_types.h:1483
Describes an operand value.
Definition: decoder.h:50
static void IntWinDrvObjFreeDriverObject(WIN_DRIVER_OBJECT *DriverObject)
Frees a driver object.
Definition: windrvobj.c:1268
void IntAlertEptFillFromVictimZone(const EXCEPTION_VICTIM_ZONE *Victim, EVENT_EPT_VIOLATION *EptViolation)
Fills the victim information inside an EPT alert.
Definition: alerts.c:868
QWORD FastIOTableAddress
The guest virtual address of the _FAST_IO_DISPATCH structure used by this driver object. May be 0.
Definition: windrvobj.h:27
QWORD QwordValues[ND_MAX_REGISTER_SIZE/8]
Definition: decoder.h:57
#define STATS_ENTER(id)
Definition: stats.h:141
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1085
uint8_t * PBYTE
Definition: intro_types.h:47
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
INTSTATUS IntWinDrvObjUpdateProtection(void)
Updates the protection for all the driver objects in the gWinDriverObjects list.
Definition: windrvobj.c:1330
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
Holds information about a driver object.
Definition: windrvobj.h:13
#define memzero(a, s)
Definition: introcrt.h:35
#define PT_P
Definition: pgtable.h:83
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:286
INTSTATUS IntExceptGetVictimEpt(void *Context, QWORD Gpa, QWORD Gva, INTRO_OBJECT_TYPE Type, DWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
Fills an EXCEPTION_VICTIM_ZONE with relevant information from an EPT violation.
Definition: exceptions.c:742
unsigned long long QWORD
Definition: intro_types.h:53
DWORD NameHash
Hash of the Name.
Definition: windrvobj.h:34
QWORD DriverSize
Definition: wddefs.h:263
QWORD Owner
Guest virtual address of the kernel module that owns this driver object.
Definition: windrvobj.h:38
void * ParentHook
The parent hook. For a GPA hook, for example, a GVA hook or a PagedHook will be the parent hook...
Definition: hook.h:73
#define NAMEHASH_FLTMGR
INTRO_MODULE Module
The module that modified the translation.
Definition: intro_types.h:1456
INTSTATUS IntWinDrvObjRemove(WIN_DRIVER_OBJECT *DriverObject)
Removes a driver object and updates its owner module.
Definition: windrvobj.c:1289
struct _EVENT_INTEGRITY_VIOLATION::@295 Victim
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1999
HOOK_HEADER Header
The hook header.
Definition: hook_gva.h:20
int strlower_utf16(WCHAR *buf, size_t len)
Definition: introcrt.c:28
QWORD VirtualAddress
The guest virtual address which was modified.
Definition: intro_types.h:1481
#define TRUE
Definition: intro_types.h:30
static INTSTATUS IntWinDrvObjHandleModification(INTEGRITY_REGION *IntegrityRegion)
Handles writes done over a protected driver object.
Definition: windrvobj.c:809
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1452
union _OPERAND_VALUE::@22 Value
The actual operand value.
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
DWORD DriverStart
Definition: wddefs.h:239
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...
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
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.
Kernel-mode exception.
Definition: exceptions.h:62
INTSTATUS IntWinDrvObjRemoveFromAddress(QWORD DriverObjectAddress)
Frees and removes protection for a driver object by its address.
Definition: windrvobj.c:1191
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
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:135
INTSTATUS IntTranslateVirtualAddressEx(QWORD Gva, QWORD Cr3, DWORD Flags, VA_TRANSLATION *Translation)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1863
INTRO_EXEC_CONTEXT ExecContext
Information about the instruction that triggered the alert.
Definition: intro_types.h:1191
#define WARNING(fmt,...)
Definition: glue.h:60
static INTSTATUS IntWinDrvObjProtectFastIoDispatch(WIN_DRIVER_OBJECT *DriverObject)
Deactivates the protection for the fast IO dispatch structure of a driver object. ...
Definition: windrvobj.c:999
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
#define PAGE_SIZE
Definition: common.h:53
DWORD Crc32Wstring(const WCHAR *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated wide char string.
Definition: crc32.c:226
Describes the modified zone.
Definition: exceptions.h:847
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:726
WCHAR Name[ALERT_PATH_MAX_LEN]
NULL-terminated string with a human readable description of the modified object.
Definition: intro_types.h:1464
void IntAlertFillDriverObject(const WIN_DRIVER_OBJECT *DriverObject, INTRO_DRVOBJ *EventDrvObj)
Saves driver object information inside an alert. Available only for Windows guests.
Definition: alerts.c:592
uint32_t DWORD
Definition: intro_types.h:49
DWORD EntryPoint
Entry point (RVA).
Definition: winpe.h:601
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:879
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
Definition: winpe.c:131
static INTSTATUS IntWinDrvObjUnprotectFastIoDispatch(WIN_DRIVER_OBJECT *DriverObject)
Deactivates the protection for the fast IO dispatch structure of a driver object. ...
Definition: windrvobj.c:959
enum _INTRO_ACTION INTRO_ACTION
Event actions.
INTSTATUS IntIntegrityRemoveRegion(void *Descriptor)
Removes an integrity region from the gIntegrityRegions list.
Definition: integrity.c:313
PWCHAR Name
NULL-terminated wide-char string containing the name of the driver, as taken from the guest driver ob...
Definition: windrvobj.h:30
INTRO_WRITE_INFO WriteInfo
The original and the new value.
Definition: intro_types.h:1477
#define IntDbgEnterDebugger()
Definition: introcore.h:381
__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
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:884
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:370
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
BOOLEAN Aligned
True if the driver object allocation is page aligned.
Definition: windrvobj.h:66
Encapsulates a protected Windows kernel module.
Definition: winguest.h:124
PWIN_DRIVER_OBJECT IntWinDrvObjFindByDrvObj(QWORD Gva)
Finds a driver object in the gWinDriverObjects list by its guest virtual address. ...
Definition: windrvobj.c:424
EVENT_INTEGRITY_VIOLATION Integrity
Definition: alerts.h:23
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1083
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
Definition: drivers.c:164
QWORD BaseAddress
The guest virtual address at which the monitored integrity region starts.
Definition: intro_types.h:1479
struct _EVENT_INTEGRITY_VIOLATION::@294 Originator
#define LIST_HEAD_INIT(Name)
Definition: introlists.h:39
INTSTATUS IntHookObjectHookRegion(void *Object, QWORD Cr3, QWORD Gla, SIZE_T Length, BYTE Type, void *Callback, void *Context, DWORD Flags, HOOK_REGION_DESCRIPTOR **Region)
Hook a contiguous region of virtual memory inside the provided virtual address space.
Definition: hook_object.c:132
#define VICTIM_DRIVER_OBJECT
Printable name used for introObjectTypeDriverObject objects.
Definition: intro_types.h:677
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
Definition: glue.c:338
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...
DWORD DriverInit
Definition: wddefs.h:246
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
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
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1086
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
INTSTATUS IntDecGetWrittenValueFromInstruction(PINSTRUX Instrux, PIG_ARCH_REGS Registers, PBYTE MemoryValue, OPERAND_VALUE *WrittenValue)
Decode a written value from a memory write instruction.
Definition: decoder.c:1861
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
Sent for integrity violation alerts. See EVENT_INTEGRITY_VIOLATION.
Definition: intro_types.h:92
EXCEPTION_VICTIM_INTEGRITY Integrity
Valid if the modified zone is Integrity.
Definition: exceptions.h:862
Holds register state.
Definition: glueiface.h:30
DWORD SizeOfImage
Size of the image.
Definition: winpe.h:599
Event structure for EPT violations.
Definition: intro_types.h:1104
#define IC_TAG_DRNU
Guest loaded module name buffer (Unicode)
Definition: memtags.h:11
BOOLEAN DrvobjProtected
True if the driver object structure is protected.
Definition: windrvobj.h:55
PWIN_DRIVER_OBJECT DriverObject
The driver object.
Definition: windriver.h:36
void IntAlertFillWinKmModule(const KERNEL_DRIVER *Driver, INTRO_MODULE *EventModule)
Saves kernel module information inside an alert.
Definition: alerts.c:617
static INTSTATUS IntWinDrvObjSendIntegrityAlert(EXCEPTION_VICTIM_ZONE const *Victim, EXCEPTION_KM_ORIGINATOR const *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an introEventIntegrityViolation alert for a protected driver object.
Definition: windrvobj.c:537
Write-access hook.
Definition: glueiface.h:299
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
Definition: glue.c:396
INTSTATUS IntExceptKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator, DWORD Options)
This function is used to get the information about the kernel-mode originator.
INTSTATUS IntAlertFillExecContext(QWORD Cr3, INTRO_EXEC_CONTEXT *ExecContext)
Fills the current execution context.
Definition: alerts.c:31
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:698
INTSTATUS IntHookObjectCreate(DWORD ObjectType, QWORD Cr3, void **Object)
Create a new hook object.
Definition: hook_object.c:81
void IntExcept(EXCEPTION_VICTIM_ZONE *Victim, void *Originator, EXCEPTION_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason, INTRO_EVENT_TYPE EventClass)
This function is the entry point for the exception mechanism.
Definition: exceptions.c:3317
QWORD DriverStart
Definition: wddefs.h:262
INTSTATUS IntWinDrvObjCreateFromAddress(QWORD GuestAddress, BOOLEAN StaticDetected, PWIN_DRIVER_OBJECT *DriverObject)
Creates a new driver object.
Definition: windrvobj.c:227
#define INT_STATUS_EXCEPTION_ALLOW
Definition: introstatus.h:391
INTRO_DRVOBJ DriverObject
The modified driver object. Valid only if Type is introObjectTypeDriverObject.
Definition: intro_types.h:1470
DWORD NameHash
The namehash of the originator return driver.
Definition: exceptions.h:901
#define FALSE
Definition: intro_types.h:34
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
DWORD NameLen
The length, in characters, of Name, not including the NULL-terminator.
Definition: windrvobj.h:32