Bitdefender Hypervisor Memory Introspection
winstack.c File Reference
#include "winstack.h"
#include "decoder.h"
#include "drivers.h"
#include "guests.h"
#include "introcpu.h"
#include "winpe.h"
#include "winummodule.h"
#include "winthread.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, STACK_TRACE *StackTrace)
 Get the user stack trace of a 64 bit windows process. 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...
 

Macro Definition Documentation

◆ TRAPFRAME_MAX_ITERATIONS

#define TRAPFRAME_MAX_ITERATIONS   0x100

Definition at line 15 of file winstack.c.

Referenced by IntWinStackUserTrapFrameGetGeneric().

Function Documentation

◆ IntStackAnalyzePointer()

static INTSTATUS IntStackAnalyzePointer ( QWORD  Gva,
QWORD CallAddress 
)
static

Get the address of the kernel function that was called in order to push Gva on the stack as a return address.

Parameters
[in]GvaThe return address.
[out]CallAddressThe address of the called function.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

TRACE("[STACK] Op type not supported: %d\n", instruction.Operands[0].Type);

Definition at line 19 of file winstack.c.

Referenced by IntWinStackTraceGet64().

◆ IntWinIsUmTrapFrame()

BOOLEAN IntWinIsUmTrapFrame ( void *  TrapFrame)

Checks whether a TrapFrame is valid or not.

Parameters
[in]TrapFramePointer to a trap frame to be checked.
Returns
TRUE if the trap frame is valid, FALSE otherwise.

Definition at line 2173 of file winstack.c.

Referenced by IntWinStackUserTrapFrameGet32(), IntWinStackUserTrapFrameGet64(), and IntWinStackUserTrapFrameGetGeneric().

◆ IntWinStackTraceGet()

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.

Parameters
[in]StackFrameThe current stack frame (EBP on x86, RSP on x86_64).
[in]RipThe current instruction pointer ( ignored on x86).
[in]MaxNumberOfTracesMaximum number of stack traces to get.
[in]FlagsCan be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1210 of file winstack.c.

Referenced by IntExceptWinKernelGetOriginator().

◆ IntWinStackTraceGet32()

static INTSTATUS IntWinStackTraceGet32 ( DWORD  Stack,
DWORD  Eip,
DWORD  MaxNumberOfTraces,
QWORD  Flags,
STACK_TRACE StackTrace 
)
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.

Parameters
[in]StackStack frame pointer from where to start searching.
[in]EipInstruction pointer from where to start searching.
[in]MaxNumberOfTracesMaximum number of stack traces to get.
[in]FlagsCan be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1042 of file winstack.c.

Referenced by IntWinStackTraceGet().

◆ IntWinStackTraceGet64()

static INTSTATUS IntWinStackTraceGet64 ( QWORD  Rsp,
QWORD  Rip,
DWORD  MaxTraces,
QWORD  Flags,
STACK_TRACE StackTrace 
)
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.

Parameters
[in]RspStack frame pointer from where to start searching.
[in]RipInstruction pointer from where to start searching.
[in]MaxTracesMaximum number of stack traces to get.
[in]FlagsCan be either STACK_FLG_ONLY_DRIVER_ADDRS or STACK_FLG_FAST_GET.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 274 of file winstack.c.

Referenced by IntWinStackTraceGet().

◆ IntWinStackTraceGetUser()

INTSTATUS IntWinStackTraceGetUser ( PIG_ARCH_REGS  Registers,
PWIN_PROCESS_OBJECT  Process,
DWORD  MaxNumberOfTraces,
STACK_TRACE StackTrace 
)

Get the user stack trace of a windows process.

Parameters
[in]RegistersPointer to a structure containing registers of the current CPU.
[in]ProcessPointer to the process from which to get the stack trace.
[in]MaxNumberOfTracesMaximum number of stack traces to get.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1502 of file winstack.c.

Referenced by IntExceptUserGetExecOriginator(), and IntExceptUserHandleMemoryFunctions().

◆ IntWinStackTraceGetUser32()

static INTSTATUS IntWinStackTraceGetUser32 ( PIG_ARCH_REGS  Registers,
PWIN_PROCESS_OBJECT  Process,
DWORD  MaxNumberOfTraces,
STACK_TRACE StackTrace 
)
static

