Bitdefender Hypervisor Memory Introspection
|
#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... | |
#define LIX_MODULE_MAP_END 0xfffffffffeffffff |
Definition at line 40 of file lixmodule.c.
Referenced by IntLixDrvFindList(), and IntLixDrvValidate().
#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().
#define LIX_MODULE_MAX_ITERATIONS 4096 |
Definition at line 42 of file lixmodule.c.
Referenced by IntLixDrvIterateList().
typedef enum _MODULE_STATE MODULE_STATE |
The state of a kernel module.
enum _MODULE_STATE |
The state of a kernel module.
Definition at line 27 of file lixmodule.c.
|
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.
[in] | Driver | The internal structure of the driver. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED_HINT | If the driver is not initialized yet. |
INT_STATUS_ALREADY_INITIALIZED_HINT | If the driver is already protected. |
Definition at line 144 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress(), IntLixDrvInitVfreeHandler(), and IntLixDrvUpdateProtection().
|
static |
Create a KERNEL_DRIVER object that contains the information found at the address of the 'struct module'.
[in] | DriverGva | The address of the 'struct module'. |
[out] | Object | The KERNEL_DRIVER object to be created. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INSUFFICIENT_RESOURCES | If the HpAllocWithTag fails. |
Definition at line 558 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress().
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:
[in] | DriverGva | The address of the 'struct module'. |
[in] | StaticDetected | True if the driver is static detected, otherwise false |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED | If the IDT of the provided CPU is not initialized. |
Definition at line 696 of file lixmodule.c.
Referenced by IntDriverLoadHandler(), and IntLixGuestInitAgentCompletion().
INTSTATUS IntLixDrvCreateKernel | ( | void | ) |
Create the KERNEL_DRIVER object for the operating system kernel and activate the protection for it.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INSUFFICIENT_RESOURCES | If the HpAllocWithTag fails. |
Definition at line 1452 of file lixmodule.c.
Referenced by IntLixGuestInit().
|
static |
Disable protection for the provided driver.
This function removes the EPT write-hooks from '.rodata' section of the driver.
[in] | Driver | The internal structure of the driver. |
Definition at line 214 of file lixmodule.c.
Referenced by IntLixDrvRemoveEntry(), and IntLixDrvUpdateProtection().
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.
[out] | Drivers | Contains the guest virtual address of 'struct module *modules'. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_FOUND | If the 'modules' variable is not found. |
Definition at line 244 of file lixmodule.c.
Referenced by IntLixDrvIterateList().
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.
[in] | Driver | The internal driver structure. |
[in] | Gva | The guest virtual address that belong to a section. |
[out] | SectionName | A string that contains the name of the section, if any. |
Definition at line 913 of file lixmodule.c.
Referenced by IntExceptLixKernelGetOriginator(), IntLixDrvSendViolationEvent(), and IntLixKernelHandleRead().
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.
[in] | Context | The context provided by the caller; in our case is the driver object. |
[in] | Hook | The GPA hook associated to this callback. |
[in] | Address | The GPA address that was accessed. |
[out] | Action | The action that must be taken. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER_1 | If the provided Context is null. |
INT_STATUS_INVALID_PARAMETER_2 | If the provided Hook is null. |
INT_STATUS_INVALID_PARAMETER_4 | If the provided Action is null. |
Definition at line 1236 of file lixmodule.c.
Referenced by IntLixDrvActivateProtection(), and IntLixHookKernelWrite().
|
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.
[in] | Context | The internal structure of the driver. |
[in] | VirtualAddress | Unused. |
[in] | OldEntry | The old page-table entry. |
[in] | NewEntry | The new page-table entry. |
[in] | OldPageSize | Unused. |
[in] | NewPageSize | Unused. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_REMOVE_HOOK_ON_RET | If fails to remove the init section's hook |
Definition at line 372 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress().
Checks if the provided guest virtual address is inside an active-patch range.
[in] | Gva | The guest virtual address to be checked. |
True,if | the guest virtual address is inside an active-patch range, otherwise false. |
Definition at line 672 of file lixmodule.c.
Referenced by IntLixDrvHandleWrite().
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.
[in] | Hook | The hook object. |
[in] | Address | The modified address. |
[in] | ActivePatch | The active patch that modified the protected memory zone. |
[out] | Action | The action that must be taken. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER_1 | If the provided Hook is null. |
INT_STATUS_INVALID_PARAMETER_3 | If the provided Action is null. |
INT_STATUS_NOT_SUPPORTED | If 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().
INTSTATUS IntLixDrvIterateList | ( | PFUNC_IterateListCallback | Callback, |
QWORD | Aux | ||
) |
Iterates the 'modules' list form the guest and activate protection for each driver that is initialized.
[in] | Callback | The callback that will be called for each found driver. |
[in] | Aux | The auxiliary parameter (StaticDetection) passed to the callback. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER_1 | If the provided callback is invalid. |
INT_STATUS_NOT_FOUND | If the 'modules' list is not found. |
INT_STATUS_NOT_INITIALIZED_HINT | If the 'modules' list is empty. |
INT_STATUS_NOT_SUPPORTED | If the number of the drivers exceed the LIX_MODULE_MAX_ITERATIONS limit. |
Definition at line 1364 of file lixmodule.c.
Referenced by IntLixGuestInitAgentCompletion().
|
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.
[in] | DriverGva | The address of the 'struct module'. |
Definition at line 514 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress().
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.
[in] | Driver | The internal driver structure. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER_1 | If the parameter is invalid. |
Definition at line 828 of file lixmodule.c.
Referenced by IntDriverUninit(), IntLixDrvRemoveDuplicate(), and IntLixDrvRemoveFromAddress().
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.
[in] | DriverGva | The internal driver structure |
INT_STATUS_SUCCESS | On success. |
Definition at line 866 of file lixmodule.c.
Referenced by IntDriverUnloadHandler().
|
static |
Send an event to the integrator that contains the information about the provided driver.
[in] | Driver | The internal structure of the driver. |
[in] | Loaded | True if the driver object is created, otherwise false. |
[in] | StaticDetected | True if the driver is static detected, otherwise false. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_NEEDED_HINT | If the core options INTRO_OPT_EVENT_MODULES is not set. |
Definition at line 435 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress(), IntLixDrvRemoveDuplicate(), and IntLixDrvRemoveFromAddress().
|
static |
Sends an introEventEptViolation event for a protected kernel module.
[in] | Driver | The KERNEL_DRIVER object. |
[in] | Victim | The victim information, as obtained from the exception mechanism. |
[in] | Originator | The originator information, as obtained from the exception mechanism. |
[in] | Hook | The GPA hook associated to this callback. |
[in] | Address | The GPA address that was accessed. |
[in] | Action | The action that was taken. |
[in] | Reason | The reason for which Action was taken. |
Definition at line 1119 of file lixmodule.c.
Referenced by IntLixDrvHandleWrite().
|
static |
Checks if the system is booting.
True,if | the system is booting, otherwise false. |
Definition at line 1206 of file lixmodule.c.
Referenced by IntLixDrvHandleWrite().
void IntLixDrvUpdateProtection | ( | void | ) |
Update Linux drivers protection according to the new core options.
Definition at line 487 of file lixmodule.c.
Referenced by IntGuestUpdateCoreOptions().
Validates if the provided driver with the provided address is valid.
This function performs the following checks:
[in] | Driver | The guest virtual address of the 'struct module'. |
INT_STATUS_SUCCESS | If the driver is valid. |
INT_STATUS_INVALID_OBJECT_TYPE | If the driver is invalid. |
Definition at line 46 of file lixmodule.c.
Referenced by IntLixDrvFindList().
LIST_HEAD gKernelDrivers |
DWORD gModuleIgnore = 0 |
Used to count the modules that are unloading.
Definition at line 21 of file lixmodule.c.
Referenced by IntLixDrvCreateFromAddress(), and IntLixDrvRemoveFromAddress().