Bitdefender Hypervisor Memory Introspection
callbacks.h File Reference
#include "glue.h"
#include "introdefs.h"

Go to the source code of this file.

Functions

INTSTATUS IntHandleEptViolation (void *GuestHandle, QWORD PhysicalAddress, DWORD Length, QWORD LinearAddress, DWORD CpuNumber, INTRO_ACTION *Action, IG_EPT_ACCESS AccessType)
 Handle an EPT violation. More...
 
INTSTATUS IntHandleMsrViolation (void *GuestHandle, DWORD Msr, IG_MSR_HOOK_TYPE Flags, INTRO_ACTION *Action, QWORD OriginalValue, QWORD *NewValue, DWORD CpuNumber)
 Handle a model specific register violation. More...
 
INTSTATUS IntHandleCrWrite (void *GuestHandle, DWORD Cr, DWORD CpuNumber, QWORD OldValue, QWORD NewValue, INTRO_ACTION *Action)
 Handle a control register violation. More...
 
INTSTATUS IntHandleDtrViolation (void *GuestHandle, DWORD Flags, DWORD CpuNumber, INTRO_ACTION *Action)
 Handle GDTR, IDTR, LDTR, TR accesses. More...
 
INTSTATUS IntHandleIntroCall (void *GuestHandle, QWORD Rip, DWORD CpuNumber)
 Handle a VMCALL issued inside the guest. More...
 
INTSTATUS IntHandleTimer (void *GuestHandle)
 Periodically called by the integrator, once every second. More...
 
INTSTATUS IntHandleXcrWrite (void *GuestHandle, DWORD CpuNumber, INTRO_ACTION *Action)
 Handle extended control registers writes. More...
 
INTSTATUS IntHandleBreakpoint (void *GuestHandle, QWORD GuestPhysicalAddress, DWORD CpuNumber)
 Handle guest breakpoints. More...
 
INTSTATUS IntCallbacksInit (void)
 Initialize the callbacks. More...
 
INTSTATUS IntCallbacksUnInit (void)
 Uninit all the Introcore callbacks. More...
 
static INTSTATUS IntEnableEptNotifications (void)
 
static INTSTATUS IntDisableEptNotifications (void)
 
static INTSTATUS IntEnableDtrNotifications (void)
 
static INTSTATUS IntDisableDtrNotifications (void)
 
static INTSTATUS IntEnableMsrNotifications (void)
 
static INTSTATUS IntDisableMsrNotifications (void)
 
static INTSTATUS IntEnableCrNotifications (void)
 
static INTSTATUS IntDisableCrNotifications (void)
 
static INTSTATUS IntEnableXcrNotifications (void)
 
static INTSTATUS IntDisableXcrNotifications (void)
 
static INTSTATUS IntEnableBreakpointNotifications (void)
 
static INTSTATUS IntDisableBreakpointNotifications (void)
 

Function Documentation

◆ IntCallbacksInit()

INTSTATUS IntCallbacksInit ( void  )

Initialize the callbacks.

Most of the callbacks are initialized here. As soon as a callback is registered for a certain type of event, Introcore can start processing them. NOTE: Some callbacks, such as the breakpoint handler or the EPT violation handler are registered on the init flow, so as to avoid having to handle many irrelevant events while we initialize.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 3527 of file callbacks.c.

Referenced by IntGuestHandleCr3Write().

◆ IntCallbacksUnInit()

INTSTATUS IntCallbacksUnInit ( void  )

Uninit all the Introcore callbacks.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 3576 of file callbacks.c.

Referenced by IntGuestUninit().

◆ IntDisableBreakpointNotifications()

static INTSTATUS IntDisableBreakpointNotifications ( void  )
inlinestatic

Definition at line 278 of file callbacks.h.

Referenced by IntLixAgentExit(), and IntLixAgentThreadExit().

◆ IntDisableCrNotifications()

static INTSTATUS IntDisableCrNotifications ( void  )
inlinestatic

Definition at line 210 of file callbacks.h.

Referenced by IntHookCrDeleteHook().

◆ IntDisableDtrNotifications()

