Bitdefender Hypervisor Memory Introspection
winintobj.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winintobj.h"
6 #include "integrity.h"
7 #include "exceptions.h"
8 #include "alerts.h"
9 #include "kernvm.h"
10 
30 
31 
35 #define INTERRUPT_OBJECT_COUNT 0x20
36 
40 #define DISPATCH_OFFSET (gGuest.Guest64 ? FIELD_OFFSET(KINTERRUPT_COMMON64, DispatchAddress) : \
41  FIELD_OFFSET(KINTERRUPT_COMMON32, DispatchAddress))
42 #define SERVICE_OFFSET (gGuest.Guest64 ? FIELD_OFFSET(KINTERRUPT_COMMON64, ServiceRoutine) : \
46  FIELD_OFFSET(KINTERRUPT_COMMON32, ServiceRoutine))
47 
52 {
58 
59 
64 {
69 
72 
73 
74 static INTSTATUS
76  _In_ INTOBJ_PROT_DESCRIPTOR *Descriptor,
78  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
79  _In_ INTRO_ACTION Action,
81  )
93 {
94  INTSTATUS status;
96 
97  pEvent = &gAlert.Integrity;
98  memzero(pEvent, sizeof(*pEvent));
99 
100  pEvent->BaseAddress = Descriptor->ObjectGva;
101  pEvent->VirtualAddress = Descriptor->ObjectGva;
102  pEvent->Size = 2 * gGuest.WordSize;
103  pEvent->Victim.IdtEntry = Descriptor->EntryIndex;
105 
106  // No valid CPU context and no valid current process can be obtained for this, as it is
107  // an integrity alert.
108  pEvent->Header.CpuContext.Valid = FALSE;
109  pEvent->Header.CurrentProcess.Valid = FALSE;
110 
112  pEvent->Header.Flags |= ALERT_FLAG_ASYNC;
113 
114  pEvent->Header.Action = Action;
115  pEvent->Header.Reason = Reason;
116  pEvent->Header.MitreID = idRootkit;
117 
119 
120  IntAlertFillWriteInfo(Victim, &pEvent->WriteInfo);
121 
122  IntAlertFillWinKmModule(Originator->Original.Driver, &pEvent->Originator.Module);
123 
125 
126  status = IntNotifyIntroEvent(introEventIntegrityViolation, pEvent, sizeof(*pEvent));
127  if (!INT_SUCCESS(status))
128  {
129  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
130  }
131 
132  return INT_STATUS_SUCCESS;
133 }
134 
135 
136 static INTSTATUS
138  _In_ INTOBJ_PROT_DESCRIPTOR *Descriptor,
140  _Out_ INTRO_ACTION *Action
141  )
157 {
158  INTEGRITY_REGION *dispatchReg = (INTEGRITY_REGION *)Descriptor->DispatchIntegrityObject;
159  INTEGRITY_REGION *serviceReg = (INTEGRITY_REGION *)Descriptor->ServiceIntegrityObject;
160  QWORD oldDispatchValue, oldServiceValue;
161  QWORD newDispatchValue = 0, newServiceValue = 0;
162  INTSTATUS status;
165  EXCEPTION_VICTIM_ZONE victim = { 0 };
166  EXCEPTION_KM_ORIGINATOR originator = { 0 };
167  DWORD offset = 0;
168 
169  if (0 == ObjectGva)
170  {
171  *Action = introGuestAllowed;
172  return INT_STATUS_SUCCESS;
173  }
174 
175  if (NULL == dispatchReg)
176  {
177  oldDispatchValue = 0;
178  }
179  else
180  {
181  oldDispatchValue = *(QWORD *)dispatchReg->OriginalContent;
182  }
183 
184  if (NULL == serviceReg)
185  {
186  oldServiceValue = 0;
187  }
188  else
189  {
190  oldServiceValue = *(QWORD *)serviceReg->OriginalContent;
191  }
192 
193  status = IntKernVirtMemFetchWordSize(ObjectGva + DISPATCH_OFFSET, &newDispatchValue);
194  if (!INT_SUCCESS(status))
195  {
196  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
197  return status;
198  }
199 
200  status = IntKernVirtMemFetchWordSize(ObjectGva + SERVICE_OFFSET, &newServiceValue);
201  if (!INT_SUCCESS(status))
202  {
203  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
204  return status;
205  }
206 
207  if (newDispatchValue == oldDispatchValue && newServiceValue == oldServiceValue)
208  {
209  *Action = introGuestAllowed;
210  return INT_STATUS_SUCCESS;
211  }
212 
213  // Note: This function is called either on an object relocation or when the object
214  // (DispatchAddress/ServiceRoutine) has been modified. On object relocation, if the object
215  // was NULL beforehand, then both serviceReg and dispatchReg will be NULL. If the object
216  // was valid, or a modification has been detected directly on the object, then both
217  // serviceReg and dispatchReg will be valid INTEGRITY_REGION objects.
218  if (newDispatchValue == oldDispatchValue && serviceReg != NULL)
219  {
220  status = IntExceptGetVictimIntegrity(serviceReg, &offset, &victim);
221  }
222  else if(dispatchReg != NULL)
223  {
224  status = IntExceptGetVictimIntegrity(dispatchReg, &offset, &victim);
225  }
226  else
227  {
228  // If we don't have an integrity region (the object has not been protected beforehand),
229  // then we'll need to construct our own victim.
232  victim.ZoneFlags |= ZONE_WRITE | ZONE_INTEGRITY;
233  victim.WriteInfo.AccessSize = 2 * gGuest.WordSize;
234 
235  status = INT_STATUS_SUCCESS;
236  }
237 
238  if (!INT_SUCCESS(status))
239  {
240  ERROR("[ERROR] Failed getting integrity zone: 0x%08x\n", status);
241  return status;
242  }
243 
244  // We'll set the old and new values so that they are in a known order.
245  victim.WriteInfo.OldValue[0] = oldDispatchValue;
246  victim.WriteInfo.OldValue[1] = oldServiceValue;
247 
248  victim.WriteInfo.NewValue[0] = newDispatchValue;
249  victim.WriteInfo.NewValue[1] = newServiceValue;
250 
251  victim.Integrity.InterruptObjIndex = Descriptor->EntryIndex;
253 
254  status = IntExceptGetOriginatorFromModification(&victim, &originator);
255  if (!INT_SUCCESS(status))
256  {
257  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
258  return status;
259  }
260 
261  IntExcept(&victim, &originator, exceptionTypeKm, &action, &reason, introEventIntegrityViolation);
262 
264  {
265  IntWinIntObjSendIntegrityAlert(Descriptor, &victim, &originator, action, reason);
266  }
267 
269 
270  *Action = action;
271  return INT_STATUS_SUCCESS;
272 }
273 
274 
275 static INTSTATUS
277  _Inout_ INTEGRITY_REGION *IntegrityRegion
278  )
291 {
292  INTOBJ_PROT_DESCRIPTOR *pDescriptor = (INTOBJ_PROT_DESCRIPTOR *)IntegrityRegion->Context;
294  INTSTATUS status;
295 
296  status = IntWinIntObjHandleModification(pDescriptor, pDescriptor->ObjectGva, &action);
297  if (!INT_SUCCESS(status))
298  {
299  ERROR("[ERROR] IntWinIntObjHandleModification failed: 0x%08x\n", status);
300  return status;
301  }
302 
303  if (action == introGuestAllowed)
304  {
305  IntIntegrityRecalculate(IntegrityRegion);
306  }
307  else if (action == introGuestNotAllowed)
308  {
309  IntPauseVcpus();
310 
312  IntegrityRegion->Gva,
314  IntegrityRegion->OriginalContent,
315  IG_CS_RING_0);
316 
317  IntResumeVcpus();
318 
319  if (!INT_SUCCESS(status))
320  {
321  ERROR("[ERROR] IntVirtMemSafeWrite failed for gva 0x%016llx: 0x%08x\n",
322  IntegrityRegion->Gva, status);
323  }
324  }
325 
326  return status;
327 }
328 
329 
330 static INTSTATUS
332  _Inout_ INTEGRITY_REGION *IntegrityRegion
333  )
348 {
349  INTSTATUS status;
350  INTOBJ_PERPROC_DESCRIPTOR *pDescriptor = (INTOBJ_PERPROC_DESCRIPTOR *)IntegrityRegion->Context;
351  QWORD *oldArray = (QWORD *)IntegrityRegion->OriginalContent;
352  QWORD *newArray;
353  BOOLEAN recalculate = FALSE;
355 
356  status = IntVirtMemMap(IntegrityRegion->Gva, IntegrityRegion->Length, gGuest.Mm.SystemCr3, 0, &newArray);
357  if (!INT_SUCCESS(status))
358  {
359  ERROR("[ERROR] IntVirtMemMap failed: 0x%08x\n", status);
360  return status;
361  }
362 
363  for (QWORD i = 0; i < INTERRUPT_OBJECT_COUNT; i++)
364  {
365  if (oldArray[i] == newArray[i])
366  {
367  continue;
368  }
369 
370  status = IntWinIntObjHandleModification(&pDescriptor->IntObjDescriptors[i], newArray[i], &action);
371  if (!INT_SUCCESS(status))
372  {
373  ERROR("[ERROR] IntWinIntObjHandleModification failed: 0x%08x\n", status);
374  goto cleanup_and_exit;
375  }
376 
377  if (action == introGuestAllowed)
378  {
379  recalculate = TRUE;
380 
381  // We need to create a new integrity object for the new object's Dispatch and remove the old one.
382  if (NULL != pDescriptor->IntObjDescriptors[i].DispatchIntegrityObject)
383  {
385  if (!INT_SUCCESS(status))
386  {
387  ERROR("[ERROR] IntIntegrityRemoveRegion failed: 0x%08x\n", status);
388  goto cleanup_and_exit;
389  }
390 
391  pDescriptor->IntObjDescriptors[i].DispatchIntegrityObject = NULL;
392  }
393 
394  if (newArray[i] != 0 && IS_KERNEL_POINTER_WIN(gGuest.Guest64, newArray[i]))
395  {
396  status = IntIntegrityAddRegion(newArray[i] + DISPATCH_OFFSET,
399  &pDescriptor->IntObjDescriptors[i],
401  TRUE,
402  &pDescriptor->IntObjDescriptors[i].DispatchIntegrityObject);
403  if (!INT_SUCCESS(status))
404  {
405  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
406  goto cleanup_and_exit;
407  }
408  }
409 
410  // As well as for ServiceRoutine.
411  if (NULL != pDescriptor->IntObjDescriptors[i].ServiceIntegrityObject)
412  {
414  if (!INT_SUCCESS(status))
415  {
416  ERROR("[ERROR] IntIntegrityRemoveRegion failed: 0x%08x\n", status);
417  goto cleanup_and_exit;
418  }
419 
420  pDescriptor->IntObjDescriptors[i].ServiceIntegrityObject = NULL;
421  }
422 
423  if (newArray[i] != 0 && IS_KERNEL_POINTER_WIN(gGuest.Guest64, newArray[i]))
424  {
425  status = IntIntegrityAddRegion(newArray[i] + SERVICE_OFFSET,
428  &pDescriptor->IntObjDescriptors[i],
430  TRUE,
431  &pDescriptor->IntObjDescriptors[i].ServiceIntegrityObject);
432  if (!INT_SUCCESS(status))
433  {
434  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
435  goto cleanup_and_exit;
436  }
437  }
438  }
439  else if (action == introGuestNotAllowed)
440  {
441  IntPauseVcpus();
442 
444  IntegrityRegion->Gva + i * gGuest.WordSize,
446  (BYTE *)IntegrityRegion->OriginalContent + i * gGuest.WordSize,
447  IG_CS_RING_0);
448 
449  IntResumeVcpus();
450 
451  if (!INT_SUCCESS(status))
452  {
453  ERROR("[ERROR] IntVirtMemSafeWrite failed for gva 0x%016llx: 0x%08x\n",
454  IntegrityRegion->Gva + i * gGuest.WordSize, status);
455  goto cleanup_and_exit;
456  }
457  }
458  }
459 
460  if (recalculate)
461  {
462  IntIntegrityRecalculate(IntegrityRegion);
463  }
464 
465 cleanup_and_exit:
466  IntVirtMemUnmap(&newArray);
467 
468  return status;
469 }
470 
471 
472 INTSTATUS
474  void
475  )
492 {
494  QWORD prcb = 0;
495 
496  if (!gGuest.Guest64)
497  {
499  }
500 
501  if (0 == WIN_KM_FIELD(Pcr, PrcbInterruptObject))
502  {
504  }
505 
506  gDescriptors = HpAllocWithTag(gGuest.ActiveCpuCount * sizeof(*gDescriptors), IC_TAG_IOBD);
507  if (NULL == gDescriptors)
508  {
510  }
511 
512  for (DWORD i = 0; i < gGuest.ActiveCpuCount; i++)
513  {
514  if (gGuest.VcpuArray[i].PcrGla == 0)
515  {
516  status = IntFindKernelPcr(i, &gGuest.VcpuArray[i].PcrGla);
517  if (!INT_SUCCESS(status))
518  {
519  ERROR("[ERROR] IntFindKernelPcr failed: 0x%08x\n", status);
520  continue;
521  }
522  }
523 
525  &prcb);
526  if (!INT_SUCCESS(status))
527  {
528  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
529  continue;
530  }
531 
532  // First, create an integrity object in order to be notified of modifications on the
533  // interrupt object array.
534  status = IntIntegrityAddRegion(prcb + WIN_KM_FIELD(Pcr, PrcbInterruptObject),
537  &gDescriptors[i],
539  TRUE,
540  &gDescriptors[i].ObjectIntegrityObject);
541  if (!INT_SUCCESS(status))
542  {
543  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
544  goto cleanup_and_exit;
545  }
546 
547  // For objects in the array that are currently initialized add integrity protection on
548  // DispatchAddress and ServiceRoutine.
549  for (DWORD intobjidx = 0; intobjidx < INTERRUPT_OBJECT_COUNT; intobjidx++)
550  {
551  QWORD currentIntObj = 0;
552  QWORD addr = prcb + WIN_KM_FIELD(Pcr, PrcbInterruptObject) + (QWORD)intobjidx * gGuest.WordSize;
553 
554  gDescriptors[i].IntObjDescriptors[intobjidx].EntryIndex = (BYTE)intobjidx;
555 
556  status = IntKernVirtMemFetchWordSize(addr, &currentIntObj);
557  if (!INT_SUCCESS(status))
558  {
559  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
560  continue;
561  }
562 
563  if (0 == currentIntObj || !IS_KERNEL_POINTER_WIN(gGuest.Guest64, currentIntObj))
564  {
565  continue;
566  }
567 
568  status = IntIntegrityAddRegion(currentIntObj + DISPATCH_OFFSET,
571  &gDescriptors[i].IntObjDescriptors[intobjidx],
573  TRUE,
574  &gDescriptors[i].IntObjDescriptors[intobjidx].DispatchIntegrityObject);
575  if (!INT_SUCCESS(status))
576  {
577  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
578  goto cleanup_and_exit;
579  }
580 
581  status = IntIntegrityAddRegion(currentIntObj + SERVICE_OFFSET,
584  &gDescriptors[i].IntObjDescriptors[intobjidx],
586  TRUE,
587  &gDescriptors[i].IntObjDescriptors[intobjidx].ServiceIntegrityObject);
588  if (!INT_SUCCESS(status))
589  {
590  ERROR("[ERROR] IntIntegrityAddRegion failed: 0x%08x\n", status);
591  goto cleanup_and_exit;
592  }
593 
594  gDescriptors[i].IntObjDescriptors[intobjidx].ObjectGva = currentIntObj;
595  }
596  }
597 
598 cleanup_and_exit:
599  if (!INT_SUCCESS(status))
600  {
602  }
603 
604  return status;
605 }
606 
607 
608 INTSTATUS
610  void
611  )
622 {
623  INTSTATUS status;
624 
625  if (NULL == gDescriptors)
626  {
628  }
629 
630  for (DWORD i = 0; i < gGuest.ActiveCpuCount; i++)
631  {
632  if (NULL == gDescriptors[i].ObjectIntegrityObject)
633  {
634  continue;
635  }
636 
637  status = IntIntegrityRemoveRegion(gDescriptors[i].ObjectIntegrityObject);
638  if (!INT_SUCCESS(status))
639  {
640  ERROR("[ERROR] IntIntegrityRemoveRegion failed: 0x%08x\n", status);
641  }
642 
643  for (DWORD objidx = 0; objidx < INTERRUPT_OBJECT_COUNT; objidx++)
644  {
645  if (gDescriptors[i].IntObjDescriptors[objidx].DispatchIntegrityObject != NULL)
646  {
647  status = IntIntegrityRemoveRegion(gDescriptors[i].IntObjDescriptors[objidx].DispatchIntegrityObject);
648  if (!INT_SUCCESS(status))
649  {
650  ERROR("[ERROR] IntIntegrityRemoveRegion failed: 0x%08x\n", status);
651  }
652 
653  gDescriptors[i].IntObjDescriptors[objidx].DispatchIntegrityObject = NULL;
654  }
655 
656  if (gDescriptors[i].IntObjDescriptors[objidx].ServiceIntegrityObject != NULL)
657  {
658  status = IntIntegrityRemoveRegion(gDescriptors[i].IntObjDescriptors[objidx].ServiceIntegrityObject);
659  if (!INT_SUCCESS(status))
660  {
661  ERROR("[ERROR] IntIntegrityRemoveRegion failed: 0x%08x\n", status);
662  }
663 
664  gDescriptors[i].IntObjDescriptors[objidx].ServiceIntegrityObject = NULL;
665  }
666  }
667  }
668 
669  HpFreeAndNullWithTag(&gDescriptors, IC_TAG_IOBD);
670 
671  return INT_STATUS_SUCCESS;
672 }
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:904
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
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
uint8_t BYTE
Definition: intro_types.h:47
QWORD ZoneFlags
The flags of the modified zone.
Definition: exceptions.h:898
void * ObjectIntegrityObject
The integrity object associated with the monitorized array.
Definition: winintobj.c:67
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:211
#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
An interrupt object from KPRCB.
Definition: intro_types.h:274
Event structure for integrity violations on monitored structures.
Definition: intro_types.h:1572
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
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
#define DISPATCH_OFFSET
Helper macro for computing the offset of DispatchAddress inside the nt!_KINTERRUPT structure...
Definition: winintobj.c:40
QWORD ObjectGva
The GVA of the current interrupt object.
Definition: winintobj.c:56
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
INTRO_OBJECT_TYPE Type
Definition: intro_types.h:1589
struct _EVENT_INTEGRITY_VIOLATION::@304 Victim
struct _INTOBJ_PERPROC_DESCRIPTOR INTOBJ_PERPROC_DESCRIPTOR
Structure describing the protected InterruptObject array for a KPRCB associated with a CPU...
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
#define ALERT_FLAG_ASYNC
If set, the alert was generated in an async manner.
Definition: intro_types.h:675
#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
int INTSTATUS
The status data type.
Definition: introstatus.h:24
void * ServiceIntegrityObject
The integrity object associated with ServiceRoutine.
Definition: winintobj.c:54
Rootkit.
Definition: intro_types.h:1144
Describes a kernel-mode originator.
Definition: exceptions.h:943
PVCPU_STATE VcpuArray
Array of the VCPUs assigned to this guest. The index in this array matches the VCPU number...
Definition: guests.h:372
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
BYTE IdtEntry
The modified IDT entry. Valid only if Type is introObjectTypeIdt.
Definition: intro_types.h:1599
static INTSTATUS IntWinIntObjHandleObjectModification(INTEGRITY_REGION *IntegrityRegion)
Integrity callback for modifications detected inside protected objects.
Definition: winintobj.c:276
#define VICTIM_INTERRUPT_OBJECT
Printable name used for introObjectTypeInterruptObject.
Definition: intro_types.h:763
struct _INTOBJ_PERPROC_DESCRIPTOR * PINTOBJ_PERPROC_DESCRIPTOR
struct _INTOBJ_PROT_DESCRIPTOR INTOBJ_PROT_DESCRIPTOR
Structure describing a protected interrupt object.
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
#define ZONE_INTEGRITY
Used for integrity zone.
Definition: exceptions.h:738
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
EXCEPTION_VICTIM_OBJECT Object
The modified object.
Definition: exceptions.h:895
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
void * DispatchIntegrityObject
The integrity object associated with DispatchAddress.
Definition: winintobj.c:53
INTOBJ_PROT_DESCRIPTOR IntObjDescriptors[INTERRUPT_OBJECT_COUNT]
Array containing protection descriptors for each protected interrupt object in the array...
Definition: winintobj.c:66
void IntAlertFillWriteInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_WRITE_INFO *WriteInfo)
Fills the write information for an alert.
Definition: alerts.c:521
INTSTATUS IntFindKernelPcr(DWORD CpuNumber, QWORD *Pcr)
Finds the address of the Windows kernel _KPCR.
Definition: introcpu.c:1116
DWORD Size
The size of the modified memory area.
Definition: intro_types.h:1618
#define IC_TAG_IOBD
Used for interrupt object protection descriptors.
Definition: memtags.h:139
#define INT_STATUS_NOT_INITIALIZED
Definition: introstatus.h:266
Structure describing the protected InterruptObject array for a KPRCB associated with a CPU...
Definition: winintobj.c:63
The modified object is inside an integrity hook.
Definition: exceptions.h:749
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1196
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
#define memzero(a, s)
Definition: introcrt.h:35
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
INTSTATUS IntWinIntObjProtect(void)
Protects the interrupt objects which are present in the KPRCB&#39;s InterruptObject array.
Definition: winintobj.c:473
INTRO_MODULE Module
The module that modified the monitored region.
Definition: intro_types.h:1578
#define INTRO_OPT_PROT_KM_INTERRUPT_OBJ
Enable protection against modifications of interrupt objects from KPRCB&#39;s InterruptObject.
Definition: intro_types.h:531
QWORD VirtualAddress
The guest virtual address which was modified.
Definition: intro_types.h:1616
#define TRUE
Definition: intro_types.h:30
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1574
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
QWORD StartVirtualAddress
The start address of the integrity zone.
Definition: exceptions.h:802
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
static INTSTATUS IntWinIntObjHandleArrayModification(INTEGRITY_REGION *IntegrityRegion)
Integrity callback for modifications detected inside the array containing the protected objects...
Definition: winintobj.c:331
#define INTERRUPT_OBJECT_COUNT
The number of protected interrupt objects.
Definition: winintobj.c:35
Kernel-mode exception.
Definition: exceptions.h:61
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
Definition: guests.h:367
INTRO_OBJECT_TYPE Type
The type of the modified object.
Definition: exceptions.h:852
ZONE_TYPE ZoneType
The type of the modified zone.
Definition: exceptions.h:897
static INTSTATUS IntWinIntObjSendIntegrityAlert(INTOBJ_PROT_DESCRIPTOR *Descriptor, EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an introEventIntegrityViolation alert for a modified Interrupt Object entry.
Definition: winintobj.c:75
#define SERVICE_OFFSET
Helper macro for computing the offset of ServiceRoutine inside the nt!_KINTERRUPT structure...
Definition: winintobj.c:45
#define WARNING(fmt,...)
Definition: glue.h:60
INTSTATUS IntVirtMemSafeWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, void *Buffer, DWORD Ring)
Safely modify guest memory.
Definition: kernvm.c:498
Describes the modified zone.
Definition: exceptions.h:893
struct _INTOBJ_PROT_DESCRIPTOR * PINTOBJ_PROT_DESCRIPTOR
struct _EXCEPTION_VICTIM_ZONE::@58::@60 WriteInfo
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:740
WCHAR Name[ALERT_PATH_MAX_LEN]
NULL-terminated string with a human readable description of the modified object.
Definition: intro_types.h:1591
uint32_t DWORD
Definition: intro_types.h:49
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:965
enum _INTRO_ACTION INTRO_ACTION
Event actions.
INTSTATUS IntIntegrityRemoveRegion(void *Descriptor)
Removes an integrity region from the gIntegrityRegions list.
Definition: integrity.c:313
INTRO_WRITE_INFO WriteInfo
Definition: intro_types.h:1607
__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
BYTE InterruptObjIndex
The index of the modified interrupt object. Valid only for introObjectTypeInterruptObject.
Definition: exceptions.h:807
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:374
Structure describing a protected interrupt object.
Definition: winintobj.c:51
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
void * OriginalContent
A buffer containing the original bytes of the associated region.
Definition: integrity.h:43
BYTE EntryIndex
The index of the current object in the InterruptObject array.
Definition: winintobj.c:55
EVENT_INTEGRITY_VIOLATION Integrity
Definition: alerts.h:23
struct _EVENT_INTEGRITY_VIOLATION::@302 Originator
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
QWORD BaseAddress
The guest virtual address at which the monitored integrity region starts.
Definition: intro_types.h:1614
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...
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
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:908
DWORD ActiveCpuCount
The number of CPUs actually used by the guest.
Definition: guests.h:280
INTOBJ_PERPROC_DESCRIPTOR * gDescriptors
Global array containing the per CPU protection descriptors for each InterruptObject array...
Definition: winintobj.c:71
void IntAlertFillWinKmModule(const KERNEL_DRIVER *Driver, INTRO_MODULE *EventModule)
Saves kernel module information inside an alert.
Definition: alerts.c:617
INTSTATUS IntWinIntObjUnprotect(void)
Uninitializes the interrupt objects protection.
Definition: winintobj.c:609
QWORD PcrGla
The guest linear address of the _KPCR structure loaded by this CPU.
Definition: guests.h:108
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
static INTSTATUS IntWinIntObjHandleModification(INTOBJ_PROT_DESCRIPTOR *Descriptor, QWORD ObjectGva, INTRO_ACTION *Action)
Handles the modification of an interrupt object.
Definition: winintobj.c:137
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:3357
#define FALSE
Definition: intro_types.h:34
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281