Bitdefender Hypervisor Memory Introspection
|
#include "introcore.h"
#include "winsecdesc.h"
#include "guests.h"
#include "hook.h"
#include "alerts.h"
#include "gpacache.h"
#include "kernvm.h"
#include "crc32.h"
Go to the source code of this file.
Macros | |
#define | INT_MAX_ACE_COUNT 1820 |
The maximum number of ACEs that are allowed within a single ACL. "The maximum size of an ACL is 64
kilobytes (KB), or approximately 1,820 ACEs." https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/error-add-user-to-security-permissions. More... | |
#define | INT_SID_CHAR_SIZE 512 |
#define | INT_MAX_SUB_AUTHORITY_COUT 30 |
Functions | |
STATIC_ASSERT (sizeof(ACL)==sizeof(QWORD), "Sizeof of ACL is not a QWORD") | |
We are using the EXCEPTION_VICTIM_ZONE.WriteInfo to send the New/Old SACL/DACL. More... | |
STATIC_ASSERT (INTRO_SECURITY_DESCRIPTOR_SIZE >(sizeof(SECURITY_DESCRIPTOR)+2 *sizeof(ACL)), "INTRO_SECURITY_DESCRIPTOR_SIZE is too small") | |
Make sure the buffer is big enough - at least for the headers. More... | |
static char * | IntWinSDGetAceTypeName (BYTE AceTypeValue) |
This function obtains the printable name for a given ACE type. More... | |
INTSTATUS | IntWinSDFindAcls (DWORD BufferSize, BYTE *SecurityDescriptorBuffer, DWORD *ReadSize, ACL **Sacl, ACL **Dacl) |
This function looks for the Sacl/Dacl within the SecurityDescriptorBuffer and makes sure they are within the buffer range. More... | |
static BOOLEAN | IntWinSDIsAceInsideAcl (ACL *Acl, ACE_HEADER *Ace) |
This function checks whether the ACE fits inside the ACL (the ACL structure must be obtained using IntWinSDFindAcls). More... | |
static BOOLEAN | IntWinSDIsAceInsideBuffer (BYTE *Buffer, DWORD BufferSize, ACE_HEADER *Ace) |
This function checks whether the ACE fits inside the given buffer. More... | |
INTSTATUS | IntWinSDReadSecDesc (QWORD SecurityDescriptorGva, DWORD BufferSize, BYTE *SecurityDescriptorBuffer, DWORD *ReadSize, ACL **Sacl, ACL **Dacl) |
This function reads the ACLs (along with the ACEs) from the given GVA and returns the data using the provided buffer and the Sacl/Dacl pointers. This function will read the SECURITY_DESCRIPTOR structure that acts as a header, the SACL header and then use the SACL size to find the DACL. If an attacker were to alter the SACL/DACL size such that it will not fit in the given buffer, the function will fail with INT_STATUS_DATA_BUFFER_TOO_SMALL - check the returned Sacl/Dacl values. More... | |
static void | IntWinSDDumpAclEntries (ACL *Acl, BOOLEAN IsSacl, BYTE *SecurityDescriptorBuffer, DWORD BufferSize) |
This function dumps the access control entries (ACE) for a given access control list (ACL). More... | |
static void | IntWinSDDumpSecDesc (WIN_PROCESS_OBJECT *Process, BYTE *SecurityDescriptorBuffer, DWORD BufferSize, BOOLEAN Original) |
This function dumps the security descriptor for a given process. More... | |
static INTSTATUS | IntWinSDGatherAcl (WIN_PROCESS_OBJECT *Process) |
This function gathers the 2 ACLs (SACL/DACL) and stores them in the WIN_PROCESS_OBJECT structure of the given process (the data will later be used for integrity checks and DPI). More... | |
static INTSTATUS | IntWinSDFetchSecDescAddress (WIN_PROCESS_OBJECT *Process, QWORD *SecurityDescriptorAddressGva) |
This function reads the security descriptor address for the given process using the GPA cache. More... | |
INTSTATUS | IntWinSDProtectSecDesc (WIN_PROCESS_OBJECT *Process) |
This function saves the security descriptor address and ACLs into the WIN_PROCESS_OBJECT structure. More... | |
static INTSTATUS | IntWinSDFetchSecDescValues (WIN_PROCESS_OBJECT *Process, QWORD *OldValue, QWORD *NewValue) |
This function obtains the original security descriptor value (from the WIN_PROCESS_OBJECT structure) and the current value (by reading the guest memory using GPA cache). More... | |
BOOLEAN | IntWinSDIsSecDescPtrAltered (WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT **VictimProcess, QWORD *OldValue, QWORD *NewValue) |
This function checks if the security descriptor pointer of a process has been altered or not. More... | |
BOOLEAN | IntWinSDIsAclEdited (WIN_PROCESS_OBJECT *Process, DWORD BufferSize, BYTE *SecurityDescriptorBuffer, DWORD *ReadSize, ACL **NewSacl, ACL **NewDacl) |
This function reads the ACLs for the given process (returning the data using the provided buffer and the Sacl/Dacl pointers) and then compares the read data with the one stored within the WIN_PROCESS_OBJECT structure. More... | |
static INTSTATUS | IntWinSDSendSecDescIntViolation (WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *Victim, QWORD OldValue, QWORD NewValue, BYTE *SecDescBuffer, DWORD SecDescSize, DWORD SecDescHash, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
This function sends an integrity violation caused by a modified security descriptor pointer. More... | |
static INTSTATUS | IntWinSDSendAclIntegrityViolation (WIN_PROCESS_OBJECT *Process, BYTE *SecDescBuffer, DWORD SecDescSize, DWORD SecDescHash, INTRO_ACTION Action, INTRO_ACTION_REASON Reason) |
This function sends an integrity violation caused by a modified ACL (SACL/DACL). More... | |
static void | IntWinSDClearAclEnd (ACL *Acl, WORD CalculatedSize) |
This function clears the last bytes of the ACL in case the ACL size is greater than the sum of its ACEs. More... | |
static void | IntWinSDProcessAcl (ACL *Acl) |
This function clears the SIDs that have more than one sub authority for a given ACL. More... | |
static INTSTATUS | IntWinSDCheckSecDescIntegrity (WIN_PROCESS_OBJECT *Process) |
This function checks the integrity of the security descriptor for the given process. In case the security descriptor pointer has been altered, the VCPUs will be paused in order to restore the original value, the victim process will be found (in case there is one) and an alert will be sent. More... | |
static INTSTATUS | IntWinSDCheckAclIntegrity (WIN_PROCESS_OBJECT *Process) |
This function checks the integrity of the ACLs (SACL/DACL) for the given process. In case the ACLs have been altered, the VCPUs will be paused in order to restore the original value and an alert will be sent. More... | |
TIMER_FRIENDLY INTSTATUS | IntWinSDCheckIntegrity (void) |
This function checks the integrity of the security descriptor for all the processes inside gWinProcesses. More... | |
Variables | |
LIST_HEAD | gWinProcesses |
The list of all the processes inside the guest. More... | |
#define INT_MAX_ACE_COUNT 1820 |
The maximum number of ACEs that are allowed within a single ACL. "The maximum size of an ACL is 64 kilobytes (KB), or approximately 1,820 ACEs." https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/error-add-user-to-security-permissions.
Definition at line 108 of file winsecdesc.c.
Referenced by IntWinSDDumpAclEntries(), and IntWinSDProcessAcl().
#define INT_MAX_SUB_AUTHORITY_COUT 30 |
Referenced by IntWinSDDumpAclEntries().
#define INT_SID_CHAR_SIZE 512 |
Referenced by IntWinSDDumpAclEntries().
|
static |
This function checks the integrity of the ACLs (SACL/DACL) for the given process. In case the ACLs have been altered, the VCPUs will be paused in order to restore the original value and an alert will be sent.
[in] | Process | The process to be saved. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED_HINT | If the SecurityDescriptor GVA is NULL. |
Definition at line 1485 of file winsecdesc.c.
Referenced by IntWinSDCheckIntegrity().
TIMER_FRIENDLY INTSTATUS IntWinSDCheckIntegrity | ( | void | ) |
This function checks the integrity of the security descriptor for all the processes inside gWinProcesses.
INT_STATUS_SUCCESS | On success. |
Definition at line 1656 of file winsecdesc.c.
Referenced by IntHandleTimer().
|
static |
This function checks the integrity of the security descriptor for the given process. In case the security descriptor pointer has been altered, the VCPUs will be paused in order to restore the original value, the victim process will be found (in case there is one) and an alert will be sent.
[in] | Process | The process to be saved. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_SKIP_OTHER_CALLBACKS | If the security descriptor has been patched and there is no need for the ACL checks. |
Definition at line 1293 of file winsecdesc.c.
Referenced by IntWinSDCheckIntegrity().
This function clears the last bytes of the ACL in case the ACL size is greater than the sum of its ACEs.
[in,out] | Acl | The access control entry to be cleared (SACL/DACL). |
[in] | CalculatedSize | The calculated size of the ACEs contained within the ACL. |
Definition at line 1206 of file winsecdesc.c.
Referenced by IntWinSDProcessAcl().
|
static |
This function dumps the access control entries (ACE) for a given access control list (ACL).
[in] | Acl | The ACL to dump the entries for. |
[in] | IsSacl | TRUE is the ACL is Sacl, FALSE otherwise (Dacl) - used for logging. |
[in] | SecurityDescriptorBuffer | The security descriptor buffer. |
[in] | BufferSize | The size of the security descriptor buffer. |
The size of the printable SID buffer.
The maximum number of sub authorities - empirically chosen value.
Definition at line 459 of file winsecdesc.c.
Referenced by IntWinSDDumpSecDesc().
|
static |
This function dumps the security descriptor for a given process.
[in] | Process | The process to dump the security descriptor for. |
[in] | SecurityDescriptorBuffer | The security descriptor to be dumped. |
[in] | BufferSize | The size of the security descriptor buffer. |
[in] | Original | TRUE is the given security descriptor is the original one, FALSE otherwise (used only for logging). |
Definition at line 577 of file winsecdesc.c.
Referenced by IntWinSDCheckAclIntegrity(), and IntWinSDCheckSecDescIntegrity().
|
static |
This function reads the security descriptor address for the given process using the GPA cache.
[in] | Process | The process to read the security descriptor for. |
[in] | SecurityDescriptorAddressGva | The security descriptor GVA. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_PAGE_NOT_PRESENT | If the GVA is not mapped/present using guest PTEs. |
Definition at line 697 of file winsecdesc.c.
Referenced by IntWinSDFetchSecDescValues(), and IntWinSDProtectSecDesc().
|
static |
This function obtains the original security descriptor value (from the WIN_PROCESS_OBJECT structure) and the current value (by reading the guest memory using GPA cache).
[in] | Process | The process to query the information for. |
[out] | OldValue | The original security descriptor value. |
[out] | NewValue | The current security descriptor value. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_PAGE_NOT_PRESENT | If the GVA is not mapped/present using guest PTEs. |
Definition at line 793 of file winsecdesc.c.
Referenced by IntWinSDIsSecDescPtrAltered().
INTSTATUS IntWinSDFindAcls | ( | DWORD | BufferSize, |
BYTE * | SecurityDescriptorBuffer, | ||
DWORD * | ReadSize, | ||
ACL ** | Sacl, | ||
ACL ** | Dacl | ||
) |
This function looks for the Sacl/Dacl within the SecurityDescriptorBuffer and makes sure they are within the buffer range.
[in] | BufferSize | The size in bytes of the given buffer (SecurityDescriptorBuffer). |
[in] | SecurityDescriptorBuffer | The buffer where the ACLs (along with the ACEs) are stored. |
[out] | ReadSize | The size in bytes of the returned security descriptor. |
[out] | Sacl | Points to the SACL header inside the SecurityDescriptorBuffer. |
[out] | Dacl | Points to the DACL header inside the SecurityDescriptorBuffer. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_DATA_BUFFER_TOO_SMALL | If the Sacl/Dacl do not fit within the buffer. |
Definition at line 202 of file winsecdesc.c.
Referenced by IntWinSDDumpSecDesc(), and IntWinSDReadSecDesc().
|
static |
This function gathers the 2 ACLs (SACL/DACL) and stores them in the WIN_PROCESS_OBJECT structure of the given process (the data will later be used for integrity checks and DPI).
[in,out] | Process | The process to gather the ACLs for. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_NEEDED_HINT | If the SecurityDescriptor GVA is NULL. |
Definition at line 634 of file winsecdesc.c.
Referenced by IntWinSDCheckAclIntegrity(), IntWinSDCheckSecDescIntegrity(), IntWinSDIsSecDescPtrAltered(), and IntWinSDProtectSecDesc().
|
static |
This function obtains the printable name for a given ACE type.
[in] | AceTypeValue | The ACE type - found within the Security Descriptor. |
A | valid ACE type name On success. |
NULL | If the given ACE type value is invalid. |
Definition at line 111 of file winsecdesc.c.
Referenced by IntWinSDDumpAclEntries().
|
static |
This function checks whether the ACE fits inside the ACL (the ACL structure must be obtained using IntWinSDFindAcls).
[in] | Acl | The Access Control List. |
[in] | Ace | The Access Control Entry. |
Definition at line 289 of file winsecdesc.c.
Referenced by IntWinSDProcessAcl().
|
static |
This function checks whether the ACE fits inside the given buffer.
[in] | Buffer | The buffer. |
[in] | BufferSize | The size of the buffer. |
[in] | Ace | The Access Control Entry. |
Definition at line 326 of file winsecdesc.c.
Referenced by IntWinSDDumpAclEntries().
BOOLEAN IntWinSDIsAclEdited | ( | WIN_PROCESS_OBJECT * | Process, |
DWORD | BufferSize, | ||
BYTE * | SecurityDescriptorBuffer, | ||
DWORD * | ReadSize, | ||
ACL ** | NewSacl, | ||
ACL ** | NewDacl | ||
) |
This function reads the ACLs for the given process (returning the data using the provided buffer and the Sacl/Dacl pointers) and then compares the read data with the one stored within the WIN_PROCESS_OBJECT structure.
[in] | Process | The process the check the ACLs integrity for. |
[in] | BufferSize | The size in bytes of the given buffer (SecurityDescriptorBuffer). |
[out] | SecurityDescriptorBuffer | The buffer where the ACLs (along with the ACEs) will be stored. |
[out] | ReadSize | The size in bytes of the returned security descriptor. |
[out] | NewSacl | The current SACL header. |
[out] | NewDacl | The current DACL header. |
Definition at line 916 of file winsecdesc.c.
Referenced by IntWinDpiValidateParentAclEdit(), and IntWinSDCheckAclIntegrity().
BOOLEAN IntWinSDIsSecDescPtrAltered | ( | WIN_PROCESS_OBJECT * | Process, |
WIN_PROCESS_OBJECT ** | VictimProcess, | ||
QWORD * | OldValue, | ||
QWORD * | NewValue | ||
) |
This function checks if the security descriptor pointer of a process has been altered or not.
[in] | Process | The process to query the information for. |
[out] | VictimProcess | The process where the security descriptor has been stolen from (it can be NULL if the security descriptor was not altered or it was altered but the source is not the security descriptor of a known process). |
[out] | OldValue | The original security descriptor value. |
[out] | NewValue | The current security descriptor value. |
TRUE | The security descriptor has been altered. |
FALSE | The security descriptor has NOT been altered. |
Definition at line 829 of file winsecdesc.c.
Referenced by IntWinDpiValidateParentSecDesc(), and IntWinSDCheckSecDescIntegrity().
|
static |
This function clears the SIDs that have more than one sub authority for a given ACL.
[in,out] | Acl | The access control entry to be processed (SACL/DACL). |
Definition at line 1234 of file winsecdesc.c.
Referenced by IntWinSDCheckAclIntegrity(), and IntWinSDCheckSecDescIntegrity().
INTSTATUS IntWinSDProtectSecDesc | ( | WIN_PROCESS_OBJECT * | Process | ) |
This function saves the security descriptor address and ACLs into the WIN_PROCESS_OBJECT structure.
[in] | Process | The process to save the security descriptor for. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER_1 | If the given Process is NULL. |
Definition at line 750 of file winsecdesc.c.
Referenced by IntWinProcCreateProcessObject().
INTSTATUS IntWinSDReadSecDesc | ( | QWORD | SecurityDescriptorGva, |
DWORD | BufferSize, | ||
BYTE * | SecurityDescriptorBuffer, | ||
DWORD * | ReadSize, | ||
ACL ** | Sacl, | ||
ACL ** | Dacl | ||
) |
This function reads the ACLs (along with the ACEs) from the given GVA and returns the data using the provided buffer and the Sacl/Dacl pointers. This function will read the SECURITY_DESCRIPTOR structure that acts as a header, the SACL header and then use the SACL size to find the DACL. If an attacker were to alter the SACL/DACL size such that it will not fit in the given buffer, the function will fail with INT_STATUS_DATA_BUFFER_TOO_SMALL - check the returned Sacl/Dacl values.
[in] | SecurityDescriptorGva | The GVA of the security descriptor. |
[in] | BufferSize | The size in bytes of the given buffer (SecurityDescriptorBuffer). |
[out] | SecurityDescriptorBuffer | The buffer where the ACLs (along with the ACEs) will be stored. |
[out] | ReadSize | The size in bytes of the returned security descriptor. |
[out] | Sacl | Points to the SACL header inside the SecurityDescriptorBuffer. |
[out] | Dacl | Points to the DACL header inside the SecurityDescriptorBuffer. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_PAGE_NOT_PRESENT | If the given GVA is not mapped. |
INT_STATUS_DATA_BUFFER_TOO_SMALL | If the security descriptor is larger than the provided buffer. |
Definition at line 362 of file winsecdesc.c.
Referenced by IntWinDpiValidateParentSecDesc(), IntWinSDCheckAclIntegrity(), IntWinSDCheckSecDescIntegrity(), IntWinSDGatherAcl(), and IntWinSDIsAclEdited().
|
static |
This function sends an integrity violation caused by a modified ACL (SACL/DACL).
[in] | Process | The process that was found to have a modified security descriptor. |
[in] | SecDescBuffer | The new security descriptor buffer. |
[in] | SecDescSize | The new security descriptor buffer size. |
[in] | SecDescHash | The new security descriptor hash (computer after IntWinSDProcessAcl). |
[in] | Action | The taken action (INTRO_ACTION). |
[in] | Reason | The reason for the taken action (INTRO_ACTION_REASON). |
INT_STATUS_SUCCESS | On success. |
Definition at line 1131 of file winsecdesc.c.
Referenced by IntWinSDCheckAclIntegrity().
|
static |
This function sends an integrity violation caused by a modified security descriptor pointer.
[in] | Process | The process that was found to have a different security descriptor. |
[in] | Victim | The process from where the security descriptor pointer was stolen from (it can be NULL). |
[in] | OldValue | The old value of the security descriptor. |
[in] | NewValue | The new value of the security descriptor. |
[in] | SecDescBuffer | The new security descriptor buffer. |
[in] | SecDescSize | The new security descriptor buffer size. |
[in] | SecDescHash | The new security descriptor hash (computer after IntWinSDProcessAcl). |
[in] | Action | The taken action (INTRO_ACTION). |
[in] | Reason | The reason for the taken action (INTRO_ACTION_REASON). |
INT_STATUS_SUCCESS | On success. |
Definition at line 1048 of file winsecdesc.c.
Referenced by IntWinSDCheckSecDescIntegrity().
We are using the EXCEPTION_VICTIM_ZONE.WriteInfo to send the New/Old SACL/DACL.
STATIC_ASSERT | ( | INTRO_SECURITY_DESCRIPTOR_SIZE | , |
(sizeof(SECURITY_DESCRIPTOR)+2 *sizeof(ACL)) | , | ||
"INTRO_SECURITY_DESCRIPTOR_SIZE is too small" | |||
) |
Make sure the buffer is big enough - at least for the headers.
LIST_HEAD gWinProcesses |
The list of all the processes inside the guest.
Definition at line 11 of file winprocesshp.c.