static INTSTATUS IntDisableDtrNotifications ( void  )
inlinestatic

Definition at line 142 of file callbacks.h.

Referenced by IntHookDtrDeleteHook().

◆ IntDisableEptNotifications()

static INTSTATUS IntDisableEptNotifications ( void  )
inlinestatic

Definition at line 108 of file callbacks.h.

Referenced by IntHookGpaDeleteHookInternal().

◆ IntDisableMsrNotifications()

static INTSTATUS IntDisableMsrNotifications ( void  )
inlinestatic

Definition at line 176 of file callbacks.h.

Referenced by IntHookMsrDeleteHook().

◆ IntDisableXcrNotifications()

static INTSTATUS IntDisableXcrNotifications ( void  )
inlinestatic

Definition at line 244 of file callbacks.h.

Referenced by IntHookXcrDeleteHook().

◆ IntEnableBreakpointNotifications()

static INTSTATUS IntEnableBreakpointNotifications ( void  )
inlinestatic

Definition at line 261 of file callbacks.h.

Referenced by IntLixAgentActivatePendingAgent().

◆ IntEnableCrNotifications()

static INTSTATUS IntEnableCrNotifications ( void  )
inlinestatic

Definition at line 193 of file callbacks.h.

Referenced by IntHookCrSetHook().

◆ IntEnableDtrNotifications()

static INTSTATUS IntEnableDtrNotifications ( void  )
inlinestatic

Definition at line 125 of file callbacks.h.

Referenced by IntHookDtrSetHook().

◆ IntEnableEptNotifications()

static INTSTATUS IntEnableEptNotifications ( void  )
inlinestatic

Definition at line 91 of file callbacks.h.

Referenced by IntHookGpaSetHook().

◆ IntEnableMsrNotifications()

static INTSTATUS IntEnableMsrNotifications ( void  )
inlinestatic

Definition at line 159 of file callbacks.h.

Referenced by IntHookMsrSetHook().

◆ IntEnableXcrNotifications()

static INTSTATUS IntEnableXcrNotifications ( void  )
inlinestatic

Definition at line 227 of file callbacks.h.

Referenced by IntHookXcrSetHook().

◆ IntHandleBreakpoint()

INTSTATUS IntHandleBreakpoint ( void *  GuestHandle,
QWORD  GuestPhysicalAddress,
DWORD  CpuNumber 
)

Handle guest breakpoints.

This handler is called by the integrator whenever a breakpoint (INT3) takes place inside the guest. This function will just dispatch the event to an appropriate Introcore handler, in this order:

  1. Detours;
  2. Agents;
  3. The PT filter. If no handler claims ownership for a particular INT3, we will disassemble the instruction pointed by the current RIP. If indeed there is an INT3 there, we will re-inject it to the guest, as it probably really is an in-guest breakpoint. If the instruction is not INT3, it may have been replaced by the PT filter, for example, when inspecting a candidate instruction. In that case, we will simply re-entry inside the guest at the same RIP. Handling the breakpoint can be done in three ways:
  1. Reinject it; if the INT3 wasn't triggered by our detours, agents or PT filter, it gets reinjected;
  2. Skip it; if the INT3 was handled by us, simply move the RIP over it;
  3. Re-entry at the same instruction; if introcore replaced the INT3 with something else in the meantime, simply re-enter at the same RIP.
Parameters
[in]GuestHandleThe guest handle.
[in]GuestPhysicalAddressUnused.
[in]CpuNumberThe VCPU number.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized.
INT_STATUS_NOT_FOUNDIf Introcore did not handle the VMCALL.
INT_STATUS_FATAL_ERRORIf a fatal error occurred and the integrator should unload Introcore.
INT_STATUS_UNINIT_BUGCHECKIf a bug-check occurred inside the guest and Introcore should be unloaded.

Definition at line 2734 of file callbacks.c.

Referenced by IntEnableBreakpointNotifications(), and IntWinGuestInit().

◆ IntHandleCrWrite()

