Bitdefender Hypervisor Memory Introspection
lixmodule.c File Reference
#include "lixmodule.h"
#include "alerts.h"
#include "crc32.h"
#include "decoder.h"
#include "hook.h"
#include "lixksym.h"

Go to the source code of this file.

Macros

#define LIX_MODULE_MAP_START   0xffffffffa0000000
 Module mapping space, as defined by linux kernel (mm.txt) More...
 
#define LIX_MODULE_MAP_END   0xfffffffffeffffff
 
#define LIX_MODULE_MAX_ITERATIONS   4096
 

Typedefs

typedef enum _MODULE_STATE MODULE_STATE
 The state of a kernel module. More...
 

Enumerations

enum  _MODULE_STATE { moduleStateLive = 0, moduleStateComing, moduleStateGoing, moduleStateUnformed }
 The state of a kernel module. More...
 

Functions

static INTSTATUS IntLixDrvValidate (QWORD Driver)
 Validates if the provided driver with the provided address is valid. More...
 
static INTSTATUS IntLixDrvActivateProtection (KERNEL_DRIVER *Driver)
 Activates protection for the provided driver. More...
 
static void IntLixDrvDeactivateProtection (KERNEL_DRIVER *Driver)
 Disable protection for the provided driver. More...
 
INTSTATUS IntLixDrvFindList (QWORD *Drivers)
 Searches the Linux kernel for the 'modules' variable. More...
 
static INTSTATUS IntLixDrvInitVfreeHandler (void *Context, QWORD VirtualAddress, QWORD OldEntry, QWORD NewEntry, QWORD OldPageSize, QWORD NewPageSize)
 This function is called when the init section of the driver is freed. More...
 
static INTSTATUS IntLixDrvSendEvent (KERNEL_DRIVER *Driver, BOOLEAN Loaded, BOOLEAN StaticDetected)
 Send an event to the integrator that contains the information about the provided driver. More...
 
void IntLixDrvUpdateProtection (void)
 Update Linux drivers protection according to the new core options. More...
 
static void IntLixDrvRemoveDuplicate (QWORD DriverGva)
 Removes the driver with the provided guest virtual address if exists in our list. More...
 
static INTSTATUS IntLixDrvCreateDriverObject (QWORD DriverGva, KERNEL_DRIVER **Object)
 Create a KERNEL_DRIVER object that contains the information found at the address of the 'struct module'. More...
 
static BOOLEAN IntLixDrvIsActivePatch (QWORD Gva)
 Checks if the provided guest virtual address is inside an active-patch range. More...
 
INTSTATUS IntLixDrvCreateFromAddress (QWORD DriverGva, QWORD StaticDetected)
 Create the KERNEL_DRIVER object from the provided 'module struct' address and activate the protection for it. More...
 
INTSTATUS IntLixDrvRemoveEntry (KERNEL_DRIVER *Driver)
 Disable protection and frees the driver structure from our internal list. More...
 
INTSTATUS IntLixDrvRemoveFromAddress (QWORD DriverGva)
 Disable protection and remove the driver structure from our internal list. More...
 
void IntLixDrvGetSecName (KERNEL_DRIVER *Driver, QWORD Gva, CHAR *SectionName)
 Get the section of the driver that contains the provided guest virtual address. More...
 
INTSTATUS IntLixDrvIsLegitimateTextPoke (void *Hook, QWORD Address, LIX_ACTIVE_PATCH *ActivePatch, INTRO_ACTION *Action)
 This function checks if the modified zone by the current instruction is a 'text_poke'. More...
 
