Bitdefender Hypervisor Memory Introspection
|
Hides memory contents from the guest. More...
Data Structures | |
struct | _MEMCLOAK_PAGE |
A structure that describes a hidden guest memory page. More... | |
struct | _MEMCLOAK_REGION |
A structure that describes a hidden guest memory region. More... | |
Macros | |
#define | MEMCLOACK_PAGE_MAX_COUNT 2 |
The maximum number of pages that can be contained in a MEMCLOAK_REGION. More... | |
Typedefs | |
typedef INTSTATUS(* | PFUNC_IntMemCloakWriteHandle) (void *Hook, QWORD Address, QWORD RegionVirtualAddress, void *CloakHandle, INTRO_ACTION *Action) |
The type of custom write handlers that can be used by cloak regions. More... | |
typedef struct _MEMCLOAK_PAGE | MEMCLOAK_PAGE |
A structure that describes a hidden guest memory page. More... | |
typedef struct _MEMCLOAK_PAGE * | PMEMCLOAK_PAGE |
typedef struct _MEMCLOAK_REGION | MEMCLOAK_REGION |
A structure that describes a hidden guest memory region. More... | |
typedef struct _MEMCLOAK_REGION * | PMEMCLOAK_REGION |
Enumerations | |
enum | MEMCLOAK_OPTIONS { MEMCLOAK_OPT_ALLOW_INTERNAL = 0x00000001, MEMCLOAK_OPT_APPLY_PATCH = 0x00000002 } |
Options that control the way a cloaked memory region is handled. More... | |
Functions | |
INTSTATUS | IntMemClkCloakRegion (QWORD VirtualAddress, QWORD Cr3, DWORD Size, DWORD Options, PBYTE OriginalData, PBYTE PatchedData, PFUNC_IntMemCloakWriteHandle WriteHandler, void **CloakHandle) |
Hides a memory zone from the guest. More... | |
INTSTATUS | IntMemClkModifyOriginalData (void *CloakHandle, DWORD Offset, DWORD Size, void *Data) |
Modifies the internal copy of the original data buffer held by a cloak region. More... | |
INTSTATUS | IntMemClkModifyPatchedData (void *CloakHandle, DWORD Offset, DWORD Size, const void *Data) |
Modifies the patched data inside the guest memory. More... | |
INTSTATUS | IntMemClkUncloakRegion (void *CloakHandle, DWORD Options) |
Removes a cloak region, making the original memory contents available again to the guest. More... | |
INTSTATUS | IntMemClkHashRegion (QWORD VirtualAddress, QWORD PhysicalAddress, DWORD Size, DWORD *Crc32) |
Hashes the contents of a cloaked memory page. More... | |
BOOLEAN | IntMemClkIsPtrInCloak (const void *Cloak, QWORD Ptr) |
Checks if a guest virtual address is located inside a cloak region. More... | |
INTSTATUS | IntMemClkGetOriginalData (void *CloakHandle, BYTE **OriginalData, DWORD *Length) |
Returns the original data of a cloaked region. More... | |
INTSTATUS | IntMemClkUnInit (void) |
Uninits the memory cloak subsystem. More... | |
void | IntMemClkDump (void) |
Dumps all the active cloak regions. More... | |
static INTSTATUS | IntMemClkUncloakRegionInternal (DWORD Options, PMEMCLOAK_REGION Region) |
Removes a cloak region, making the original memory contents available again to the guest. More... | |
static INTSTATUS | IntMemClkHandleSwap (MEMCLOAK_PAGE *Context, QWORD VirtualAddress, QWORD OldEntry, QWORD NewEntry, QWORD OldPageSize, QWORD NewPageSize) |
Handles swap-in and swap-outs performed on hidden memory regions. More... | |
static INTSTATUS | IntMemClkHandleRead (MEMCLOAK_PAGE *Context, PHOOK_GPA Hook, QWORD Gpa, INTRO_ACTION *Action) |
Handles reads from a hidden memory region. More... | |
static INTSTATUS | IntMemClkHandleWrite (PMEMCLOAK_PAGE *Context, void *Hook, QWORD Address, INTRO_ACTION *Action) |
Handles writes done inside a hidden memory region. More... | |
void | IntMemClkCleanup (MEMCLOAK_REGION *Region) |
Frees any resources held by a MEMCLOAK_REGION. More... | |
Variables | |
static LIST_HEAD | gMemClkRegions = LIST_HEAD_INIT(gMemClkRegions) |
A list containing all the memory regions that are currently hidden from the guest. More... | |
Hides memory contents from the guest.
Introcore may inject code or data, or modify existing guest code or data. This raises a series of problems, from hiding from the guest the fact that it is introspected, to making sure the changes are not seen by integrity mechanisms used by the guest (like patch guard on Windows). We also need to make sure that attackers can not modify code or data owned by introcore, while allowing us to easily modify and use those. This is handled here, by the memory cloak mechanism, which employs three memory hooks:
#define MEMCLOACK_PAGE_MAX_COUNT 2 |
The maximum number of pages that can be contained in a MEMCLOAK_REGION.
Definition at line 27 of file memcloak.c.
Referenced by IntMemClkCloakRegion().
typedef struct _MEMCLOAK_PAGE MEMCLOAK_PAGE |
A structure that describes a hidden guest memory page.
typedef struct _MEMCLOAK_REGION MEMCLOAK_REGION |
A structure that describes a hidden guest memory region.
typedef INTSTATUS(* PFUNC_IntMemCloakWriteHandle) (void *Hook, QWORD Address, QWORD RegionVirtualAddress, void *CloakHandle, INTRO_ACTION *Action) |
The type of custom write handlers that can be used by cloak regions.
[in] | Hook | The hook that triggered the event. |
[in] | Address | The physical address written. |
[in] | RegionVirtualAddress | The virtual address at which the region starts. |
[in] | CloakHandle | The cloak handle returned by IntMemClkCloakRegion. |
[out] | Action | The action that must be taken. This will overwrite the default action, which. is introGuestNotAllowed. |
Definition at line 41 of file memcloak.h.
typedef struct _MEMCLOAK_PAGE * PMEMCLOAK_PAGE |
typedef struct _MEMCLOAK_REGION * PMEMCLOAK_REGION |
enum MEMCLOAK_OPTIONS |
Options that control the way a cloaked memory region is handled.
Enumerator | |
---|---|
MEMCLOAK_OPT_ALLOW_INTERNAL | Allows the code inside the region to modify the region. |
MEMCLOAK_OPT_APPLY_PATCH | Will write the contents of the patched data inside the guest. |
Definition at line 51 of file memcloak.h.
void IntMemClkCleanup | ( | MEMCLOAK_REGION * | Region | ) |
Frees any resources held by a MEMCLOAK_REGION.
This function will free the MEMCLOAK_REGION.OriginalData and MEMCLOAK_REGION.PatchedData buffers, as well as the Region itself. It does not remove the hooks set for a region.
[in,out] | Region | The region to be freed. This pointer is no longer valid after this function returns. |
Definition at line 521 of file memcloak.c.
Referenced by IntMemClkUncloakRegionInternal().
INTSTATUS IntMemClkCloakRegion | ( | QWORD | VirtualAddress, |
QWORD | Cr3, | ||
DWORD | Size, | ||
DWORD | Options, | ||
PBYTE | OriginalData, | ||
PBYTE | PatchedData, | ||
PFUNC_IntMemCloakWriteHandle | WriteHandler, | ||
void ** | CloakHandle | ||
) |
Hides a memory zone from the guest.
This will place an EPT read, EPT write hook on the [VirtualAddress, VirtualAddress + Size) memory region. The read hook will allow us to hide memory from the guest. Attempts to read from the hidden pages will trigger an EPT violation that will be handled by IntMemClkHandleRead. This will allow us to control what the guest sees from a memory page. This is helpful when trying to hide code or data injected by us inside the guest. The write hook will allow us to protect the code or data injected inside the guest. It has a second purpose, as only removing the read permission from the EPT is not allowed, write-execute being an invalid combination. The write will be handled by IntMemClkHandleWrite, but a custom WriteHandler can also be provided. It will also hook the page tables used to translate the hidden pages, in order to catch swaps done on those pages and make sure that the modified data does not leak during page swap-in. The swap operation will be handled by IntMemClkHandleSwap.
[in] | VirtualAddress | The start of the virtual memory region to be hidden. |
[in] | Cr3 | The virtual address space in which the hiding is done. |
[in] | Size | The size of the hidden region. |
[in] | Options | Options that control the way accesses to the memory region are handled. Must be 0 or a combination of MEMCLOAK_OPTIONS values. |
[in] | OriginalData | The original data. This will be presented to the guest when it tries to read from the cloaked area. If not NULL, it must be Size bytes in length. If it is NULL, the original data is considered to be 0. |
[in] | PatchedData | The data patched by Introcore inside the guest.If not NULL, it must be Size bytes in length. If it is NULL, the patched data is considered to be 0. |
[in] | WriteHandler | A custom handler to use when the guest tries to write to the hidden memory area. It may be NULL, in which case the default handler will be used and all writes will be blocked. |
[out] | CloakHandle | The handle of the cloaked region. This is used as an unique identifier by APIs that control or modify the cloaked region. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_NOT_SUPPORTED | if the region spans across more than MEMCLOACK_PAGE_MAX_COUNT pages. |
INT_STATUS_INSUFFICIENT_RESOURCES | if an internal buffer could not be allocated. |
INT_STATUS_INVALID_PARAMETER_8 | if CloakHandle is NULL. |
Definition at line 548 of file memcloak.c.
Referenced by DbgTestRead(), IntDetPatchFunction(), IntDetSetHook(), IntLixAgentActivatePendingAgent(), IntLixGuestAllocateDeploy(), IntMtblPatchInstruction(), IntPtiMonitorAllPtWriteCandidates(), IntSwapgsInstallHandler(), IntSwapgsStartMitigation(), IntWinAgentActivatePendingAgent(), IntWinAgentInjectTrampoline(), and IntWinApiHookVeHandler().
void IntMemClkDump | ( | void | ) |
Dumps all the active cloak regions.
Definition at line 1218 of file memcloak.c.
Referenced by IntLogCriticalStructureCoruption().
Returns the original data of a cloaked region.
This will return a pointer to the internal MEMCLOAK_REGION.OriginalData buffer.
[in] | CloakHandle | The cloak handle. This is obtained from IntMemClkCloakRegion. |
[out] | OriginalData | Pointer to a BYTE* that will receive the address of the original data buffer. |
[out] | Length | Pointer to a DWORD that will receive the size of the original data buffer. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_INVALID_PARAMETER_1 | if CloakHandle is NULL. |
INT_STATUS_INVALID_PARAMETER_2 | if OriginalData is NULL. |
INT_STATUS_INVALID_PARAMETER_3 | if Length is NULL. |
Definition at line 1121 of file memcloak.c.
Referenced by IntDetHandleWrite().
|
static |
Handles reads from a hidden memory region.
This is were the actual hiding takes place. When trying to read from a memory area that is hidden, the guest will generate an EPT violation VMEXIT that will be handled here. This is done using the GLUE_IFACE.SetIntroEmulatorContext mechanism, providing the underlying hypervisor the data that needs to be used when emulating the access done by the guest. In order to do this, we need to figure out where exactly inside the cloaked region is the read done and extract the appropriate parts of the MEMCLOAK_REGION.OriginalData buffer. A read can overlap the hidden memory region in multiple way. If the hidden region is in the range [0x1002, 0x1006], the read can be done for:
[in] | Context | The page for which this handler is invoked. |
[in] | Hook | The GPA hook which triggered this event. |
[in] | Gpa | The guest physical address that was accessed. |
[out] | Action | The action that must be taken while handling this event. This will be set to introGuestAllowedPatched if there is something that must be hidden from the guest. If introGuestAllowed is used, this can mean a few things: the accessed page is no longer present, in which case we want to allow the read, as it will generate a page fault inside the guest, which will handle it; or, we decided to allow the read (usually, due to the MEMCLOAK_OPT_ALLOW_INTERNAL option). |
Definition at line 197 of file memcloak.c.
Referenced by IntMemClkCloakRegion().
|
static |
Handles swap-in and swap-outs performed on hidden memory regions.
On swap-in operations, we have to ensure that the patched data is restored. Otherwise, after a swap-out, the original content of the page would be restored, leading to the loss of the patched data.
[in] | Context | The page for which this handler is invoked. |
[in] | VirtualAddress | The guest virtual address for which this handler is invoked. |
[in] | OldEntry | The old page table entry used to translate VirtualAddress. |
[in] | NewEntry | The new page table entry used to translate VirtualAddress. |
[in] | OldPageSize | The old page size. |
[in] | NewPageSize | The new page size. |
Definition at line 64 of file memcloak.c.
Referenced by IntMemClkCloakRegion().
|
static |
Handles writes done inside a hidden memory region.
Each region can have its own write handler that can decide the action that must be taken for this event. If no custom write handler is provided, the write is always blocked, as we don't want our code and data to be changed by the guest. Also, even in situations in which we want to allow writes, we must place an EPT write hook for the hidden pages as removing only the read permission from the EPT will cause the EPT rights to be write-execute, which is an invalid combination.
[in] | Context | The page for which this handler is invoked. |
[in] | Hook | The hook for which this handler is invoked. It simply passes it further to the custom handler, if one exists. |
[in] | Address | The physical address accessed. |
[out] | Action | The action that must be taken. The default value is introGuestNotAllowed for regions that do not have a custom write handler. |
Definition at line 467 of file memcloak.c.
Referenced by IntMemClkCloakRegion().
INTSTATUS IntMemClkHashRegion | ( | QWORD | VirtualAddress, |
QWORD | PhysicalAddress, | ||
DWORD | Size, | ||
DWORD * | Crc32 | ||
) |
Hashes the contents of a cloaked memory page.
The algorithm used for hashing is the one used by Crc32ComputeFast.
[in] | VirtualAddress | The virtual address of the start of the region.. |
[in] | PhysicalAddress | The physical address to which VirtualAddress translates to. |
[in] | Size | The size of the hashed buffer. This must not be larger than PAGE_SIZE. |
[out] | Crc32 | The crc32 of the hashed region. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_INVALID_PARAMETER_3 | is the hashed region crosses a page boundary. |
INT_STATUS_INVALID_PARAMETER_4 | is Crc32 is NULL. |
Definition at line 1005 of file memcloak.c.
Referenced by IntHookGvaDisableHooks(), and IntHookGvaEnableHooks().
Checks if a guest virtual address is located inside a cloak region.
[in] | Cloak | The cloak handle. This is obtained from IntMemClkCloakRegion |
[in] | Ptr | The guest virtual address to be checked. |
True | if Ptr is inside the cloak region |
False | if Ptr is not inside the cloak region or if Cloak is NULL. |
Definition at line 1089 of file memcloak.c.
Referenced by IntVeIsPtrInAgent().
Modifies the internal copy of the original data buffer held by a cloak region.
This will change the contents of the MEMCLOAK_REGION.OriginalData buffer. This function will not enlarge or shrink the buffer.
[in] | CloakHandle | The cloak handle. This is returned by IntMemClkCloakRegion when a new cloak is set. |
[in] | Offset | Offset inside the data buffer at which the change will be done. |
[in] | Size | The size of the modified chunk. |
[in] | Data | The new data. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_INVALID_PARAMETER_1 | is CloakHandle is NULL. |
INT_STATUS_INVALID_PARAMETER_2 | is Offset is outside the region's size. |
INT_STATUS_INVALID_PARAMETER_3 | if Size (or the Size and Offset combination) make the write go beyond the size of the region. |
INT_STATUS_INVALID_PARAMETER_4 | is Data is NULL. |
Definition at line 734 of file memcloak.c.
Referenced by IntDetHandleWrite().
INTSTATUS IntMemClkModifyPatchedData | ( | void * | CloakHandle, |
DWORD | Offset, | ||
DWORD | Size, | ||
const void * | Data | ||
) |
Modifies the patched data inside the guest memory.
This will also change the contents of the MEMCLOAK_REGION.PatchedData buffer. This function will not enlarge or shrink the buffer. It will run with the VCPUs paused in order to ensure consistency of the patched data, as well as the fact that no thread will start using the data while it is being modified. However, it will not check that no guest threads are already inside the patched section. If this needs to be ensured the thread safeness mechanism exposed by IntThrSafeCheckThreads should be used before calling this function. If the patched memory region is swapped out, the write inside the guest will not be possible. But in those cases, the memory contents will be modified when the pages get swapped back in.
Whenever data that is hidden is modified, this function must be called. We must ensure permanent consistency between the data in memory and the data inside the cloak structure, otherwise we may cause corruptions. We also patch the data in memory ourselves, in order to avoid race conditions/sync issues.
[in] | CloakHandle | The cloak handle. This is returned by IntMemClkCloakRegion when a new cloak is set. |
[in] | Offset | Offset inside the data buffer at which the change will be done. |
[in] | Size | The size of the modified chunk. |
[in] | Data | The new data. If it is NULL, the buffer will be zeroed.. |
INT_STATUS_SUCCESS | in case of success. |
INT_STATUS_INVALID_PARAMETER_1 | is CloakHandle is NULL. |
INT_STATUS_INVALID_PARAMETER_2 | is Offset is outside the region's size. |
INT_STATUS_INVALID_PARAMETER_3 | if Size (or the Size and Offset combination) make the write go beyond the size of the region. |
Definition at line 795 of file memcloak.c.
Referenced by IntDetDisableWinHypercall(), IntDetEnableHypercall(), and IntDetModifyPublicData().
Removes a cloak region, making the original memory contents available again to the guest.
This is a thin wrapper over IntMemClkUncloakRegionInternal that does some parameter validation..
[in] | CloakHandle | The handle of the cloaked region. This is obtained from IntMemClkCloakRegion. |
[in] | Options | Options that control the way accesses to the memory region are handled. Must be 0 or a combination of MEMCLOAK_OPTIONS values. |
INT_STATUS_SUCCESS | if successful, or an appropriate INTSTATUS error value. |
INT_STATUS_INVALID_PARAMETER_2 | if CloakHandle is NULL. |
Definition at line 970 of file memcloak.c.
Referenced by IntDetRemoveBranch(), IntDetRemoveHandler(), IntLixAgentStart(), IntLixGuestUnhookGuestCode(), IntMtblDisable(), IntMtblRemoveEntry(), IntPtiDeleteInstruction(), IntPtiUnhookPtFilter(), IntSwapgsDisable(), IntSwapgsUninit(), IntVeUnhookVeAgent(), IntWinAgentHandleBreakpointAgent(), IntWinAgentHandleLoader1Hypercall(), IntWinAgentRemove(), and IntWinAgentUnInit().
|
static |
Removes a cloak region, making the original memory contents available again to the guest.
This function will undo any changes made to the cloaked memory region, as well as free any resources held by the region. It will remove Region from the gMemClkRegions list, will write the MEMCLOAK_REGION.OriginalData buffer back to the guest if the MEMCLOAK_OPT_APPLY_PATCH option is used, will remove the EPT hooks set for the region and will free the internal buffers. Restoring the original contents of the memory is done with the VCPUs paused in order to ensure consistency of the data as well as the fact that no thread will start using the data while it is being modified. However, it will not check that no guest threads are already inside the patched section. If this needs to be ensured, the thread safeness mechanism exposed by IntThrSafeCheckThreads should be used before calling this function.
[in] | Options | Options that control the way accesses to the memory region are handled. Must be 0 or a combination of MEMCLOAK_OPTIONS values. |
[in,out] | Region | The region to be removed. This pointer will no longer be valid after this function returns. |
Definition at line 885 of file memcloak.c.
Referenced by IntMemClkCloakRegion(), IntMemClkUncloakRegion(), and IntMemClkUnInit().
INTSTATUS IntMemClkUnInit | ( | void | ) |
Uninits the memory cloak subsystem.
This is used when introcore unloads and free any internal resources as well as check if there are still cloak regions set. During a normal unload process, when this function is called, there should be no remaining regions set, as whoever sets them is responsible of undoing any changes it has done. However, in that case the remaining regions will be uncloaked, but that may leave the guest in an unstable guest and no other subsystem should depend on this behavior.
INT_STATUS_SUCCESS | always. |
Definition at line 1169 of file memcloak.c.
Referenced by IntGuestUninit().
|
static |
A list containing all the memory regions that are currently hidden from the guest.
Definition at line 54 of file memcloak.c.