Get the user stack trace of a 32 bit windows process.

Parameters
[in]RegistersPointer to a structure containing registers of the current CPU.
[in]ProcessPointer to the process from which to get the stack trace.
[in]MaxNumberOfTracesMaximum number of stack traces to get.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1241 of file winstack.c.

Referenced by IntWinStackTraceGetUser().

◆ IntWinStackTraceGetUser64()

static INTSTATUS IntWinStackTraceGetUser64 ( PIG_ARCH_REGS  Registers,
PWIN_PROCESS_OBJECT  Process,
DWORD  MaxNumberOfTraces,
STACK_TRACE StackTrace 
)
static

Get the user stack trace of a 64 bit windows process.

Parameters
[in]RegistersPointer to a structure containing registers of the current CPU.
[in]ProcessPointer to the process from which to get the stack trace.
[in]MaxNumberOfTracesMaximum number of stack traces to get.
[in,out]StackTraceA caller initialized STACK_TRACE structure that will hold the stack trace.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1407 of file winstack.c.

Referenced by IntWinStackTraceGetUser().

◆ IntWinStackUserCheckIsPivoted()

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.

Parameters
[in]UserRspThe current user stack pointer.
[in]SegCsThe 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]IsWow64StackTrue if this is a Wow64 stack.
[in,out]DpiExtraInfoPointer to a caller allocated DPI_EXTRA_INFO structure that will have the stack base and limit fields set upon success.
[out]IsPivotedWill be set to TRUE if the stack is pivoted, FALSE otherwise.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1631 of file winstack.c.

Referenced by IntWinDpiValidatePivotedStack(), and IntWinStackWow64CheckIsPivoted().

◆ IntWinStackUserTrapFrameGet32()

static INTSTATUS IntWinStackUserTrapFrameGet32 ( DWORD  KernelStack,
DPI_EXTRA_INFO DpiExtraInfo,
KTRAP_FRAME32 TrapFrame 
)
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.

Parameters
[in]KernelStackThe kernel stack from which to start searching for the trap frame.
[in,out]DpiExtraInfoPointer to a caller allocated DPI_EXTRA_INFO structure. It will have the DpiPivotedStackExtraInfo.TrapFrameAddress set accordingly upon success.
[out]TrapFramePointer to a caller allocated KTRAP_FRAME32 structure that will hold the trap frame.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1832 of file winstack.c.

Referenced by IntWinStackUserTrapFrameGetGeneric().

◆ IntWinStackUserTrapFrameGet64()

static INTSTATUS IntWinStackUserTrapFrameGet64 ( QWORD  KernelStack,
DPI_EXTRA_INFO DpiExtraInfo,
KTRAP_FRAME64 TrapFrame 
)
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.

Parameters
[in]KernelStackThe kernel stack from which to start searching for the trap frame.
[in,out]DpiExtraInfoPointer to a caller allocated DPI_EXTRA_INFO structure. It will have the DpiPivotedStackExtraInfo.TrapFrameAddress set accordingly upon success.
[out]TrapFramePointer to a caller allocated KTRAP_FRAME64 structure that will hold the trap frame.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1755 of file winstack.c.

Referenced by IntWinStackUserTrapFrameGetGeneric().

◆ 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.

Parameters
[out]UserRspWill hold the current user space stack pointer.
[out]SegCsWill 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]FallbackIf TRUE and we fail getting a valid trap frame, will search on the user stack.
[in,out]DpiExtraInfoPointer to a caller allocated DPI_EXTRA_INFO structure.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 1910 of file winstack.c.

Referenced by IntWinDpiValidatePivotedStack().

◆ IntWinStackWow64CheckIsPivoted()

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.

Parameters
[in]ProcessThe process whose stack to be checked.
[in]RealParentThe process' parent.
[in,out]DpiExtraInfoPointer to a caller allocated DPI_EXTRA_INFO structure.
Returns
INT_STATUS_SUCCESS if successful, or an appropriate INTSTATUS error value.

Definition at line 2093 of file winstack.c.

Referenced by IntWinDpiValidatePivotedStack().