Bitdefender Hypervisor Memory Introspection
winsud.c File Reference

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_FIELDPSHARED_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_GVAgSudExecHook = NULL
 The hook object protecting against executions on SharedUserData. More...
 
static BYTEgSudBuffer = 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...
 

Detailed Description

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 Documentation

◆ PSHARED_USER_DATA_PROT_FIELD

◆ SHARED_USER_DATA_PROT_FIELD

Describes a field from KUSER_SHARED_DATA which is protected through integrity.

Function Documentation

◆ IntWinSudCheckIntegrity()

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.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the SharedUserData integrity protection was not yet initialized.
INT_STATUS_INVALID_INTERNAL_STATEIf 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().

◆ IntWinSudFetchFieldCurrentValue()

static BOOLEAN IntWinSudFetchFieldCurrentValue ( SHARED_USER_DATA_PROT_FIELD Field,
QWORD CurrentValue 
)
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.

Return values
TRUEIf the value has been succesfully fetched for the given field.
FALSEOtherwise.

Definition at line 725 of file winsud.c.

Referenced by IntWinSudCheckIntegrity(), and IntWinSudProtectIntegrity().

◆ IntWinSudHandleFieldModification()

static INTSTATUS IntWinSudHandleFieldModification ( SHARED_USER_DATA_PROT_FIELD Field,
QWORD  NewValue 
)
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.

Parameters
[in]FieldThe SHARED_USER_DATA_PROT_FIELD describing the field on which the modification has been detected.
[in]NewValueThe new value of the modified field. For ShouldBeZero fields it should be ignored.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 828 of file winsud.c.

Referenced by IntWinSudCheckIntegrity().

◆ IntWinSudHandleKernelSudExec()

static INTSTATUS IntWinSudHandleKernelSudExec ( QWORD  Address,
INTRO_ACTION Action 
)
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.

Parameters
[in]AddressThe physical address on which the execution occurred.
[in,out]ActionThe action which is decided by the exception mechanism and the current policy.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 365 of file winsud.c.

Referenced by IntWinSudHandleSudExec().

◆ IntWinSudHandleSudExec()

static INTSTATUS IntWinSudHandleSudExec ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
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.

Parameters
[in]ContextUser-supplied context. Unused in this case.
[in]HookThe hook object for the given protection. Unused in this case.
[in]AddressThe physical address on which the violation occurred.
[out]ActionThe INTRO_ACTION which is decided for the given execution in this handler.
Return values
INT_STATUS_SUCCESSOn success

Definition at line 523 of file winsud.c.

Referenced by IntWinSudProtectSudExec().

◆ IntWinSudHandleUserSudExec()

static INTSTATUS IntWinSudHandleUserSudExec ( QWORD  Address,
INTRO_ACTION Action 
)
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.

Parameters
[in]AddressThe physical address on which the execution occurred.
[in,out]ActionThe action which is decided by the exception mechanism and the current policy.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf there doesn't exist a process with the current CR3.

Definition at line 443 of file winsud.c.

Referenced by IntWinSudHandleSudExec().

◆ IntWinSudProtectIntegrity()

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.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the protection is already initialized.
INT_STATUS_INSUFFICIENT_RESOURCESIf the global buffer could not be allocated.

Definition at line 1099 of file winsud.c.

Referenced by IntGuestUpdateCoreOptions(), and IntWinGuestActivateProtection().

◆ IntWinSudProtectSudExec()

INTSTATUS IntWinSudProtectSudExec ( void  )

Protects SharedUserData against executions by establishing an EPT hook on it.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_ALREADY_INITIALIZEDIf the hook is already established.

Definition at line 661 of file winsud.c.

Referenced by IntGuestUpdateCoreOptions(), and IntWinGuestActivateProtection().

◆ IntWinSudSendSudExecAlert()

static void IntWinSudSendSudExecAlert ( void *  Originator,
EXCEPTION_VICTIM_ZONE Victim,
BOOLEAN  IsKernel,
INTRO_ACTION  Action,
INTRO_ACTION_REASON  Reason 
)
static

Constructs and sends an EVENT_EPT_VIOLATION alert which occurred due to an execution in SharedUserData.

Parameters
[in]OriginatorDepending on the IsKernel parameter, can be EXCEPTION_KM_ORIGINATOR or EXCEPTION_UM_ORIGINATOR. Represents the originator of the execution.
[in]VictimThe EXCEPTION_VICTIM_ZONE representing the victim of the violation.
[in]IsKernelTRUE if the alert occurred in kernel-mode, FALSE for user-mode.
[in]ActionThe action which was decided by the exception engine.
[in]ReasonThe reason why the given action has been taken.

Definition at line 298 of file winsud.c.

Referenced by IntWinSudHandleKernelSudExec(), and IntWinSudHandleUserSudExec().

◆ IntWinSudSendSudIntegrityAlert()

static void IntWinSudSendSudIntegrityAlert ( EXCEPTION_VICTIM_ZONE Victim,
SHARED_USER_DATA_PROT_FIELD Field,
INTRO_ACTION  Action,
INTRO_ACTION_REASON  Reason 
)
static

Completes and sends an alert for a detected SharedUserData modification on a monitored field.

Parameters
[in]VictimThe EXCEPTION_VICTIM_ZONE describing the modified field.
[in]FieldThe SHARED_USER_DATA_PROT_FIELD describing the protected field.
[in]ActionThe action which was taken before deciding to send the alert.
[in]ReasonThe reason for which the given action has been taken.

Definition at line 767 of file winsud.c.

Referenced by IntWinSudHandleFieldModification().

◆ IntWinSudUnprotectIntegrity()

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.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the protection is already uninitialized.

Definition at line 1178 of file winsud.c.

Referenced by IntGuestUpdateCoreOptions().

◆ IntWinSudUnprotectSudExec()

INTSTATUS IntWinSudUnprotectSudExec ( void  )

Removes the execution EPT hook on SharedUserData.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf the hook was not previously established.

Definition at line 697 of file winsud.c.

Referenced by IntGuestUpdateCoreOptions().

Variable Documentation

◆ gProtFields

Global array containing the descriptors used for protecting fields inside SharedUserData.

Definition at line 72 of file winsud.c.

◆ gSudBuffer

BYTE* gSudBuffer = NULL
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().

◆ gSudExecHook

HOOK_GVA* gSudExecHook = NULL
static

The hook object protecting against executions on SharedUserData.

Definition at line 37 of file winsud.c.

◆ gSudIntegrityInitialized

BOOLEAN gSudIntegrityInitialized = FALSE
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().