HyperDbg/hyperdbg/hyperkd/code/debugger/commands/Callstack.c

142 lines
3.8 KiB
C
Raw Permalink Normal View History

2022-03-05 15:46:03 +03:30
/**
* @file Callstack.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Kernel routines for callstack
2023-01-18 20:23:40 +09:00
* @details
2022-03-05 15:46:03 +03:30
* @version 0.1
* @date 2021-03-05
2023-01-18 20:23:40 +09:00
*
2022-03-05 15:46:03 +03:30
* @copyright This project is released under the GNU Public License v3.
2023-01-18 20:23:40 +09:00
*
2022-03-05 15:46:03 +03:30
*/
#include "pch.h"
2022-03-05 15:46:03 +03:30
/**
* @brief Walkthrough the stack
2023-01-18 20:23:40 +09:00
*
* @param AddressToSaveFrames
* @param FrameCount
2023-01-18 20:23:40 +09:00
* @param StackBaseAddress
* @param Size
* @param Is32Bit
*
2022-03-05 15:46:03 +03:30
* @return BOOLEAN
*/
BOOLEAN
CallstackWalkthroughStack(PDEBUGGER_SINGLE_CALLSTACK_FRAME AddressToSaveFrames,
UINT32 * FrameCount,
2022-03-05 17:32:54 +03:30
UINT64 StackBaseAddress,
2022-03-05 15:46:03 +03:30
UINT32 Size,
BOOLEAN Is32Bit)
{
2022-03-05 17:32:54 +03:30
UINT32 FrameIndex = 0;
UINT16 AddressMode = 0;
2024-03-01 18:11:24 +09:00
UINT64 Value = (UINT64)NULL;
UINT64 CurrentStackAddress = (UINT64)NULL;
2022-03-05 15:46:03 +03:30
if (Size == 0)
{
return FALSE;
}
if (Is32Bit)
{
//
// 32-bit interpretation
//
AddressMode = sizeof(UINT32);
FrameIndex = Size / AddressMode;
}
else
{
//
// 64-bit interpretation
//
AddressMode = sizeof(UINT64);
FrameIndex = Size / AddressMode;
}
//
// Walkthrough the stack
//
for (SIZE_T i = 0; i < FrameIndex; i++)
2022-03-05 15:46:03 +03:30
{
2022-03-05 17:32:54 +03:30
//
// Compute the current stack position address
//
CurrentStackAddress = StackBaseAddress + (i * AddressMode);
*FrameCount = FrameIndex;
2022-03-05 17:32:54 +03:30
2023-04-27 18:21:55 +09:00
if (!CheckAccessValidityAndSafety(CurrentStackAddress, AddressMode))
2022-03-05 15:46:03 +03:30
{
AddressToSaveFrames[i].IsStackAddressValid = FALSE;
//
// Stack is no longer valid or available to access from here
//
if (FrameIndex == 0)
{
//
// Stack is invalid
//
return FALSE;
}
else
{
//
// Stack is invalid, but there are frames that are still valid
//
return TRUE;
}
2022-03-05 15:46:03 +03:30
}
//
// Stack address is valid
//
AddressToSaveFrames[i].IsStackAddressValid = TRUE;
//
// Read the 4 or 8 byte from the target stack
//
2022-03-05 17:32:54 +03:30
MemoryMapperReadMemorySafeOnTargetProcess(CurrentStackAddress, &Value, AddressMode);
2022-03-05 15:46:03 +03:30
//
// Set the value
//
AddressToSaveFrames[i].Value = Value;
//
// This implementation has a problem, if the target jump is between two page were the second
// page is not available, it fails to set it as the valid address,
// We should check it for this page attribute (check boundary) but for now, i'm lazy enough
// to let it unimplemented
//
// Check if value is a valid address
//
2023-04-27 18:21:55 +09:00
if (CheckAccessValidityAndSafety(Value, MAXIMUM_CALL_INSTR_SIZE))
2022-03-05 15:46:03 +03:30
{
//
// It's a valid address
//
AddressToSaveFrames[i].IsValidAddress = TRUE;
2022-03-06 02:43:58 +03:30
//
// Check if the target page has NX bit (executable page)
//
2024-03-01 21:02:52 +09:00
AddressToSaveFrames[i].IsExecutable = MemoryMapperCheckIfPageIsNxBitSetOnTargetProcess((PVOID)Value);
2022-03-06 02:43:58 +03:30
2022-03-05 15:46:03 +03:30
//
// Read the memory at the target address
//
2022-03-06 02:43:58 +03:30
MemoryMapperReadMemorySafeOnTargetProcess(Value - MAXIMUM_CALL_INSTR_SIZE,
AddressToSaveFrames[i].InstructionBytesOnRip,
MAXIMUM_CALL_INSTR_SIZE);
2022-03-05 15:46:03 +03:30
}
}
//
// Stack walk is finished
//
return TRUE;
}