Bitdefender Hypervisor Memory Introspection
windriver.c File Reference

This file handles Windows Drivers related events (loading, unloading, writes, etc.) More...

#include "windriver.h"
#include "alerts.h"
#include "crc32.h"
#include "hook.h"
#include "swapmem.h"
#include "winpe.h"
#include "winagent.h"
#include "windrv_protected.h"

Go to the source code of this file.

Macros

#define NTOSKRNL_RIP_PAGES_COUNT   20
 
#define PATCHGUARD_RIP_COUNT   4
 
#define MAX_KNOWN_DRIVER_READS   100000
 

Functions

static void IntWinDrvSendEvent (KERNEL_DRIVER *Driver, BOOLEAN Loaded)
 Send a driver loaded/unloaded event. More...
 
INTSTATUS IntWinDrvIsListHead (QWORD PsLoadedModuleListGva, void *PsLoadedModuleList, QWORD KernelLdr)
 Used to identify WINDOWS_GUEST::PsLoadedModuleList. More...
 
INTSTATUS IntWinDrvIterateLoadedModules (PFUNC_IterateListCallback Callback, QWORD Aux)
 Used to iterate trough the WINDOWS_GUEST::PsLoadedModuleList. More...
 
INTSTATUS IntWinDrvCreateFromAddress (QWORD ModuleInfo, QWORD Flags)
 Adds a driver to introspection's LoadedModuleList (gKernelDrivers). This way we avoid lots of mapping when searching a driver. More...
 
INTSTATUS IntWinDrvRemoveFromAddress (QWORD ModuleInfo)
 Removes a driver from the introspection's loaded modules list (gKernelDrivers). More...
 
INTSTATUS IntWinProtectReadNtEat (void)
 Used to place a read hook on the ntoskrnl.exe EAT. More...
 
INTSTATUS IntWinUnprotectReadNtEat (void)
 Used to remove the EAT read hook from ntoskrnl.exe. More...
 
