Bitdefender Hypervisor Memory Introspection
|
#include "winstack.h"
#include "decoder.h"
#include "drivers.h"
#include "guests.h"
#include "introcpu.h"
#include "winpe.h"
#include "winummodule.h"
#include "winthread.h"
#include "swapmem.h"
Go to the source code of this file.
Macros | |
#define | TRAPFRAME_MAX_ITERATIONS 0x100 |
Functions | |
static INTSTATUS | IntStackAnalyzePointer (QWORD Gva, QWORD *CallAddress) |
Get the address of the kernel function that was called in order to push Gva on the stack as a return address. More... | |
static INTSTATUS | IntWinStackTraceGet64 (QWORD Rsp, QWORD Rip, DWORD MaxTraces, QWORD Flags, STACK_TRACE *StackTrace) |
Get a kernel stack trace starting from the current stack pointer for 64 bit systems. More... | |
static INTSTATUS | IntWinStackTraceGet32 (DWORD Stack, DWORD Eip, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace) |
Get a kernel stack trace starting from the current stack pointer for 32 bit systems. More... | |
INTSTATUS | IntWinStackTraceGet (QWORD StackFrame, QWORD Rip, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace) |
Get a kernel stack trace starting from the current stack pointer for 64 bit systems. More... | |
static INTSTATUS | IntWinStackTraceGetUser32 (PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace) |
Get the user stack trace of a 32 bit windows process. More... | |
static INTSTATUS | IntWinStackTraceGetUser64 (PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, QWORD Remaining, STACK_TRACE *StackTrace) |
Get the user stack trace of a 64 bit windows process. More... | |
static INTSTATUS | IntWinStackHandleUserStackPagedOut (WIN_PROCESS_OBJECT *Process, QWORD *Remaining) |
Handles the case when the stack is needed but is swapped out. More... | |
INTSTATUS | IntWinStackTraceGetUser (PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace) |
Get the user stack trace of a windows process. More... | |
INTSTATUS | IntWinStackUserCheckIsPivoted (QWORD UserRsp, DWORD SegCs, BOOLEAN IsWow64Stack, DPI_EXTRA_INFO *DpiExtraInfo, BOOLEAN *IsPivoted) |
Check whether the stack is pivoted by checking if it's in the bounds of the stack base and limit from the TIB. More... | |
static INTSTATUS | IntWinStackUserTrapFrameGet64 (QWORD KernelStack, DPI_EXTRA_INFO *DpiExtraInfo, KTRAP_FRAME64 *TrapFrame) |
Get a 64 bit trap frame from a kernel stack. More... | |
static INTSTATUS | IntWinStackUserTrapFrameGet32 (DWORD KernelStack, DPI_EXTRA_INFO *DpiExtraInfo, KTRAP_FRAME32 *TrapFrame) |
Get a 32 bit trap frame from a kernel stack. More... | |
INTSTATUS | IntWinStackUserTrapFrameGetGeneric (QWORD *UserRsp, DWORD *SegCs, BOOLEAN Fallback, DPI_EXTRA_INFO *DpiExtraInfo) |
Get a bit trap frame from a kernel stack. More... | |
INTSTATUS | IntWinStackWow64CheckIsPivoted (WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *RealParent, DPI_EXTRA_INFO *DpiExtraInfo) |
Check whether a wow64 process' stack is pivoted. More... | |
BOOLEAN | IntWinIsUmTrapFrame (void *TrapFrame) |
Checks whether a TrapFrame is valid or not. More... | |
#define TRAPFRAME_MAX_ITERATIONS 0x100 |
Definition at line 16 of file winstack.c.
Referenced by IntWinStackUserTrapFrameGetGeneric().
Get the address of the kernel function that was called in order to push Gva on the stack as a return address.
[in] | Gva | The return address. |
[out] | CallAddress | The address of the called function. |
TRACE("[STACK] Op type not supported: %d\n", instruction.Operands[0].Type);
Definition at line 20 of file winstack.c.
Referenced by IntWinStackTraceGet32(), and IntWinStackTraceGet64().
BOOLEAN IntWinIsUmTrapFrame | ( | void * | TrapFrame | ) |
Checks whether a TrapFrame is valid or not.
[in] | TrapFrame | Pointer to a trap frame to be checked. |
Definition at line 2283 of file winstack.c.
Referenced by IntWinStackUserTrapFrameGet32(), IntWinStackUserTrapFrameGet64(), and IntWinStackUserTrapFrameGetGeneric().
|
static |
Handles the case when the stack is needed but is swapped out.
When checking for the return modules in some certain cases, such as writes from memcpy-like functions, we will need the return module in order to match the exceptions, as the caller should be excepted instead of the memcpy function. But, in the case when the stack is swapped out, we would most probably raise some false positives, as the return module cannot be fetched and the exceptions will not match on these violations. For this purpose, when the exception mechanism returns INT_STATUS_STACK_SWAPPED_OUT, this function should be called. This function will check if the stack is inside the known limits (fetched from TIB), and will inject a page-fault in order to force the OS to swap in the stack. The caller must retry the instruction which caused the violation when this function succeeds, as, on retrying, the stack should be in memory. Note that, sometimes we would need the next page as well in order to get a correct stack trace. For this purpose, we will get the current VAD containing the stack and inject a page fault either up until the end of the VAD, or up until the next page after the one containing the RSP. If there doesn't exist such a VAD then we will not inject any page faults, so the presence of a VAD for the current stack is also a form of validation.
[in] | Process | The process in which the stack swapped out corner case took place. |
[out] | Remaining | If the function succeeds, will contain the number of bytes which are accessible starting from the current RSP. |
INT_STATUS_SUCCESS | On success. |
INT_STATUS_INVALID_DATA_VALUE | If the stack is a kernel pointer. |
INT_STATUS_NOT_NEEDED_HINT | If we are in the context of another process, in the case of shared memory, indicating that no action needs to be done for this process. |
INT_STATUS_STACK_SWAPPED_OUT | If a #PF was injected, either for the TIB or the stack, signaling that the current instruction must be retried. |
Definition at line 1462 of file winstack.c.
Referenced by IntWinStackTraceGetUser().
INTSTATUS IntWinStackTraceGet | ( | QWORD | StackFrame, |
QWORD | Rip, | ||
DWORD | MaxNumberOfTraces, | ||
QWORD | Flags, | ||
STACK_TRACE * | StackTrace | ||
) |
Get a kernel stack trace starting from the current stack pointer for 64 bit systems.
[in] | StackFrame | The current stack frame (EBP on x86, RSP on x86_64). |
[in] | Rip | The current instruction pointer ( ignored on x86). |
[in] | MaxNumberOfTraces | Maximum number of stack traces to get. |
[in] | Flags | Can be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 1164 of file winstack.c.
Referenced by IntExceptWinKernelGetOriginator().
|
static |
Get a kernel stack trace starting from the current stack pointer for 32 bit systems.
Simplest algorithm. EBP[0] = next stack frame, EBP[1] = return address, EBP[2..] = parameters
If the function doesn't use the x86 stack convention, will just skip it... Either way, the old method failed too if the EBP wasn't used as a stack pointer. From what I saw, the windows kernel drivers are respecting the stack convention. If it fails for a 3rd party driver, we will have no way but to except it through exceptions.bin.
[in] | Stack | Stack frame pointer from where to start searching. |
[in] | Eip | Instruction pointer from where to start searching. |
[in] | MaxNumberOfTraces | Maximum number of stack traces to get. |
[in] | Flags | Can be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 985 of file winstack.c.
Referenced by IntWinStackTraceGet().
|
static |
Get a kernel stack trace starting from the current stack pointer for 64 bit systems.
This is the same method WinDbg uses. It parses the internal windows structures _RUNTIME_FUNCTION and _UNWIND_INFO to see how may stack space each function needs (just the prologue which contains push registers and sub rsp, value). A further check it's still needed because we don't know how many parameters each function has on the stack.
[in] | Rsp | Stack frame pointer from where to start searching. |
[in] | Rip | Instruction pointer from where to start searching. |
[in] | MaxTraces | Maximum number of stack traces to get. |
[in] | Flags | Can be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 208 of file winstack.c.
Referenced by IntWinStackTraceGet().
INTSTATUS IntWinStackTraceGetUser | ( | PIG_ARCH_REGS | Registers, |
PWIN_PROCESS_OBJECT | Process, | ||
DWORD | MaxNumberOfTraces, | ||
STACK_TRACE * | StackTrace | ||
) |
Get the user stack trace of a windows process.
[in] | Registers | Pointer to a structure containing registers of the current CPU. |
[in] | Process | Pointer to the process from which to get the stack trace. |
[in] | MaxNumberOfTraces | Maximum number of stack traces to get. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 1604 of file winstack.c.
Referenced by IntExceptUserGetExecOriginator(), and IntExceptUserHandleMemoryFunctions().
|
static |
Get the user stack trace of a 32 bit windows process.
[in] | Registers | Pointer to a structure containing registers of the current CPU. |
[in] | Process | Pointer to the process from which to get the stack trace. |
[in] | MaxNumberOfTraces | Maximum number of stack traces to get. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 1195 of file winstack.c.
Referenced by IntWinStackTraceGetUser().
|
static |
Get the user stack trace of a 64 bit windows process.
[in] | Registers | Pointer to a structure containing registers of the current CPU. |
[in] | Process | Pointer to the process from which to get the stack trace. |
[in] | MaxNumberOfTraces | Maximum number of stack traces to get. |
[in] | Remaining | Number of bytes that can be accessed starting from the current RSP. |
[in,out] | StackTrace | A caller initialized STACK_TRACE structure that will hold the stack trace. |
Definition at line 1361 of file winstack.c.
Referenced by IntWinStackTraceGetUser().
INTSTATUS IntWinStackUserCheckIsPivoted | ( | QWORD | UserRsp, |
DWORD | SegCs, | ||
BOOLEAN | IsWow64Stack, | ||
DPI_EXTRA_INFO * | DpiExtraInfo, | ||
BOOLEAN * | IsPivoted | ||
) |
Check whether the stack is pivoted by checking if it's in the bounds of the stack base and limit from the TIB.
[in] | UserRsp | The current user stack pointer. |
[in] | SegCs | The CS selector, can be any of the CODE_SEG_UM_32_GUEST_64, CODE_SEG_UM_64_GUEST_64, or CODE_SEG_UM_32_GUEST_32. |
[in] | IsWow64Stack | True if this is a Wow64 stack. |
[in,out] | DpiExtraInfo | Pointer to a caller allocated DPI_EXTRA_INFO structure that will have the stack base and limit fields set upon success. |
[out] | IsPivoted | Will be set to TRUE if the stack is pivoted, FALSE otherwise. |
Definition at line 1741 of file winstack.c.
Referenced by IntWinDpiValidatePivotedStack(), and IntWinStackWow64CheckIsPivoted().
|
static |
Get a 32 bit trap frame from a kernel stack.
Will parse the current KM stack for the trap frame. We will check some fields in TrapFrame to validate it.
[in] | KernelStack | The kernel stack from which to start searching for the trap frame. |
[in,out] | DpiExtraInfo | Pointer to a caller allocated DPI_EXTRA_INFO structure. It will have the DpiPivotedStackExtraInfo.TrapFrameAddress set accordingly upon success. |
[out] | TrapFrame | Pointer to a caller allocated KTRAP_FRAME32 structure that will hold the trap frame. |
Definition at line 1942 of file winstack.c.
Referenced by IntWinStackUserTrapFrameGetGeneric().
|
static |
Get a 64 bit trap frame from a kernel stack.
Will parse the current KM stack for the trap frame. We will check some fields in TrapFrame to validate it.
[in] | KernelStack | The kernel stack from which to start searching for the trap frame. |
[in,out] | DpiExtraInfo | Pointer to a caller allocated DPI_EXTRA_INFO structure. It will have the DpiPivotedStackExtraInfo.TrapFrameAddress set accordingly upon success. |
[out] | TrapFrame | Pointer to a caller allocated KTRAP_FRAME64 structure that will hold the trap frame. |
Definition at line 1865 of file winstack.c.
Referenced by IntWinStackUserTrapFrameGetGeneric().
INTSTATUS IntWinStackUserTrapFrameGetGeneric | ( | QWORD * | UserRsp, |
DWORD * | SegCs, | ||
BOOLEAN | Fallback, | ||
DPI_EXTRA_INFO * | DpiExtraInfo | ||
) |
Get a bit trap frame from a kernel stack.
Will also set the DpiExtraInfo DpiPivotedStackExtraInfo.TrapFrameAddress and DpiPivotedStackExtraInfo.CurrentStack fields accordingly upon success.
[out] | UserRsp | Will hold the current user space stack pointer. |
[out] | SegCs | Will be set to any of the CODE_SEG_UM_32_GUEST_64, CODE_SEG_UM_64_GUEST_64, or CODE_SEG_UM_32_GUEST_32 accordingly. |
[in] | Fallback | If TRUE and we fail getting a valid trap frame, will search on the user stack. |
[in,out] | DpiExtraInfo | Pointer to a caller allocated DPI_EXTRA_INFO structure. |
Definition at line 2020 of file winstack.c.
Referenced by IntWinDpiValidatePivotedStack().
INTSTATUS IntWinStackWow64CheckIsPivoted | ( | WIN_PROCESS_OBJECT * | Process, |
WIN_PROCESS_OBJECT * | RealParent, | ||
DPI_EXTRA_INFO * | DpiExtraInfo | ||
) |
Check whether a wow64 process' stack is pivoted.
Will set the CreationInfo field of the Process accordingly upon success.
[in] | Process | The process whose stack to be checked. |
[in] | RealParent | The process' parent. |
[in,out] | DpiExtraInfo | Pointer to a caller allocated DPI_EXTRA_INFO structure. |
Definition at line 2203 of file winstack.c.
Referenced by IntWinDpiValidatePivotedStack().