Bitdefender Hypervisor Memory Introspection
|
#include "drivers.h"
#include "winhal.h"
#include "alerts.h"
#include "decoder.h"
#include "hook.h"
#include "winpe.h"
#include "swapmem.h"
Go to the source code of this file.
Macros | |
#define | HAL_HEAP_PROT_PAGES_EXEC 0x20 |
The number of HAL heap pages to protect against executions. More... | |
#define | MAX_INT_CTRL_COUNT 20 |
#define | MAX_LIST_ITERATIONS_HAL_PERF 20 |
#define | MAX_INSTRUCTIONS_SEARCH 10 |
#define | HAL_HEAP_ORIGINAL 0xFFFFFFFFF0000000 |
#define | MASK_DEVICE_ADDRESS_FEC 0x00000000fec00000 |
#define | MASK_DEVICE_ADDRESS_FED 0x00000000fed00000 |
#define | MASK_DEVICE_ADDRESS_FEE 0x00000000fee00000 |
#define | HAL_HEAP_PHYSICAL_ADDRESS 0x1000 |
Functions | |
static void | IntWinHalSendAlert (EXCEPTION_VICTIM_ZONE const *Victim, EXCEPTION_KM_ORIGINATOR const *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
Sends an introEventEptViolation for HAL alerts. More... | |
static INTSTATUS | IntWinHalHandleHalIntCtrlWrite (KERNEL_DRIVER *Context, HOOK_GPA const *Hook, QWORD Address, INTRO_ACTION *Action) |
Handles writes done over the HAL interrupt controller. More... | |
static INTSTATUS | IntWinHalHandleHalHeapExec (void *Context, HOOK_GPA *Hook, QWORD Address, INTRO_ACTION *Action) |
Handles execution attempts from the HAL heap. More... | |
static INTSTATUS | IntWinHalHandleDispatchTableWrite (PINTEGRITY_REGION IntegrityRegion) |
Handles modifications done to the HAL dispatch table. More... | |
static void | IntWinHalSendPerfCntIntegrityAlert (EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
Sends an introEventIntegrityViolation for detections of writes over HalPerformanceCounter. More... | |
static INTSTATUS | IntWinHalHandlePerfCounterModification (INTEGRITY_REGION *IntegrityRegion) |
Integrity callback for detections of modifications over HalPerformanceCounter. More... | |
INTSTATUS | IntWinHalProtectHalHeapExecs (void) |
Hooks the HAL heap against execution. More... | |
INTSTATUS | IntWinHalUnprotectHalHeapExecs (void) |
Deactivates the HAL heap execution protection. More... | |
INTSTATUS | IntWinHalProtectHalIntCtrl (void) |
Protects the HAL interrupt controller against writes. More... | |
INTSTATUS | IntWinHalUnprotectHalIntCtrl (void) |
Deactivates the HAL interrupt controller write protection. More... | |
INTSTATUS | IntWinHalProtectHalDispatchTable (void) |
Activates the HAL dispatch table protection. More... | |
INTSTATUS | IntWinHalUnprotectHalDispatchTable (void) |
Deactivates the HAL dispatch table protection. More... | |
INTSTATUS | IntWinHalProtectHalPerfCounter (void) |
Enables protection on HalPerformanceCounter function pointer. More... | |
INTSTATUS | IntWinHalUnprotectHalPerfCounter (void) |
Removes the protection on HalPerformanceCounter. More... | |
static BOOLEAN | IntWinHalIsIntController (QWORD CheckedAddress, QWORD HalHeap) |
Checks if a guest memory range is the HAL interrupt controller. More... | |
BOOLEAN | IntWinHalIsHalPerf (QWORD HalPerfCandidate) |
Verifies if the given pointer is the HalPerformanceCounter. More... | |
static INTSTATUS | IntWinHalFindPerformanceCounterInternal (void) |
Finds and protects if needed the HalPerformanceCounter structure. More... | |
static INTSTATUS | IntWinHalFinishRead (void) |
This is the function called when the Hal is completely read. More... | |
static void | IntWinHalCancelRead (void) |
Cancels the Hal module read. More... | |
static INTSTATUS | IntWinHalSectionInMemory (WIN_INIT_SWAP *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags) |
Handles the swap in of a Hal section done while the WIN_HAL_DATA.HalBuffer is read. More... | |
static INTSTATUS | IntWinHalReadHal (void) |
Reads the whole Hal image in memory, including swapped-out sections. More... | |
static INTSTATUS | IntWinHalHeadersInMemory (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags) |
This callback is called as soon as all the HAL headers have been read using IntSwapMemReadData. More... | |
static INTSTATUS | IntWinHalFindPerformanceCounter (void) |
Starts the process of finding the HalPerformanceCounter. More... | |
static INTSTATUS | IntWinHalFindInterruptController (QWORD HalHeap, QWORD HalHeapSize, QWORD *HalInterruptController) |
Attempts to find the Hal Interrupt Controller address within the .data section of Hal. More... | |
static INTSTATUS | IntWinHalFindHalHeapAndInterruptController (QWORD *HalHeapBaseAddress, QWORD *HalInterruptController) |
Attempts to find the Hal Heap and the Hal Interrupt Controller address within the .data section of Hal. More... | |
INTSTATUS | IntWinHalCreateHalData (void) |
Initializes gHalData. More... | |
INTSTATUS | IntWinHalUpdateProtection (void) |
Updates any of the HAL protections. More... | |
void | IntWinHalUninit (void) |
Frees any resources held by gHalData and removes all the HAL protections. More... | |
Variables | |
static WIN_HAL_DATA | gHalData = { 0 } |
The HAL information. More... | |
#define HAL_HEAP_ORIGINAL 0xFFFFFFFFF0000000 |
Referenced by IntWinHalFindHalHeapAndInterruptController().
#define HAL_HEAP_PHYSICAL_ADDRESS 0x1000 |
Referenced by IntWinHalFindHalHeapAndInterruptController().
#define HAL_HEAP_PROT_PAGES_EXEC 0x20 |
The number of HAL heap pages to protect against executions.
Definition at line 13 of file winhal.c.
Referenced by IntWinHalCreateHalData(), and IntWinHalFindHalHeapAndInterruptController().
#define MASK_DEVICE_ADDRESS_FEC 0x00000000fec00000 |
Referenced by IntWinHalFindHalHeapAndInterruptController().
#define MASK_DEVICE_ADDRESS_FED 0x00000000fed00000 |
Referenced by IntWinHalFindHalHeapAndInterruptController().
#define MASK_DEVICE_ADDRESS_FEE 0x00000000fee00000 |
Referenced by IntWinHalFindHalHeapAndInterruptController().
#define MAX_INSTRUCTIONS_SEARCH 10 |
Referenced by IntWinHalFindPerformanceCounterInternal().
#define MAX_INT_CTRL_COUNT 20 |
Referenced by IntWinHalIsIntController().
#define MAX_LIST_ITERATIONS_HAL_PERF 20 |
Referenced by IntWinHalIsHalPerf().
|
static |
Cancels the Hal module read.
This function cancels all the pending page faults that were scheduled in order to read the WIN_HAL_DATA.HalBuffer.
Definition at line 1455 of file winhal.c.
Referenced by IntWinHalUninit().
INTSTATUS IntWinHalCreateHalData | ( | void | ) |
Initializes gHalData.
Will collect the relevant information from the guest and if any of the INTRO_OPT_PROT_KM_HAL_DISP_TABLE, INTRO_OPT_PROT_KM_HAL_HEAP_EXEC, or INTRO_OPT_PROT_KM_HAL_INT_CTRL option is active, will activate the needed protections.
Definition at line 2270 of file winhal.c.
Referenced by IntWinGuestFinishInit().
|
static |
Attempts to find the Hal Heap and the Hal Interrupt Controller address within the .data section of Hal.
On Windows versions newer than RS2 the Hal Hep is randomized using KASLR. Within the .data section of Hal there are 2 variables (HalpHeapStart and HalpOriginalHeapStart) that seem to point to the Hal Heap. This function aims to find the Hal Heap using the following mechanism:
[out] | HalHeapBaseAddress | The Hal Heap address. |
[out] | HalInterruptController | The Hal Interrupt Controller address. |
Definition at line 2058 of file winhal.c.
Referenced by IntWinHalCreateHalData().
|
static |
Attempts to find the Hal Interrupt Controller address within the .data section of Hal.
This functions reads the .data section of the Hal module in order to find the RVA of the Hal Interrupt Controller. Candidate RVAs are verified using IntWinHalIsIntController in order to find the correct address.
[in] | HalHeap | The Hal Heap address. |
[in] | HalHeapSize | The Hal Heap size (may not be the entire Hal Heap). |
[out] | HalInterruptController | The Hal Interrupt Controller address. |
Definition at line 1974 of file winhal.c.
Referenced by IntWinHalCreateHalData(), and IntWinHalFindHalHeapAndInterruptController().
|
static |
Starts the process of finding the HalPerformanceCounter.
On OSes for which the kernel is also the Hal owner, such as 20h1, this function will find synchronously the HalPerformanceCounter structure, as the Hal buffer is equivalent with the already read Kernel Buffer. Otherwise, the searching of HalPerformanceCounter might be asynchronous, as some sections in the Hal module might be swapped out. A call to IntWinHalReadHal will be made in order to read the present sections and inject page faults on the swapped out ones. If no sections are swapped out, then IntWinHalFindPerformanceCounterInternal will be called synchronously in this case too. Otherwise, the protection on HalPerformanceCounter will be initialized only when the paged-out sections are swapped in.
Definition at line 1931 of file winhal.c.
Referenced by IntWinHalCreateHalData().
|
static |
Finds and protects if needed the HalPerformanceCounter structure.
This function will search the HalPerformanceCounter by the following heuristic: Firstly, fetch the KeQueryPerformanceCounter address and decode the first instructions. Among these instructions there should be an instructions of the form "mov reg, [mem]", where the memory should represent either the rip relative address of HalpPerformanceCounter variable on x64, either the absolute address on x86. For the pointer found at that address we call IntWinHalIsHalPerf in order to make additional checks. Note that this function should only be called when all the needed data was already fetched. This means that the Hal module should already be read in HalBuffer from gHalData. For OSes where the NT represent the Hal owner (such as 20h1), reading HalBuffer a priori is not needed.
Definition at line 1280 of file winhal.c.
Referenced by IntWinHalFindPerformanceCounter(), and IntWinHalFinishRead().
|
static |
This is the function called when the Hal is completely read.
Here should be initializations of protections which are dependent on the Hal driver contents. For example, on HalPerformanceCounter protection, we need to fetch the KeQueryPerformanceCounter export from the EAT, and then decode it, thus the whole Hal is needed in order to initialize this protection.
Definition at line 1429 of file winhal.c.
Referenced by IntWinHalReadHal(), and IntWinHalSectionInMemory().
|
static |
Handles modifications done to the HAL dispatch table.
This is the integrity callback set by IntWinHalProtectHalDispatchTable.
[in,out] | IntegrityRegion | The integrity region used to protect the HAL dispatch table. |
Definition at line 377 of file winhal.c.
Referenced by IntWinHalProtectHalDispatchTable().
|
static |
Handles execution attempts from the HAL heap.
This is the EPT hook handler set by IntWinHalProtectHalHeapExecs. If execution comes from a CPU that is in real mode it is allowed, as it will be the result of an IPI sent at boot in order to wake up an AP. If there is an exception for the executed code, the execution is allowed, and the hook will be removed.
[in] | Context | The context set by IntWinHalProtectHalHeapExecs. Ignored. |
[in,out] | Hook | The hook for which this callback was invoked. |
[in] | Address | The accessed physical address. |
[out] | Action | The action to be taken. |
Definition at line 161 of file winhal.c.
Referenced by IntWinHalProtectHalHeapExecs().
|
static |
Handles writes done over the HAL interrupt controller.
This is the EPT write hook set by IntWinHalProtectHalIntCtrl.
[in] | Context | The context set by IntWinHalProtectHalIntCtrl. This will be the hal.dll KERNEL_DRIVER. |
[in] | Hook | The hook for which this callback was invoked. |
[in] | Address | The accessed physical address. |
[out] | Action | The action to be taken. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_INVALID_PARAMETER_1 | if Context is NULL. |
Definition at line 71 of file winhal.c.
Referenced by IntWinHalProtectHalIntCtrl().
|
static |
Integrity callback for detections of modifications over HalPerformanceCounter.
When a modification is detected over HalPerformanceCounter protected area (more specifically, over the protected function which gets called on KeQueryPerformanceCounter) on the timer check, this function will get called. In this function, all the detection logic is made for the HalPerformanceCounter protection, as well as the decision whether this modification is legitimate or not. If the modification is deemed as not legitimate and the policy implies blocking of such attempts, the old value will be overwritten over the modified zone.
[in,out] | IntegrityRegion | The INTEGRITY_REGION describing the protected zone. |
INT_STATUS_SUCCESS | On success. |
Definition at line 623 of file winhal.c.
Referenced by IntWinHalProtectHalPerfCounter().
|
static |
This callback is called as soon as all the HAL headers have been read using IntSwapMemReadData.
[in] | Context | The KERNEL_DRIVER structure. |
[in] | Cr3 | The virtual address space. |
[in] | VirtualAddress | The base virtual address read. |
[in] | PhysicalAddress | The physical address of the first page (VirtualAddress) read. |
[in] | Data | Buffer containing the read data. This will be freed once the callback returns! |
[in] | DataSize | Size of the Data buffer. Will normally be equal to the Length passed to read function. |
[in] | Flags | Swap flags. Check out SWAPMEM_FLG* for more info. |
INT_STATUS_SUCCESS | On success. |
Definition at line 1877 of file winhal.c.
Referenced by IntWinHalFindPerformanceCounter().
Verifies if the given pointer is the HalPerformanceCounter.
The checks done on the given pointer are:
Definition at line 1196 of file winhal.c.
Referenced by IntWinHalFindPerformanceCounterInternal().
Checks if a guest memory range is the HAL interrupt controller.
The check is done based on invariants:
[in] | CheckedAddress | The guest virtual address to check. |
[in] | HalHeap | The Hal Heap address. |
Definition at line 1068 of file winhal.c.
Referenced by IntWinHalFindInterruptController().
INTSTATUS IntWinHalProtectHalDispatchTable | ( | void | ) |
Activates the HAL dispatch table protection.
Will set IntWinHalHandleDispatchTableWrite as the EPT hook handler.
Definition at line 914 of file winhal.c.
Referenced by IntWinHalCreateHalData(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalProtectHalHeapExecs | ( | void | ) |
Hooks the HAL heap against execution.
This will protect the first 16 pages from the HAL heap. Based on the Windows version, some of them already have the NX bit set inside the guest page tables. IntWinHalHandleHalHeapExec will be set as the EPT hook handler. Pages that translate to physical address 0 or that are not present are not hooked.
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_ALREADY_INITIALIZED_HINT | if the HAL heap is already protected. |
INT_STATUS_NOT_NEEDED_HINT | if the HAL heap is not yet initialized. |
Definition at line 718 of file winhal.c.
Referenced by IntWinHalCreateHalData(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalProtectHalIntCtrl | ( | void | ) |
Protects the HAL interrupt controller against writes.
Will set IntWinHalHandleHalIntCtrlWrite as the EPT hook callback.
Definition at line 837 of file winhal.c.
Referenced by IntWinHalCreateHalData(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalProtectHalPerfCounter | ( | void | ) |
Enables protection on HalPerformanceCounter function pointer.
The protected region contains the function which is called when KeQueryPerformanceCounter gets called inside the guest OS.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_ALREADY_INITIALIZED_HINT | If the protection is already initialized. |
INT_STATUS_NOT_INITIALIZED_HINT | If the HalPerformanceCounter has not yet been found. |
Definition at line 989 of file winhal.c.
Referenced by IntWinHalFindPerformanceCounterInternal(), and IntWinHalUpdateProtection().
|
static |
Reads the whole Hal image in memory, including swapped-out sections.
This will allocate and fill WIN_HAL_DATA.HalBuffer. For the swapped-out sections, IntSwapMemRead will be used with IntWinHalSectionInMemory as the swap-in handler. Discardable sections will be filled with 0, as those can not be brought back into memory. If all the sections are already present in memory, this function will try to initialize the protections which rely on the Hal module, by calling IntWinHalFinishRead. If not, this step is left to the last invocation of the IntWinHalSectionInMemory callback. Once IntWinHalFinishRead is called the Hal buffer can be safely used.
INT_STATUS_SUCCESS | in case of success. Note that even if this function exits with a success status, the hal buffer is not necessarily valid yet, as parts of it may be read in an asynchronous manner. |
INT_STATUS_INVALID_OBJECT_TYPE | if the MZPE validation of the headers fails. |
INT_STATUS_NOT_SUPPORTED | if a section header can not be parsed. |
INT_STATUS_INSUFFICIENT_RESOURCES | if not enough memory is available. |
INT_STATUS_INVALID_INTERNAL_STATE | if an internal error is encountered. |
Definition at line 1593 of file winhal.c.
Referenced by IntWinHalFindPerformanceCounter(), and IntWinHalHeadersInMemory().
|
static |
Handles the swap in of a Hal section done while the WIN_HAL_DATA.HalBuffer is read.
This is the IntSwapMemRead handler set by IntWinHalReadHal that will read a Hal section into the Hal buffer. It will set the appropriate part of the WIN_HAL_DATA.HalBuffer with the data obtained from the guest and will decrement the WIN_HAL_DATA.RemainingSections counter. It will also remove Context from the WIN_HAL_DATA.InitSwapHandles list and will free it.
[in] | Context | The init swap handle used for this section |
[in] | Cr3 | Ignored |
[in] | VirtualAddress | Ignored |
[in] | PhysicalAddress | Ignored |
[in] | Data | The data read from the Hal |
[in] | DataSize | The size of the Data buffer |
[in] | Flags | A combination of flags describing the way in which the data was read. This function checks only for the SWAPMEM_FLAG_ASYNC_CALL flag. If it is present, it means that it was invoked asynchronously, in which case it will pause the VCPUs in order to ensure consistency of the data. If the WIN_HAL_DATA.RemainingSections is set to 0 by this callback while SWAPMEM_FLAG_ASYNC_CALL is set, it will also initialize the protections that rely on the Hal module, by calling IntWinHalFinishRead. |
Definition at line 1505 of file winhal.c.
Referenced by IntWinHalReadHal().
|
static |
Sends an introEventEptViolation for HAL alerts.
[in] | Victim | Victim information. |
[in] | Originator | Originator information. |
[in] | Action | The action taken. |
[in] | Reason | The reason for which Action was taken. |
Definition at line 20 of file winhal.c.
Referenced by IntWinHalHandleHalIntCtrlWrite().
|
static |
Sends an introEventIntegrityViolation for detections of writes over HalPerformanceCounter.
[in] | Victim | Victim information. |
[in] | Originator | Originator information. |
[in] | Action | The action taken. |
[in] | Reason | The reason for which Action was taken. |
Definition at line 557 of file winhal.c.
Referenced by IntWinHalHandlePerfCounterModification().
void IntWinHalUninit | ( | void | ) |
Frees any resources held by gHalData and removes all the HAL protections.
Definition at line 2479 of file winhal.c.
Referenced by IntWinGuestUninit().
INTSTATUS IntWinHalUnprotectHalDispatchTable | ( | void | ) |
Deactivates the HAL dispatch table protection.
Definition at line 957 of file winhal.c.
Referenced by IntWinHalUninit(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalUnprotectHalHeapExecs | ( | void | ) |
Deactivates the HAL heap execution protection.
Definition at line 812 of file winhal.c.
Referenced by IntWinHalUninit(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalUnprotectHalIntCtrl | ( | void | ) |
Deactivates the HAL interrupt controller write protection.
Definition at line 889 of file winhal.c.
Referenced by IntWinHalUninit(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalUnprotectHalPerfCounter | ( | void | ) |
Removes the protection on HalPerformanceCounter.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED_HINT | If the protection was not enabled beforehand. |
Definition at line 1035 of file winhal.c.
Referenced by IntWinHalUninit(), and IntWinHalUpdateProtection().
INTSTATUS IntWinHalUpdateProtection | ( | void | ) |
Updates any of the HAL protections.
If any of the INTRO_OPT_PROT_KM_HAL_DISP_TABLE, INTRO_OPT_PROT_KM_HAL_HEAP_EXEC, or INTRO_OPT_PROT_KM_HAL_INT_CTRL option is changed, the protection is enabled, or disabled, based on the new value.
Definition at line 2405 of file winhal.c.
Referenced by IntGuestUpdateCoreOptions().
|
static |