Bitdefender Hypervisor Memory Introspection
|
Handles violations involving the SharedUserData structure. More...
#include "winsud.h"
#include "hook.h"
#include "exceptions.h"
#include "alerts.h"
#include "winthread.h"
#include "winprocesshp.h"
#include "crc32.h"
#include "utils.h"
Go to the source code of this file.
Data Structures | |
struct | _SHARED_USER_DATA_PROT_FIELD |
Describes a field from KUSER_SHARED_DATA which is protected through integrity. More... | |
Typedefs | |
typedef struct _SHARED_USER_DATA_PROT_FIELD | SHARED_USER_DATA_PROT_FIELD |
Describes a field from KUSER_SHARED_DATA which is protected through integrity. More... | |
typedef struct _SHARED_USER_DATA_PROT_FIELD * | PSHARED_USER_DATA_PROT_FIELD |
Functions | |
static void | IntWinSudSendSudExecAlert (void *Originator, EXCEPTION_VICTIM_ZONE *Victim, BOOLEAN IsKernel, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
Constructs and sends an EVENT_EPT_VIOLATION alert which occurred due to an execution in SharedUserData. More... | |
static INTSTATUS | IntWinSudHandleKernelSudExec (QWORD Address, INTRO_ACTION *Action) |
Handles a kernel mode execution inside SharedUserData. More... | |
static INTSTATUS | IntWinSudHandleUserSudExec (QWORD Address, INTRO_ACTION *Action) |
Handles an user-mode execution inside SharedUserData. More... | |
static INTSTATUS | IntWinSudHandleSudExec (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action) |
Ept callback which handles executions inside SharedUserData. More... | |
INTSTATUS | IntWinSudProtectSudExec (void) |
Protects SharedUserData against executions by establishing an EPT hook on it. More... | |
INTSTATUS | IntWinSudUnprotectSudExec (void) |
Removes the execution EPT hook on SharedUserData. More... | |
static BOOLEAN | IntWinSudFetchFieldCurrentValue (SHARED_USER_DATA_PROT_FIELD *Field, QWORD *CurrentValue) |
Fetches the value of the given described field from the global SharedUserData buffer. More... | |
static void | IntWinSudSendSudIntegrityAlert (EXCEPTION_VICTIM_ZONE *Victim, SHARED_USER_DATA_PROT_FIELD *Field, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
Completes and sends an alert for a detected SharedUserData modification on a monitored field. More... | |
static INTSTATUS | IntWinSudHandleFieldModification (SHARED_USER_DATA_PROT_FIELD *Field, QWORD NewValue) |
This function is called when a modification has been detected on a given field in order to take a decision on the current modification. More... | |
TIMER_FRIENDLY INTSTATUS | IntWinSudCheckIntegrity (void) |
This function checks the integrity of protected fields from SharedUserData, described in gProtFields. More... | |
INTSTATUS | IntWinSudProtectIntegrity (void) |
Initializes the SharedUserData integrity protection. More... | |
INTSTATUS | IntWinSudUnprotectIntegrity (void) |
Uninitializes the SharedUserData integrity protection. More... | |
Variables | |
static HOOK_GVA * | gSudExecHook = NULL |
The hook object protecting against executions on SharedUserData. More... | |
static BYTE * | gSudBuffer = NULL |
Buffer for fast accessing the current contents of SharedUserData. More... | |
static BOOLEAN | gSudIntegrityInitialized = FALSE |
Is set to true when integrity is initialized on SharedUserData signaling that checks can be performed. More... | |
SHARED_USER_DATA_PROT_FIELD | gProtFields [] |
Global array containing the descriptors used for protecting fields inside SharedUserData. More... | |
Handles violations involving the SharedUserData structure.
The SharedUserData structure (nt!KUSER_SHARED_DATA) contains various system specific data that is shared between the kernel and all the processes running on the system. In kernel mode it is hardcoded to 0xFFFFF78000000000 on x64, or 0xFFDF0000 on x86, while in user mode it is always mapped to 0x7FFE0000. The shared page is writable only from kernel mode and is not executable, but by changing the rights from the page table hierarchy, one can execute from inside this page. Since the page is hardcoded, one can leverage an arbitrary write vulnerability in order to place a shellcode after the SharedUserData structure, leading to a Remote Code Execution. Moreover, since the page is mapped in all processes, it can be used to deliver various payloads through it. For this purpose we will execute-protect the SharedUserData page through EPT.
The SharedUserData page may be used to store some fake structures in some complex exploitation scenarios, for example MDLs in SMBGhost. For this purpose, we verify once every second that after the SharedUserData structure, the rest of the page is filled with 0. Moreover, some fixed fields which may be messed with for exploitation purposes are also checked in order to detect modifications.
Definition in file winsud.c.
typedef struct _SHARED_USER_DATA_PROT_FIELD * PSHARED_USER_DATA_PROT_FIELD |
typedef struct _SHARED_USER_DATA_PROT_FIELD SHARED_USER_DATA_PROT_FIELD |
Describes a field from KUSER_SHARED_DATA which is protected through integrity.
TIMER_FRIENDLY INTSTATUS IntWinSudCheckIntegrity | ( | void | ) |
This function checks the integrity of protected fields from SharedUserData, described in gProtFields.
For every field in gProtFields, this function will check whether the internally saved value is equal to the current value. For this purpose, this function will fetch the SharedUserData contents in gSudBuffer in order to verfiy the new values. For fields that have ShouldBeZero set to TRUE, this function will verify every byte from the described field to be equal to zero. If the ShouldBeZero field has been previously modified and the modification has been allowed, it has the ReenableOnZero flag set, therefore, if a ShouldBeZero field is now filled with zeroes, this function will re-enable the checks on it.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED_HINT | If the SharedUserData integrity protection was not yet initialized. |
INT_STATUS_INVALID_INTERNAL_STATE | If the SharedUserData protection is initialized but the protection flags do not include this protection. |
Definition at line 980 of file winsud.c.
Referenced by IntHandleTimer().
|
static |
Fetches the value of the given described field from the global SharedUserData buffer.
This function should be called only for described fields that have ShouldBeZero set to FALSE. If the field size is not 1, 2, 4 or 8, the function will return FALSE and will not fetch the field value.
TRUE | If the value has been succesfully fetched for the given field. |
FALSE | Otherwise. |
Definition at line 725 of file winsud.c.
Referenced by IntWinSudCheckIntegrity(), and IntWinSudProtectIntegrity().
|
static |
This function is called when a modification has been detected on a given field in order to take a decision on the current modification.
This will call the exception engine in order to verify whether the current modification is excepted or not and based on the current policy and options will decide if an alert should be sent. Depending on the taken action, this function will decide to rewrite the modified field with the old value or to internally acknowledge the new value as the known one, if the modification was deemed legitimate.
[in] | Field | The SHARED_USER_DATA_PROT_FIELD describing the field on which the modification has been detected. |
[in] | NewValue | The new value of the modified field. For ShouldBeZero fields it should be ignored. |
INT_STATUS_SUCCESS | On success. |
Definition at line 828 of file winsud.c.
Referenced by IntWinSudCheckIntegrity().
|
static |
Handles a kernel mode execution inside SharedUserData.
This function will call the exceptions mechanism, decide if an alert should be sent, and sends it, if it is the case, for the given kernel-mode execution in SharedUserData.
[in] | Address | The physical address on which the execution occurred. |
[in,out] | Action | The action which is decided by the exception mechanism and the current policy. |
INT_STATUS_SUCCESS | On success. |
Definition at line 365 of file winsud.c.
Referenced by IntWinSudHandleSudExec().
|
static |
Ept callback which handles executions inside SharedUserData.
This will handle the executions, based on current ring, separately on kernel mode and user mode. For kernel mode executions, if the execution is deemed malicious, we will overwrite the first instruction from the executed area with a RET instruction, so that the execution is returned to the driver which called this region, limiting as much as possible the damage that can be provoked by such an execution, and limiting the possibility of a system crash. However, if the current ring points to an execution in user mode, we will instead inject an UD exception into the guest, trying to crash the process trying the execution, so that we limit the ability of this given process to continue execution.
[in] | Context | User-supplied context. Unused in this case. |
[in] | Hook | The hook object for the given protection. Unused in this case. |
[in] | Address | The physical address on which the violation occurred. |
[out] | Action | The INTRO_ACTION which is decided for the given execution in this handler. |
INT_STATUS_SUCCESS | On success |
Definition at line 523 of file winsud.c.
Referenced by IntWinSudProtectSudExec().
|
static |
Handles an user-mode execution inside SharedUserData.
This function will call the exceptions mechanism, decide if an alert should be sent, and sends it, if it is the case, for the given user-mode execution in SharedUserData.
[in] | Address | The physical address on which the execution occurred. |
[in,out] | Action | The action which is decided by the exception mechanism and the current policy. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_FOUND | If there doesn't exist a process with the current CR3. |
Definition at line 443 of file winsud.c.
Referenced by IntWinSudHandleSudExec().
INTSTATUS IntWinSudProtectIntegrity | ( | void | ) |
Initializes the SharedUserData integrity protection.
This includes allocating the global buffer for SharedUserData contents, fetching the values in the internal states for the current fields and making some checks regarding the field sizes in order to ensure that the internal state for the protected fields is correct.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_NEEDED_HINT | If the protection is already initialized. |
INT_STATUS_INSUFFICIENT_RESOURCES | If the global buffer could not be allocated. |
Definition at line 1099 of file winsud.c.
Referenced by IntGuestUpdateCoreOptions(), and IntWinGuestActivateProtection().
INTSTATUS IntWinSudProtectSudExec | ( | void | ) |
Protects SharedUserData against executions by establishing an EPT hook on it.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_ALREADY_INITIALIZED | If the hook is already established. |
Definition at line 661 of file winsud.c.
Referenced by IntGuestUpdateCoreOptions(), and IntWinGuestActivateProtection().
|
static |
Constructs and sends an EVENT_EPT_VIOLATION alert which occurred due to an execution in SharedUserData.
[in] | Originator | Depending on the IsKernel parameter, can be EXCEPTION_KM_ORIGINATOR or EXCEPTION_UM_ORIGINATOR. Represents the originator of the execution. |
[in] | Victim | The EXCEPTION_VICTIM_ZONE representing the victim of the violation. |
[in] | IsKernel | TRUE if the alert occurred in kernel-mode, FALSE for user-mode. |
[in] | Action | The action which was decided by the exception engine. |
[in] | Reason | The reason why the given action has been taken. |
Definition at line 298 of file winsud.c.
Referenced by IntWinSudHandleKernelSudExec(), and IntWinSudHandleUserSudExec().
|
static |
Completes and sends an alert for a detected SharedUserData modification on a monitored field.
[in] | Victim | The EXCEPTION_VICTIM_ZONE describing the modified field. |
[in] | Field | The SHARED_USER_DATA_PROT_FIELD describing the protected field. |
[in] | Action | The action which was taken before deciding to send the alert. |
[in] | Reason | The reason for which the given action has been taken. |
Definition at line 767 of file winsud.c.
Referenced by IntWinSudHandleFieldModification().
INTSTATUS IntWinSudUnprotectIntegrity | ( | void | ) |
Uninitializes the SharedUserData integrity protection.
This will de-allocate the global buffer and will set the gSudIntegrityInitialized boolean to FALSE, so that the next integrity checks will not be made anymore. Note that there is no need to reset the global state at this point, as a future call to IntWinSudProtectIntegrity will update the old values, and the ShouldBeZero fields that have ReenableOnZero flag set will be monitored on the next integrity check after the protection was re-activated.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_NEEDED_HINT | If the protection is already uninitialized. |
Definition at line 1178 of file winsud.c.
Referenced by IntGuestUpdateCoreOptions().
INTSTATUS IntWinSudUnprotectSudExec | ( | void | ) |
Removes the execution EPT hook on SharedUserData.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED | If the hook was not previously established. |
Definition at line 697 of file winsud.c.
Referenced by IntGuestUpdateCoreOptions().
SHARED_USER_DATA_PROT_FIELD gProtFields[] |
|
static |
Buffer for fast accessing the current contents of SharedUserData.
Definition at line 40 of file winsud.c.
Referenced by IntWinSudCheckIntegrity(), IntWinSudFetchFieldCurrentValue(), IntWinSudHandleFieldModification(), IntWinSudProtectIntegrity(), and IntWinSudUnprotectIntegrity().
|
static |
Is set to true when integrity is initialized on SharedUserData signaling that checks can be performed.
Definition at line 43 of file winsud.c.
Referenced by IntWinSudCheckIntegrity(), IntWinSudProtectIntegrity(), and IntWinSudUnprotectIntegrity().