INTSTATUS IntHandleCrWrite ( void *  GuestHandle,
DWORD  Cr,
DWORD  CpuNumber,
QWORD  OldValue,
QWORD  NewValue,
INTRO_ACTION Action 
)

Handle a control register violation.

This function is called by the integrator/HV on each CR violation. The handler will simply iterate the list of registered callbacks for this particular CR, and call each one of them. Introcore only places write hooks on the control registers; read hooks may trigger a very high performance impact.

Parameters
[in]GuestHandleThe guest handle.
[in]CrThe accessed CR.
[in]CpuNumberThe VCPU number.
[in]OldValueOld CR value.
[in]NewValueNew CR value.
[in]ActionThe desired action.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized yet.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_FOUNDIf no callback is found for this MSR.
INT_STATUS_FATAL_ERRORA fatal error occurred, and the integrator should unload Introcore.

Definition at line 1692 of file callbacks.c.

Referenced by IntEnableCrNotifications().

◆ IntHandleDtrViolation()

INTSTATUS IntHandleDtrViolation ( void *  GuestHandle,
DWORD  Flags,
DWORD  CpuNumber,
INTRO_ACTION Action 
)

Handle GDTR, IDTR, LDTR, TR accesses.

This function is called on descriptor table registers accesses. This function will iterate registered callbacks and it will call all of them. Special handling is done, however, for these instructions, as they generate a descriptor table access VM exit before doing any kind of memory checks; therefore, emulating such an instruction may lead to an EPT protection bypass (since the HV may not check EPT access rights when emulating instructions). As a result, we do some serious checks when handling these instructions:

  1. Bail out if the instruction is not LIDT, LGDT, LLDT, LTR, SIDT, SGDT, SLDT, STR;
  2. Bail out if the instruction doesn't operate on memory - we are only interested in LGDT/LIDT, which can only operate on memory operands;
  3. Decode the accessed linear address, and call the CoW and regular memory access handlers for that address;
  4. If the access is valid, carry on by calling the LIDT/LGDT handlers. NOTE: The instruction will be allowed by default when loading a non-null value over a previously null value; this is basically the initialization of that register.
Parameters
[in]GuestHandleThe guest handle.
[in]FlagsDescriptor table accessed & accessed type. Check out IG_DESC_ACCESS.
[in]CpuNumberThe VCPU number.
[out]ActionDesired action.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized.
INT_STATUS_FATAL_ERRORIf a fatal error occurred and Introcore should be unloaded.

(for example, GDTR READ, IDTR WRITE, etc.).

Definition at line 3116 of file callbacks.c.

Referenced by IntEnableDtrNotifications().

◆ IntHandleEptViolation()

INTSTATUS IntHandleEptViolation ( void *  GuestHandle,
QWORD  PhysicalAddress,
DWORD  Length,
QWORD  LinearAddress,
DWORD  CpuNumber,
INTRO_ACTION Action,
IG_EPT_ACCESS  AccessType 
)

Handle an EPT violation.