static INTSTATUS IntWinDrvHeadersInMemory (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
 This callback is called as soon as all the driver headers have been read using IntSwapMemReadData. More...
 
INTSTATUS IntWinDrvProtect (KERNEL_DRIVER *Driver, QWORD ProtectionFlag)
 Used to enable protection for the given driver. More...
 
INTSTATUS IntWinDrvUnprotect (KERNEL_DRIVER *Driver)
 Used to disable protection for the given driver. More...
 
INTSTATUS IntWinDrvHandleDriverEntry (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Used to notify the introspection engine when the DriverEntry of a module starts executing. More...
 
static INTSTATUS IntWinDrvSendAlert (KERNEL_DRIVER *Driver, EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
 Sends a driver related EPT violation alert. More...
 
INTSTATUS IntWinDrvHandleWrite (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Used to notify the introspection engine when a write took place on a protected driver. More...
 
static KERNEL_DRIVERIntWinGetDriverByGva (QWORD Rip)
 Iterates all the loaded drivers to see if the Rip points inside any of them. More...
 
static INTSTATUS IntWinDrvForceDisableReadNtEat (KERNEL_DRIVER *CurrentOriginator)
 This function is used to disable the INTRO_OPT_PROT_KM_NT_EAT_READS by removing the hook IntWinDrvHandleRead. More...
 
INTSTATUS IntWinDrvHandleRead (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Used to notify the introspection engine when a read took place on a protected driver (used only for ntoskrnl.exe). More...
 
static INTSTATUS IntWinDrvFreeEntry (KERNEL_DRIVER *Driver, QWORD Reserved)
 Frees the memory allocate for the KERNEL_DRIVER structure. More...
 
INTSTATUS IntWinDrvRemoveEntry (KERNEL_DRIVER *Driver)
 Removes the KERNEL_DRIVER from the internal structures. More...
 
INTSTATUS IntWinDrvUpdateProtection (void)
 Used to update the protection for all the loaded modules (gKernelDrivers). More...
 

Variables

LIST_HEAD gKernelDrivers
 List of all the drivers currently loaded inside the guest. More...
 

Detailed Description

This file handles Windows Drivers related events (loading, unloading, writes, etc.)

Introcore provides a very good protection against kernel exploits by identifying already loaded drivers and intercepting driver load/unload events. Once a driver is identified, read/write hooks are placed in order to protect critical structures (such as the EAT, IAT, etc.). This file contains all the functions used to identify the kernel drivers, hook critical driver structures, handle driver related EPT violations and notify the integrator upon driver related events.

Definition in file windriver.c.

Macro Definition Documentation

◆ MAX_KNOWN_DRIVER_READS

#define MAX_KNOWN_DRIVER_READS   100000

Referenced by IntWinDrvHandleRead().

◆ NTOSKRNL_RIP_PAGES_COUNT

#define NTOSKRNL_RIP_PAGES_COUNT   20

Referenced by IntWinDrvHandleRead().

◆ PATCHGUARD_RIP_COUNT

#define PATCHGUARD_RIP_COUNT   4

Referenced by IntWinDrvHandleRead().

Function Documentation

◆ IntWinDrvCreateFromAddress()

INTSTATUS IntWinDrvCreateFromAddress ( QWORD  ModuleInfo,
QWORD  Flags 
)

Adds a driver to introspection's LoadedModuleList (gKernelDrivers). This way we avoid lots of mapping when searching a driver.

Parameters
[in]ModuleInfoThe LDR_DATA_TABLE_ENTRY32 or LDR_DATA_TABLE_ENTRY64 corresponding to the module.
[in]FlagsIf FLAG_DYNAMIC_DETECTION flag is set, we will execute-protect the first page of the module. This way, when the first instruction will get executed, we will be notified, and we'll have a chance to protect the driver's driver object.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 305 of file windriver.c.

Referenced by IntDriverLoadHandler(), and IntWinGuestFinishInit().

◆ IntWinDrvForceDisableReadNtEat()

static INTSTATUS IntWinDrvForceDisableReadNtEat ( KERNEL_DRIVER CurrentOriginator)
static

This function is used to disable the INTRO_OPT_PROT_KM_NT_EAT_READS by removing the hook IntWinDrvHandleRead.

In some cases, a known driver could read the NT EAT so many times that a significant performance impact will be noticed (even if all the reads are allowed). After reaching a predetermined threshold, the INTRO_OPT_PROT_KM_NT_EAT_READS option will be disabled so that the system will not "hang" and the integrator will be notified.

Parameters
[in]CurrentOriginatorThe last driver that read the EAT (in is not necessarily the driver that performed all the reads, although is highly likely).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1436 of file windriver.c.

Referenced by IntWinDrvHandleRead().

◆ IntWinDrvFreeEntry()

static INTSTATUS IntWinDrvFreeEntry ( KERNEL_DRIVER Driver,
QWORD  Reserved 
)
static

Frees the memory allocate for the KERNEL_DRIVER structure.

Parameters
[in]DriverThe driver to be freed.
[in]ReservedReserved for further use.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1659 of file windriver.c.

Referenced by IntWinDrvRemoveEntry().

◆ IntWinDrvHandleDriverEntry()

INTSTATUS IntWinDrvHandleDriverEntry ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)

Used to notify the introspection engine when the DriverEntry of a module starts executing.

This hook will be established on the page containing the EP of freshly loaded drivers. On the execution of the first EP instruction, we will be notified, and we will be able to retrieve the driver-object associated to that driver, and hook it, if needed.

Parameters
[in]ContextUser-supplied context (may contain anything, including NULL).
[in]HookThe GPA hook associated to this callback.
[in]AddressGPA address that was accessed.
[out]ActionDesired action (allow, block).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1152 of file windriver.c.

Referenced by IntWinDrvCreateFromAddress().

◆ IntWinDrvHandleRead()

INTSTATUS IntWinDrvHandleRead ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)

Used to notify the introspection engine when a read took place on a protected driver (used only for ntoskrnl.exe).

Parameters
[in]ContextThe driver for which the violation took place (KERNEL_DRIVER structure).
[in]HookThe GPA hook associated to this callback.
[in]AddressGPA address that was accessed.
[out]ActionDesired action (allow, block).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1483 of file windriver.c.

Referenced by IntWinProtectReadNtEat().

◆ IntWinDrvHandleWrite()

INTSTATUS IntWinDrvHandleWrite ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)

Used to notify the introspection engine when a write took place on a protected driver.

Parameters
[in]ContextThe driver for which the violation took place (KERNEL_DRIVER structure).
[in]HookThe GPA hook associated to this callback.
[in]AddressGPA address that was accessed.
[out]ActionDesired action (allow, block).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1315 of file windriver.c.

Referenced by IntWinDrvHeadersInMemory().

◆ IntWinDrvHeadersInMemory()

static INTSTATUS IntWinDrvHeadersInMemory ( void *  Context,
QWORD  Cr3,
QWORD  VirtualAddress,
QWORD  PhysicalAddress,
void *  Data,
DWORD  DataSize,
DWORD  Flags 
)
static

This callback is called as soon as all the driver headers have been read using IntSwapMemReadData.

Parameters
[in]ContextThe KERNEL_DRIVER structure.
[in]Cr3The virtual address space.
[in]VirtualAddressThe base virtual address read.
[in]PhysicalAddressThe physical address of the first page (VirtualAddress) read.
[in]DataBuffer containing the read data. This will be freed once the callback returns!
[in]DataSizeSize of the Data buffer. Will normally be equal to the Length passed to read function.
[in]FlagsSwap flags. Check out SWAPMEM_FLG* for more info.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 724 of file windriver.c.

Referenced by IntWinDrvProtect().

◆ IntWinDrvIsListHead()

INTSTATUS IntWinDrvIsListHead ( QWORD  PsLoadedModuleListGva,
void *  PsLoadedModuleList,
QWORD  KernelLdr 
)

Used to identify WINDOWS_GUEST::PsLoadedModuleList.

Parameters
[in]PsLoadedModuleListGvaThe PsLoadedModuleList GVA.
[in]PsLoadedModuleListThe PsLoadedModuleList (mapped).
[in]KernelLdrGVA pointer to a LDR_DATA_TABLE_ENTRY32 or LDR_DATA_TABLE_ENTRY64 structure.
Return values
INT_STATUS_SUCCESSIf the PsLoadedModuleListGva is the actual list head.

Definition at line 67 of file windriver.c.

Referenced by IntWinGuestFindKernelObjectsInternal().

◆ IntWinDrvIterateLoadedModules()

INTSTATUS IntWinDrvIterateLoadedModules ( PFUNC_IterateListCallback  Callback,
QWORD  Aux 
)

Used to iterate trough the WINDOWS_GUEST::PsLoadedModuleList.

Parameters
[in]CallbackThe PFUNC_IterateListCallback callback invoked for every module.
[in]AuxThe auxiliary value passed to the callback.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 227 of file windriver.c.

Referenced by IntWinGuestFinishInit().

◆ IntWinDrvProtect()

INTSTATUS IntWinDrvProtect ( KERNEL_DRIVER Driver,
QWORD  ProtectionFlag 
)

Used to enable protection for the given driver.

Parameters
[in]DriverThe driver to be protected.
[in]ProtectionFlagThe protection flag.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_ALREADY_INITIALIZED_HINTIf the driver is already protected.
INT_STATUS_INVALID_PARAMETER_1If the driver is NULL.

Definition at line 1069 of file windriver.c.

Referenced by IntWinDrvCreateFromAddress(), and IntWinDrvUpdateProtection().

◆ IntWinDrvRemoveEntry()

INTSTATUS IntWinDrvRemoveEntry ( KERNEL_DRIVER Driver)

Removes the KERNEL_DRIVER from the internal structures.

Parameters
[in]DriverThe driver to be removed.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1696 of file windriver.c.

Referenced by IntDriverUninit(), IntWinDrvCreateFromAddress(), and IntWinDrvRemoveFromAddress().

◆ IntWinDrvRemoveFromAddress()

INTSTATUS IntWinDrvRemoveFromAddress ( QWORD  ModuleInfo)

Removes a driver from the introspection's loaded modules list (gKernelDrivers).

Parameters
[in]ModuleInfoThe LDR_DATA_TABLE_ENTRY32 or LDR_DATA_TABLE_ENTRY64 corresponding to the module.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 522 of file windriver.c.

Referenced by IntDriverUnloadHandler().

◆ IntWinDrvSendAlert()

static INTSTATUS IntWinDrvSendAlert ( KERNEL_DRIVER Driver,
EXCEPTION_VICTIM_ZONE Victim,
EXCEPTION_KM_ORIGINATOR Originator,
INTRO_ACTION  Action,
INTRO_ACTION_REASON  Reason 
)
static

Sends a driver related EPT violation alert.

Parameters
[in]DriverThe driver for which the violation took place.
[in]VictimThe victim.
[in]OriginatorThe originator.
[in]ActionTaken action.
[in]ReasonReason for the taken reason.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1250 of file windriver.c.

Referenced by IntWinDrvHandleRead(), and IntWinDrvHandleWrite().

◆ IntWinDrvSendEvent()

static void IntWinDrvSendEvent ( KERNEL_DRIVER Driver,
BOOLEAN  Loaded 
)
static

Send a driver loaded/unloaded event.

If INTRO_OPT_EVENT_MODULES is set, the integrator will be notified when a driver has been loaded or unloaded.

Parameters
[in]DriverThe driver that was loaded/unloaded.
[in]LoadedTrue if the driver has been loaded, FALSE otherwise.

Definition at line 30 of file windriver.c.

Referenced by IntWinDrvCreateFromAddress(), and IntWinDrvRemoveFromAddress().

◆ IntWinDrvUnprotect()

INTSTATUS IntWinDrvUnprotect ( KERNEL_DRIVER Driver)

Used to disable protection for the given driver.

Parameters
[in]DriverThe driver to be removed from protection.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the driver is NULL.

Definition at line 1103 of file windriver.c.

Referenced by IntWinDrvRemoveEntry(), and IntWinDrvUpdateProtection().

◆ IntWinDrvUpdateProtection()

INTSTATUS IntWinDrvUpdateProtection ( void  )

Used to update the protection for all the loaded modules (gKernelDrivers).

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1751 of file windriver.c.

Referenced by IntGuestUpdateCoreOptions().

◆ IntWinGetDriverByGva()

static KERNEL_DRIVER* IntWinGetDriverByGva ( QWORD  Rip)
static

Iterates all the loaded drivers to see if the Rip points inside any of them.

Parameters
[in]RipThe RIP to be checked.
Return values
TheKERNEL_DRIVER structure of the originating driver.
NULLif the Rip does NOT points inside a known driver.

Definition at line 1411 of file windriver.c.

Referenced by IntWinDrvHandleRead().

◆ IntWinProtectReadNtEat()

INTSTATUS IntWinProtectReadNtEat ( void  )

Used to place a read hook on the ntoskrnl.exe EAT.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 622 of file windriver.c.

Referenced by IntGuestUpdateCoreOptions(), and IntWinDrvHeadersInMemory().

◆ IntWinUnprotectReadNtEat()

INTSTATUS IntWinUnprotectReadNtEat ( void  )

Used to remove the EAT read hook from ntoskrnl.exe.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 690 of file windriver.c.

Referenced by IntGuestUpdateCoreOptions(), and IntWinDrvForceDisableReadNtEat().

Variable Documentation

◆ gKernelDrivers

LIST_HEAD gKernelDrivers

List of all the drivers currently loaded inside the guest.

Can always be safely used.

Definition at line 11 of file drivers.c.