static void IntLixDrvSendViolationEvent (KERNEL_DRIVER *Driver, EXCEPTION_KM_ORIGINATOR *Originator, EXCEPTION_VICTIM_ZONE *Victim, HOOK_GPA *Hook, QWORD Address, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
 Sends an introEventEptViolation event for a protected kernel module. More...
 
static BOOLEAN IntLixDrvSystemBooting (void)
 Checks if the system is booting. More...
 
INTSTATUS IntLixDrvHandleWrite (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Called if an write occurs on the protected memory zone. More...
 
INTSTATUS IntLixDrvIterateList (PFUNC_IterateListCallback Callback, QWORD Aux)
 Iterates the 'modules' list form the guest and activate protection for each driver that is initialized. More...
 
INTSTATUS IntLixDrvCreateKernel (void)
 Create the KERNEL_DRIVER object for the operating system kernel and activate the protection for it. More...
 

Variables

LIST_HEAD gKernelDrivers
 List of all the drivers currently loaded inside the guest. More...
 
DWORD gModuleIgnore = 0
 Used to count the modules that are unloading. More...
 

Macro Definition Documentation

◆ LIX_MODULE_MAP_END

#define LIX_MODULE_MAP_END   0xfffffffffeffffff

Definition at line 40 of file lixmodule.c.

Referenced by IntLixDrvFindList(), and IntLixDrvValidate().

◆ LIX_MODULE_MAP_START

#define LIX_MODULE_MAP_START   0xffffffffa0000000

Module mapping space, as defined by linux kernel (mm.txt)

Definition at line 39 of file lixmodule.c.

Referenced by IntLixDrvValidate().

◆ LIX_MODULE_MAX_ITERATIONS

#define LIX_MODULE_MAX_ITERATIONS   4096

Definition at line 42 of file lixmodule.c.

Referenced by IntLixDrvIterateList().

Typedef Documentation

◆ MODULE_STATE

The state of a kernel module.

Enumeration Type Documentation

◆ _MODULE_STATE

The state of a kernel module.

Enumerator
moduleStateLive 

The module is running.

moduleStateComing 

The module is full formed, running module_init.

moduleStateGoing 

The module is going away.

moduleStateUnformed 

The module is still setting it up.

Definition at line 27 of file lixmodule.c.

Function Documentation

◆ IntLixDrvActivateProtection()

static INTSTATUS IntLixDrvActivateProtection ( KERNEL_DRIVER Driver)
static

Activates protection for the provided driver.

This function activates protection only if the guest options has the INTRO_OPT_PROT_KM_LX_MODULES flag. The driver's '.rodata' section is protected against write using an EPT hook.

Parameters
[in]DriverThe internal structure of the driver.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the driver is not initialized yet.
INT_STATUS_ALREADY_INITIALIZED_HINTIf the driver is already protected.

Definition at line 144 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress(), IntLixDrvInitVfreeHandler(), and IntLixDrvUpdateProtection().

◆ IntLixDrvCreateDriverObject()

static INTSTATUS IntLixDrvCreateDriverObject ( QWORD  DriverGva,
KERNEL_DRIVER **  Object 
)
static

Create a KERNEL_DRIVER object that contains the information found at the address of the 'struct module'.

Parameters
[in]DriverGvaThe address of the 'struct module'.
[out]ObjectThe KERNEL_DRIVER object to be created.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf the HpAllocWithTag fails.

Definition at line 558 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress().

◆ IntLixDrvCreateFromAddress()

INTSTATUS IntLixDrvCreateFromAddress ( QWORD  DriverGva,
QWORD  StaticDetected 
)

Create the KERNEL_DRIVER object from the provided 'module struct' address and activate the protection for it.

This function calls '_IntLixDrvRemoveDuplicate' to check if the provided drivers already exists in out list. If the driver is found, it is delete and an event is sent to the integrator. The function reads the vale of the 'enum module_state' in order to check if the driver should be protected and added to out list. The 'module_state' has one of the following value:

  • LIVE/COMMING: the driver runs and it should be protected
  • GOING: the driver is dying and it should not be protected
  • UNFORMED: the driver is setting up and it should not be protected yet because it will be protected when the 'module_sysfs_param_setup' is called. If the driver has a valid 'init' section, the page-table of the init section is hooked to know when the section is freed; when the hook-callback is called the driver is initialized and it can be protected (valid only for dynamic driver initialization).
Parameters
[in]DriverGvaThe address of the 'struct module'.
[in]StaticDetectedTrue if the driver is static detected, otherwise false
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf the IDT of the provided CPU is not initialized.

Definition at line 696 of file lixmodule.c.

Referenced by IntDriverLoadHandler(), and IntLixGuestInitAgentCompletion().

◆ IntLixDrvCreateKernel()

INTSTATUS IntLixDrvCreateKernel ( void  )

Create the KERNEL_DRIVER object for the operating system kernel and activate the protection for it.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf the HpAllocWithTag fails.

Definition at line 1452 of file lixmodule.c.

Referenced by IntLixGuestInit().

◆ IntLixDrvDeactivateProtection()

static void IntLixDrvDeactivateProtection ( KERNEL_DRIVER Driver)
static

Disable protection for the provided driver.

This function removes the EPT write-hooks from '.rodata' section of the driver.

Parameters
[in]DriverThe internal structure of the driver.

Definition at line 214 of file lixmodule.c.

Referenced by IntLixDrvRemoveEntry(), and IntLixDrvUpdateProtection().

◆ IntLixDrvFindList()

INTSTATUS IntLixDrvFindList ( QWORD Drivers)

Searches the Linux kernel for the 'modules' variable.

This variable it's declared as static inside 'module.c', so we can't find it in kallsyms. Note: Only call this on the static initialization.

Parameters
[out]DriversContains the guest virtual address of 'struct module *modules'.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'modules' variable is not found.

Definition at line 244 of file lixmodule.c.

Referenced by IntLixDrvIterateList().

◆ IntLixDrvGetSecName()

void IntLixDrvGetSecName ( KERNEL_DRIVER Driver,
QWORD  Gva,
CHAR SectionName 
)

Get the section of the driver that contains the provided guest virtual address.

If the guest virtual address not belong to any section the 'unknown' string is returned.

Parameters
[in]DriverThe internal driver structure.
[in]GvaThe guest virtual address that belong to a section.
[out]SectionNameA string that contains the name of the section, if any.

Definition at line 913 of file lixmodule.c.

Referenced by IntExceptLixKernelGetOriginator(), IntLixDrvSendViolationEvent(), and IntLixKernelHandleRead().

◆ IntLixDrvHandleWrite()

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

Called if an write occurs on the protected memory zone.

This function checks if the write comes from a 'text_poke' or the write occurs when the system is booting. If these checks fails, the exception mechanism is used to decide if the write should be allowed.

Parameters
[in]ContextThe context provided by the caller; in our case is the driver object.
[in]HookThe GPA hook associated to this callback.
[in]AddressThe GPA address that was accessed.
[out]ActionThe action that must be taken.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the provided Context is null.
INT_STATUS_INVALID_PARAMETER_2If the provided Hook is null.
INT_STATUS_INVALID_PARAMETER_4If the provided Action is null.

Definition at line 1236 of file lixmodule.c.

Referenced by IntLixDrvActivateProtection(), and IntLixHookKernelWrite().

◆ IntLixDrvInitVfreeHandler()

static INTSTATUS IntLixDrvInitVfreeHandler ( void *  Context,
QWORD  VirtualAddress,
QWORD  OldEntry,
QWORD  NewEntry,
QWORD  OldPageSize,
QWORD  NewPageSize 
)
static

This function is called when the init section of the driver is freed.

The page-table of the 'init' section of the driver is hooked to know when it's freed. After the 'init' section is freed the driver is fully initialized and we can hook the '.rodata' against write.

Parameters
[in]ContextThe internal structure of the driver.
[in]VirtualAddressUnused.
[in]OldEntryThe old page-table entry.
[in]NewEntryThe new page-table entry.
[in]OldPageSizeUnused.
[in]NewPageSizeUnused.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_REMOVE_HOOK_ON_RETIf fails to remove the init section's hook

Definition at line 372 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress().

◆ IntLixDrvIsActivePatch()

static BOOLEAN IntLixDrvIsActivePatch ( QWORD  Gva)
static

Checks if the provided guest virtual address is inside an active-patch range.

Parameters
[in]GvaThe guest virtual address to be checked.
Return values
True,ifthe guest virtual address is inside an active-patch range, otherwise false.

Definition at line 672 of file lixmodule.c.

Referenced by IntLixDrvHandleWrite().

◆ IntLixDrvIsLegitimateTextPoke()

INTSTATUS IntLixDrvIsLegitimateTextPoke ( void *  Hook,
QWORD  Address,
LIX_ACTIVE_PATCH ActivePatch,
INTRO_ACTION Action 
)

This function checks if the modified zone by the current instruction is a 'text_poke'.

This function get the modified memory from the instruction operand and check if it match with the last active-patch information fetched from the 'text_poke' detour.

Parameters
[in]HookThe hook object.
[in]AddressThe modified address.
[in]ActivePatchThe active patch that modified the protected memory zone.
[out]ActionThe action that must be taken.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the provided Hook is null.
INT_STATUS_INVALID_PARAMETER_3If the provided Action is null.
INT_STATUS_NOT_SUPPORTEDIf the modified guest virtual address is not in our active-patch range.

Definition at line 980 of file lixmodule.c.

Referenced by IntDetHandleWrite(), and IntLixDrvHandleWrite().

◆ IntLixDrvIterateList()

INTSTATUS IntLixDrvIterateList ( PFUNC_IterateListCallback  Callback,
QWORD  Aux 
)

Iterates the 'modules' list form the guest and activate protection for each driver that is initialized.

Parameters
[in]CallbackThe callback that will be called for each found driver.
[in]AuxThe auxiliary parameter (StaticDetection) passed to the callback.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the provided callback is invalid.
INT_STATUS_NOT_FOUNDIf the 'modules' list is not found.
INT_STATUS_NOT_INITIALIZED_HINTIf the 'modules' list is empty.
INT_STATUS_NOT_SUPPORTEDIf the number of the drivers exceed the LIX_MODULE_MAX_ITERATIONS limit.

Definition at line 1364 of file lixmodule.c.

Referenced by IntLixGuestInitAgentCompletion().

◆ IntLixDrvRemoveDuplicate()

static void IntLixDrvRemoveDuplicate ( QWORD  DriverGva)
static

Removes the driver with the provided guest virtual address if exists in our list.

This function is used only for dynamic detection because we can race with the guest. A race condition with the guest is possible because we scan the 'modules' list from the guest and hook the 'module_param_sysfs_setup' that is called after the drivers is added to the 'modules' list. If we scan the 'modules' list when a driver is loading there's chance to add the same driver to out list.

Parameters
[in]DriverGvaThe address of the 'struct module'.

Definition at line 514 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress().

◆ IntLixDrvRemoveEntry()

INTSTATUS IntLixDrvRemoveEntry ( KERNEL_DRIVER Driver)

Disable protection and frees the driver structure from our internal list.

If the swap-mem hook on the init section is enabled, the function will disable it.

Parameters
[in]DriverThe internal driver structure.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the parameter is invalid.

Definition at line 828 of file lixmodule.c.

Referenced by IntDriverUninit(), IntLixDrvRemoveDuplicate(), and IntLixDrvRemoveFromAddress().

◆ IntLixDrvRemoveFromAddress()

INTSTATUS IntLixDrvRemoveFromAddress ( QWORD  DriverGva)

Disable protection and remove the driver structure from our internal list.

If the swap-mem hook on the init section is enabled, the function will disable it.

Parameters
[in]DriverGvaThe internal driver structure
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 866 of file lixmodule.c.

Referenced by IntDriverUnloadHandler().

◆ IntLixDrvSendEvent()

static INTSTATUS IntLixDrvSendEvent ( KERNEL_DRIVER Driver,
BOOLEAN  Loaded,
BOOLEAN  StaticDetected 
)
static

Send an event to the integrator that contains the information about the provided driver.

Parameters
[in]DriverThe internal structure of the driver.
[in]LoadedTrue if the driver object is created, otherwise false.
[in]StaticDetectedTrue if the driver is static detected, otherwise false.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the core options INTRO_OPT_EVENT_MODULES is not set.

Definition at line 435 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress(), IntLixDrvRemoveDuplicate(), and IntLixDrvRemoveFromAddress().

◆ IntLixDrvSendViolationEvent()

static void IntLixDrvSendViolationEvent ( KERNEL_DRIVER Driver,
EXCEPTION_KM_ORIGINATOR Originator,
EXCEPTION_VICTIM_ZONE Victim,
HOOK_GPA Hook,
QWORD  Address,
INTRO_ACTION  Action,
INTRO_ACTION_REASON  Reason 
)
static

Sends an introEventEptViolation event for a protected kernel module.

Parameters
[in]DriverThe KERNEL_DRIVER object.
[in]VictimThe victim information, as obtained from the exception mechanism.
[in]OriginatorThe originator information, as obtained from the exception mechanism.
[in]HookThe GPA hook associated to this callback.
[in]AddressThe GPA address that was accessed.
[in]ActionThe action that was taken.
[in]ReasonThe reason for which Action was taken.

Definition at line 1119 of file lixmodule.c.

Referenced by IntLixDrvHandleWrite().

◆ IntLixDrvSystemBooting()

static BOOLEAN IntLixDrvSystemBooting ( void  )
static

Checks if the system is booting.

Return values
True,ifthe system is booting, otherwise false.

Definition at line 1206 of file lixmodule.c.

Referenced by IntLixDrvHandleWrite().

◆ IntLixDrvUpdateProtection()

void IntLixDrvUpdateProtection ( void  )

Update Linux drivers protection according to the new core options.

Definition at line 487 of file lixmodule.c.

Referenced by IntGuestUpdateCoreOptions().

◆ IntLixDrvValidate()

static INTSTATUS IntLixDrvValidate ( QWORD  Driver)
static

Validates if the provided driver with the provided address is valid.

This function performs the following checks:

  • the state is one of the four values in 'enum module_state';
  • the name is a string; at least one character and at maxim length of LIX_MODULE_NAME_LENGTH;
  • the layout values are in range [LIX_MODULE_MAP_START, LIX_MODULE_MAP_END];
  • the size don't exceed the end of modules mapping;
Parameters
[in]DriverThe guest virtual address of the 'struct module'.
Return values
INT_STATUS_SUCCESSIf the driver is valid.
INT_STATUS_INVALID_OBJECT_TYPEIf the driver is invalid.

Definition at line 46 of file lixmodule.c.

Referenced by IntLixDrvFindList().

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.

◆ gModuleIgnore

DWORD gModuleIgnore = 0

Used to count the modules that are unloading.

Definition at line 21 of file lixmodule.c.

Referenced by IntLixDrvCreateFromAddress(), and IntLixDrvRemoveFromAddress().