This callback is called by the HV/integrator whenever an EPT violation takes place. Introcore will handle the event by calling registered callbacks for the accessed memory area. Note that Introcore will also call the callbacks for other linear addresses that may be accessed by the instruction. Upon return, it has to return an action to the integrator. The main steps taken by this function are:

  1. Decode the instruction that triggered the EPT violation;
  2. Handle PT filter or mem-table instructions that triggered an exit after being handled by another VCPU;
  3. Check if the EPT violation took place inside the protected EPT view; if so, call the appropriate handler;
  4. Handle the execute EPT violation, if it's the case;
  5. Decode all addresses the instruction accesses, and, for each decoded linear address, translate it to a physical address, and call the IntHandleMemAccess function (note that the translation will not be done if the accessed linear address is the same as LinearAddress);
  6. Handle REP instructions: if a REP prefixed instruction touches a region of memory which is hooked, disable REP optimizations, and re-execute that instruction step by step;
  7. Handle read emulation. If we have reads made by the patch-guard inside hidden memory areas, return the original data;
  8. Handle x86 PAE page table writes. If one 4 bytes piece from an 8 bytes page-table entry is written, search for the instruction which writes the second 4 bytes piece, and emulate that too;
  9. Handle Copy-on-Write at page boundary. NOTE: A good security measure is to not handle an EPT violation if the instruction that triggered it is not cached. The reasoning behind this is TOCTOU: while we disassemble & analyze the instruction that triggered the fault, an attacker may replace that instruction with a malicious one, which may get emulated once Introcore decides that the action was legitimate. Therefore, if an EPT violation is generated from an instruction that is not cached, simply cache the instruction, and re-execute it. The second time the EPT violation takes place, the instruction will be cached, and an attacker won't be able to replace it inside guest memory, since a cached instruction means that the page it lies in is marked non-writable inside EPT. NOTE: The reason why we may call the memory access function for linear addresses for which no EPT violation has been generated is because we must inspect each address accessed by the instruction in order to conclude that it is legitimate. For example, let's say the instruction "PUSH [rax]" is executed, and it triggers a read EPT violation on the memory pointed by "rax". Introcore may conclude that this is legitimate, that memory can be read, and the instruction can be emulated. However, the instruction also writes to the memory pointed by "rsp" (the stack), which may also be hooked against writes! However, because Introcore allowed the instruction to be emulated, this stack write would no longer generate an EPT violation, and protection may be bypassed. Therefore, in order to deem an instruction safe to be emulated, we analyze every address accessed by the instruction.
Parameters
[in]GuestHandleA handle to the guest that generated the EPT violation.
[in]PhysicalAddressAccessed guest physical address.
[in]LengthAccess size. Note that this parameter is reserved for future use, as the HV does not decode (and the CPU does not provide) the access size.
[in]LinearAddressThe accessed guest linear address.
[in]CpuNumberVCPU number.
[out]ActionWill contain, upon successful return, the action to be taken fro the access.
[in]AccessTypeAccess type: IG_EPT_HOOK_READ, IG_EPT_HOOK_WRITE & IG_EPT_HOOK_EXECUTE.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_FORCE_ACTION_ON_BETAForce the introGuestNotAllowed, even in beta mode. This ensures that our hooks don't get overwritten.
INT_STATUS_FATAL_ERRORA fatal error occurred, and the integrator should unload Introcore.

NOTE: The instruction may be modified after the fault is triggered. Therefore, we may process the GLA/GPA the fault took place at, but the instruction may encode a different address.

Definition at line 825 of file callbacks.c.

Referenced by IntEnableEptNotifications().

◆ IntHandleIntroCall()

INTSTATUS IntHandleIntroCall ( void *  GuestHandle,
QWORD  Rip,
DWORD  CpuNumber 
)

Handle a VMCALL issued inside the guest.

This function will be called by the hypervisor whenever a VMCALL is executed inside the guest with a magic value in EAX register. For the Xen hypervisor, this magic value involves several registers: On x64: RAX = 0x22, RDI = 0x18, RSI = 0 On x86: EAX = 0x22, EBX = 0x18, ECX = 0 The EAX register will be overwritten by the HV on guest re-entry, so don't use it to pass the result of the VMCALL. This function will dispatch the VMCALL to the following handlers, in this order:

  1. VE handler, if the RIP is inside the VE agent;
  2. PT handler, if the RIP is inside the PT filter;
  3. Detours, if VMCALL is used as the hyper call method;
  4. Agents. After dispatching the VMCALL appropriately, this function will finally dispatch it as an EPT violation if either the PT filter or the VE agent requested so.
Parameters
[in]GuestHandleThe guest handle.
[in]RipRIP where the VMCALL originates.
[in]CpuNumberThe VCPU number.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized.
INT_STATUS_NOT_FOUNDIf Introcore did not handle the VMCALL.
INT_STATUS_FATAL_ERRORIf a fatal error occurred and the integrator should unload Introcore.
INT_STATUS_UNINIT_BUGCHECKIf a bug-check occurred inside the guest and Introcore should be unloaded.

Definition at line 2140 of file callbacks.c.

Referenced by IntCallbacksInit().

◆ IntHandleMsrViolation()

