Bitdefender Hypervisor Memory Introspection
|
#include "introtypes.h"
Go to the source code of this file.
Macros | |
#define | SWAPMEM_FLAG_ASYNC_CALL 0x00000001 |
#define | SWAPMEM_FLAG_ENTRY_XD 0x00000002 |
#define | SWAPMEM_OPT_NO_FAULT 0x00000001 |
If set, no PF will be injected. Introcore will wait for the pages to be naturally swapped in. More... | |
#define | SWAPMEM_OPT_UM_FAULT 0x00000002 |
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory. More... | |
#define | SWAPMEM_OPT_KM_FAULT 0x00000004 |
#define | SWAPMEM_OPT_BP_FAULT 0x00000010 |
If set, the #PF will be generated from an int3 detour. Use this when injecting kernel PFs. More... | |
#define | SWAPMEM_OPT_RW_FAULT 0x00000020 |
If set, the PF will be generated with write access. Useful when CoW must be done. More... | |
#define | SWAPMEM_OPT_NO_DUPS 0x80000000 |
If set, will make sure that a single PF is scheduled for this page. More... | |
Typedefs | |
typedef INTSTATUS(* | PFUNC_PagesReadCallback) (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags) |
Called when all the required data is available. More... | |
typedef INTSTATUS(* | PFUNC_PreInjectCallback) (void *Context, QWORD Cr3, QWORD VirtualAddress) |
Called before injecting a PF inside the guest. More... | |
Functions | |
INTSTATUS | IntSwapMemReadData (QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle) |
Reads a region of guest virtual memory, and calls the indicated callback when all the data is available. More... | |
INTSTATUS | IntSwapMemInjectPendingPF (void) |
Inject a PF for a pending page. More... | |
void | IntSwapMemCancelPendingPF (QWORD VirtualAddress) |
Cancel a pending PF. More... | |
void | IntSwapMemReinjectFailedPF (void) |
Reinject timed-out PFs. More... | |
INTSTATUS | IntSwapMemRemoveTransaction (void *Transaction) |
Remove a transaction. More... | |
INTSTATUS | IntSwapMemRemoveTransactionsForVaSpace (QWORD Cr3) |
Remove all transactions initiated for a virtual address space. More... | |
INTSTATUS | IntSwapMemInit (void) |
Init the swapmem system. More... | |
INTSTATUS | IntSwapMemUnInit (void) |
Uninit the swapmem system. More... | |
void | IntSwapMemDump (void) |
Dump all active transactions & pages. More... | |
#define SWAPMEM_FLAG_ASYNC_CALL 0x00000001 |
This means that the callback was invoked after a PF injection. Otherwise, the callback has been invoked before returning from the IntSwapMemRead function.
Definition at line 12 of file swapmem.h.
Referenced by IntSwapMemPageSwappedIn(), IntWinGuestSectionInMemory(), IntWinHalSectionInMemory(), IntWinObjHandleDriverDirectoryEntryInMemory(), IntWinObjHandleObjectInMemory(), and IntWinObjParseDriverDirectory().
#define SWAPMEM_FLAG_ENTRY_XD 0x00000002 |
If set, than the newly mounted entry is installed as XD. This will be set if any page inside the read area is XD.
Definition at line 15 of file swapmem.h.
Referenced by IntSwapMemPageSwappedIn(), and IntSwapMemReadData().
#define SWAPMEM_OPT_BP_FAULT 0x00000010 |
If set, the #PF will be generated from an int3 detour. Use this when injecting kernel PFs.
Definition at line 27 of file swapmem.h.
Referenced by IntSwapMemInjectPendingPF(), IntWinGuestFindDriversNamespace(), IntWinGuestNew(), IntWinGuestReadKernel(), IntWinHalFindPerformanceCounter(), IntWinHalReadHal(), IntWinObjHandleDirectoryEntryInMemory(), IntWinObjHandleDriverDirectoryEntryInMemory(), IntWinObjHandleObjectInMemory(), IntWinObjHandleRootDirTagInMemory(), IntWinObjParseDriverDirectory(), and IntWinVadFetchImageName().
#define SWAPMEM_OPT_KM_FAULT 0x00000004 |
If set, the PF must be injected only while in kernel-mode. Use it when reading kernel-mode memory. Note, however, that the PF will be injected as soon as possible, and may result in a bug-check. It is recommended to use SWAPMEM_OPT_BP_FAULT instead.
Definition at line 25 of file swapmem.h.
Referenced by IntSwapMemInjectPendingPF().
#define SWAPMEM_OPT_NO_DUPS 0x80000000 |
If set, will make sure that a single PF is scheduled for this page.
Definition at line 31 of file swapmem.h.
Referenced by IntSwapMemReadData(), IntWinStackHandleUserStackPagedOut(), and IntWinVadIsExecSuspicious().
#define SWAPMEM_OPT_NO_FAULT 0x00000001 |
If set, no PF will be injected. Introcore will wait for the pages to be naturally swapped in.
Definition at line 19 of file swapmem.h.
Referenced by IntSwapMemInjectPendingPF(), and IntWinDrvProtect().
#define SWAPMEM_OPT_RW_FAULT 0x00000020 |
If set, the PF will be generated with write access. Useful when CoW must be done.
Definition at line 29 of file swapmem.h.
Referenced by IntSwapMemInjectPendingPF(), IntSwapMemReadData(), and IntWinDagentHandleVerifierReason().
#define SWAPMEM_OPT_UM_FAULT 0x00000002 |
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory.
Definition at line 21 of file swapmem.h.
Referenced by IntSwapMemInjectPendingPF(), IntWinDagentCheckSuspiciousDllLoad(), IntWinDagentHandleVerifierReason(), IntWinGetPrcoCmdLineHandleCmdLineInMemory(), IntWinGetPrcoCmdLineHandleUserParamsInMemory(), IntWinModBlockBlockModuleLoad(), IntWinModHandleModulePathInMemory(), IntWinProcReadCommandLine(), IntWinStackHandleUserStackPagedOut(), IntWinUmModCacheFillExports(), and IntWinVadIsExecSuspicious().
typedef INTSTATUS(* PFUNC_PagesReadCallback) (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags) |
Called when all the required data is available.
This callback is called as soon as all the data has been read from guest memory. The callback may be called even before returning from IntSwapMemReadData, if all the pages are present in physical memory. If at least one page is missing, the callback will be called later, after the pages have been swapped in, and all the data has been read.
[in] | Context | Optional context, as passed to the IntSwapMemReadData function. |
[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. |
Called before injecting a PF inside the guest.
This callback is called before injecting a PF inside the guest. If it returns INT_STATUS_NOT_NEEDED_HINT, the PF will no longer be injected. This may be useful if the caller wishes to inhibit PF injection in certain cases (for example, you may want to check the existence of a VAD before injecting a PF for a newly loaded module). NOTE: This callback is optional. If it is not used, the PF will be injected as soon as possible, when the scheduler decides it is safe.
[in] | Context | Context, as passed to the IntSwapMemReadData function. |
[in] | Cr3 | The virtual address space. |
[in] | VirtualAddress | The address the PF is about to be injected for. |
INT_STATUS_NOT_NEEDED_HINT | If the PF should not be injected. |
void IntSwapMemCancelPendingPF | ( | QWORD | VirtualAddress | ) |
Cancel a pending PF.
Cancel the pending PF on the provided VirtualAddress. This can happen if we requested a PF injection, but the HV had to inject something else. In this case, we cancel the injection, and we mark the page Ready, allowing it to be re-injected later.
[in] | VirtualAddress | The virtual address the PF was requested for. |
Definition at line 879 of file swapmem.c.
Referenced by IntHandleEventInjection(), and IntSwapMemHandleBreakpointAgent().
void IntSwapMemDump | ( | void | ) |
INTSTATUS IntSwapMemInit | ( | void | ) |
Init the swapmem system.
INT_STATUS_SUCCESS | On success. |
Definition at line 1026 of file swapmem.c.
Referenced by IntGuestInit().
INTSTATUS IntSwapMemInjectPendingPF | ( | void | ) |
Inject a PF for a pending page.
This is the main PF scheduling algorithm. This is called before returning from every callback, and it checks the list of existing transactions & pages, in order to inject a PF inside the guest. Note that only a single PF can be injected at any given time (even if we have multiple VCPUs), as this makes the scheduler much simpler, and it avoids spamming the guest kernel with unexpected PFs. Before injecting a PF, it makes sure the context is right (user/kernel, CR3), and it calls the PreInjectCallback; of the PreInject callback does not return INT_STATUS_SUCCESS, the PF for that page will not be injected, and another page will be selected. PFs can be either injected directly (user-mode PFs, when the context is right) or indirectly (kernel-mode PFs) via the breakpoint agent. No other PFs will be injected until the pending one has been handled (the page has been swapped in).
INT_STATUS_SUCCESS | On success. |
Definition at line 698 of file swapmem.c.
Referenced by IntGuestPreReturnCallback().
INTSTATUS IntSwapMemReadData | ( | QWORD | Cr3, |
QWORD | VirtualAddress, | ||
DWORD | Length, | ||
DWORD | Options, | ||
void * | Context, | ||
DWORD | ContextTag, | ||
PFUNC_PagesReadCallback | Callback, | ||
PFUNC_PreInjectCallback | PreInject, | ||
void ** | SwapHandle | ||
) |
Reads a region of guest virtual memory, and calls the indicated callback when all the data is available.
The function will read Length bytes from VirtualAddress inside Cr3 address space. The function may either read the data directly, if it is present inside the physical memory, or it may inject a page fault in order to force a swap-in of the pages containing the data. Callback will be invoked when all the data has been read. The callback may be invoked synchronously or asynchronously: if a page fault is needed to read parts of the data, it will invoked asynchronously. Otherwise, it will be invoked synchronously. The flag SWAPMEM_FLAG_ASYNC_CALL will be set in the Flags argument of the callback for asynchronously calls. The function can be used to read data of arbitrary length (including data spanning multiple pages). Some pages may be swapped in as a result of us injecting a PF for them, others may be swapped in naturally due to the normal guest activity, and other pages may already be present when calling this function. The PreInject callback will be called before actually injecting a PF inside the guest. This callback is optional, but if it present and it returns INT_STATUS_NOT_NEEDED_HINT, the PF will be inhibited, and therefore, it will not be injected.
[in] | Cr3 | Virtual address space where we wish to read data from. |
[in] | VirtualAddress | Guest virtual address we wish to read from. |
[in] | Length | Length, in bytes. Can span multiple pages. |
[in] | Options | Options. Check out SWAPMEM_OPT* for more info. |
[in] | Context | Optional context to be passed to the callbacks. |
[in] | ContextTag | If Context is provided and ContextTag is not 0, the Context will be freed when removing the transaction. |
[in] | Callback | Called once all the data is available. |
[in] | PreInject | Callback invoked BEFORE injecting the PF. If this returns INT_STATUS_NOT_NEEDED_HINT, the PF will not be injected. |
[out] | SwapHandle | Contains, upon return, a handle to the swap object. If SWAPMEM_OPT_NO_DUPS is used and a transaction is already present, SwapHandle will be set to NULL. Since the transactions are not reference counted, it would be problematic to return a handle, as it can then get freed more than once. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INSUFFICIENT_RESOURCES | If a memory alloc fails. |
Definition at line 417 of file swapmem.c.
Referenced by DbgSwap(), IntWinDagentCheckSuspiciousDllLoad(), IntWinDagentHandleVerifierReason(), IntWinDrvProtect(), IntWinGetPrcoCmdLineHandleCmdLineInMemory(), IntWinGetPrcoCmdLineHandleUserParamsInMemory(), IntWinGuestFindDriversNamespace(), IntWinGuestNew(), IntWinGuestReadKernel(), IntWinHalFindPerformanceCounter(), IntWinHalReadHal(), IntWinModBlockBlockModuleLoad(), IntWinModHandleModulePathInMemory(), IntWinObjHandleDirectoryEntryInMemory(), IntWinObjHandleDriverDirectoryEntryInMemory(), IntWinObjHandleObjectInMemory(), IntWinObjHandleRootDirTagInMemory(), IntWinObjParseDriverDirectory(), IntWinProcReadCommandLine(), IntWinStackHandleUserStackPagedOut(), IntWinUmModCacheFillExports(), IntWinVadFetchImageName(), and IntWinVadIsExecSuspicious().
void IntSwapMemReinjectFailedPF | ( | void | ) |
Reinject timed-out PFs.
Sometimes, injected PFs may get lost, mainly due to the HV, or may be dropped unexpectedly inside the guest. We detect this by maintaining a time-stamp for each pending PF, and retrying the injection after aprox. 1s. Note that reinjecting a PF more than once is not an issue, as the OS can handle this kind of spurious PFs.
Definition at line 913 of file swapmem.c.
Referenced by IntHandleTimer().
INTSTATUS IntSwapMemRemoveTransaction | ( | void * | Transaction | ) |
Remove a transaction.
Once a transaction is removed, the callback will no longer be called, and the swap hooks will be removed. The data will no longer be available. This should be called, for example, when there is a pending read for a process that is just terminating.
[in] | Transaction | The transaction to be removed. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_PARAMETER | If an invalid parameter is supplied. |
Definition at line 942 of file swapmem.c.
Referenced by IntWinDrvUnprotect(), IntWinGuestCancelKernelRead(), IntWinHalCancelRead(), IntWinModBlockRemoveBlockObject(), IntWinModCancelExportTransactions(), IntWinModRemoveModule(), IntWinObjCancelRootTransactions(), IntWinObjCleanup(), IntWinProcRemoveProcess(), IntWinProcSwapOut(), and IntWinVadDestroyObject().
Remove all transactions initiated for a virtual address space.
Will remove all active transactions for the given VA space. The read-data callback will not be called for any of the aborted transactions. Useful when a process is terminating.
[in] | Cr3 | The virtual address space. |
INT_STATUS_SUCCESS | On success. |
Definition at line 982 of file swapmem.c.
Referenced by IntWinProcRemoveProcess(), and IntWinProcSwapOut().
INTSTATUS IntSwapMemUnInit | ( | void | ) |
Uninit the swapmem system.
INT_STATUS_SUCCESS | On success. |
INT_STATUS_NOT_INITIALIZED_HINT | If the system has not been initialized. |
Definition at line 1044 of file swapmem.c.
Referenced by IntGuestUninit().