INTSTATUS IntHandleMsrViolation ( void *  GuestHandle,
DWORD  Msr,
IG_MSR_HOOK_TYPE  Flags,
INTRO_ACTION Action,
QWORD  OriginalValue,
QWORD NewValue,
DWORD  CpuNumber 
)

Handle a model specific register violation.

This callback is called on MSR violations. This handle will iterate the list of registered callbacks for that particular MSR, and will call each one of them. NOTE: Although read hooks can also be established on MSRs, Introcore does not make use of that, only write hooks are set.

Parameters
[in]GuestHandleThe guest handle.
[in]MsrThe accessed MSR.
[in]FlagsMSR violation type (read or write).
[out]ActionDesired action.
[in]OriginalValueOriginal MSR value.
[out]NewValueNew MSR value. Can be modified, but whether the HV will take this into consideration or not is implementation dependent, so it is advisable to not modify this value.
[in]CpuNumberThe VCPU number.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized yet.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_FOUNDIf no callback is found for this MSR.
INT_STATUS_FATAL_ERRORA fatal error occurred, and the integrator should unload Introcore.

Definition at line 1536 of file callbacks.c.

Referenced by IntEnableMsrNotifications().

◆ IntHandleTimer()

INTSTATUS IntHandleTimer ( void *  GuestHandle)

Periodically called by the integrator, once every second.

This function is called every second. Tasks such as integrity checks can be done here. The main tasks this handle carries are:

  1. Infinity hook protection;
  2. Integrity checks on structures that cannot be protected using EPT/SPP;
  3. Process token integrity checks - it will check every second if a system token has been stolen;
  4. System CR3 integrity - it will check every second to see of the System CR3 has been modified;
  5. Self-map integrity - it will check every second of the self-map entry inside the page-tables has been modified;
  6. Re-inject page-faults that did not get to be processes in the last second;
  7. Do PT integrity checks; since the PT monitors page-tables by intercepting instructions inside NT that modify them, there is a chance that someone else could modify a page-table entry without us knowing; this integrity check will make sure that every page-table entry that we monitor hasn't been tampered with;
  8. Once every hour, dump performance statistics; NOTE: this may be called on any processor. However, code must not make assumptions regarding the PCPUS/VCPUS it gets called on, and neither should it assume that it will be called on more than one processor. This function will get called every second. This also ensures us that every second, the hooks will be committed or cleaned up. IMPORTANT: Any function called here must be TIMER_FRIENDLY: it must not rely on VCPU state or on the fact that a "current VCPU exits" - it should assume that all the VCPUs are running and it must rely only on the global, known state of the guest: system CR3, cached paging mode, etc. Doing any kind of state query will lead to a VCPU pause, will return the state of that VCPU, but the VCPU will then be resumed, resulting in a dangling state, which may quickly become invalid. If guest state is required, make sure you pause all the VCPUs.
Parameters
[in]GuestHandleThe guest handle.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized.

It would be nice to pause the guest while we do the checks; However, since we're doing read-only operations and the protected areas should not be modified during the normal usage, we can safely let all other processors run code.

Definition at line 2359 of file callbacks.c.

Referenced by IntCallbacksInit().

◆ IntHandleXcrWrite()

INTSTATUS IntHandleXcrWrite ( void *  GuestHandle,
DWORD  CpuNumber,
INTRO_ACTION Action 
)

Handle extended control registers writes.

This function handles the XSETBV instruction, which modifies XCRs. Currently, only XCR0 can be intercepted. Even this is intercepted in order to aid into activating protection, and it is not protected against attacks. This function will iterate the list of XCR callbacks, and it will call each one.

Parameters
[in]GuestHandleThe guest handle.
[in]CpuNumberThe VCPU number.
[out]ActionThe desired action.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_NOT_INITIALIZED_HINTIf the guest is not initialized.
INT_STATUS_NOT_FOUNDIf Introcore did not handle the VMCALL.
INT_STATUS_FATAL_ERRORIf a fatal error occurred and the integrator should unload Introcore.

Definition at line 2580 of file callbacks.c.

Referenced by IntEnableXcrNotifications().