Commands
k, kd, kq (display stack backtrace)
Description of 'k, kd, kq' commands in HyperDbg.

Command

k : show stack backtrace (only calls)
kd : show stack backtrace (calls along with parameters in stack) in 32-bit format
kq : show stack backtrace (calls along with parameters in stack) in 64-bit format

Syntax

k
kd
kq
k [base StackAddress (hex)] [l Length (hex)]
kd [base StackAddress (hex)] [l Length (hex)]
kq [base StackAddress (hex)] [l Length (hex)]

Description

Displays stack backtrace and optionally show the parameter in the stack.

Parameters

[base StackAddress (hex)] (optional)
If you want to specify any address other than the current rsp or esp register, you should set the base address by using this parameter.
[l Length (hex)] (optional)
The length (byte) in hex format.

Examples

The following command shows the callstack of the current thread.
2: kHyperDbg> k
[$+020] fffff80168da7c86 (from <fffff80168da7c86>)
[$+050] fffff80168dafab6 (from <fffff80168dafab6>)
[$+080] fffff801678940aa (from <fffff801678940aa>)
[$+150] fffff8016362af7c (from nt!ObpReferenceObjectByHandleWithTag+0x22c <fffff8016362af7c>)
[$+190] fffff80163252f50 (from nt!IofCallDriver+0x50 <fffff80163252f50>)
[$+1d0] fffff801635fd513 (from nt!IopSynchronousServiceTail+0x1a3 <fffff801635fd513>)
The following command shows the callstack of the current thread along with stack parameters.
2: kHyperDbg> kq
[$+000] 0000000000000000
[$+008] 0000000000000000
[$+010] fffff80168daeb50 (addr <fffff80168daeb50>)
[$+018] 0000000000040246
[$+020] fffff80168da7c86 (from <fffff80168da7c86>)
[$+028] 0000000000000000
[$+030] ffff948cb9a02340 (addr <ffff948cb9a02340>)
[$+038] 0000000100000000
...
[$+150] fffff8016362af7c (from nt!ObpReferenceObjectByHandleWithTag+0x22c <fffff8016362af7c>)
[$+158] 0000000000000001
...
[$+188] ffff948cc291cae0 (addr <ffff948cc291cae0>)
[$+190] fffff80163252f50 (from nt!IofCallDriver+0x50 <fffff80163252f50>)
[$+198] ffff948cbc327760 (addr <ffff948cbc327760>)
[$+1a0] ffff948cc0314a80 (addr <ffff948cc0314a80>)
[$+1a8] ffff930520206f49
[$+1b0] 0000000000000001
[$+1b8] ffff948cbc327760 (addr <ffff948cbc327760>)
[$+1c0] ffff948cc0314b98 (addr <ffff948cc0314b98>)
[$+1c8] ffff948cc291cae0 (addr <ffff948cc291cae0>)
[$+1d0] fffff801635fd513 (from nt!IopSynchronousServiceTail+0x1a3 <fffff801635fd513>)
..
[$+1f8] 0000000000000001
The following command shows the calls along with parameters (the base address is @rbx-10).
2: kHyperDbg> kq base @rbx-10
[$+000] 8d0ac9a500000000
[$+008] 0000000000000edc
[$+010] 0000200000000000
[$+018] 0000000000000000
[$+020] 0000000000000000
[$+028] 0000006700000000
[$+030] 5754444e02060000
[$+038] fa3ced7b5a3515ff
[$+040] 0000000000000000
[$+048] 00000206c1f30004
[$+050] ffff948cc06a9790 (addr <ffff948cc06a9790>)
The following command shows the callstack of the current thread in a 32-bit environment.
0: kHyperDbg> k
[$+004] 00a42274 (from <00a42274>)
[$+008] 7559fa27 (from <7559fa27>)
[$+018] 770775f2 (from <770775f2>)
[$+074] 770775bf (from <770775bf>)
The following command shows the callstack of the current thread along with parameters in a 32-bit environment.
0: kHyperDbg> kd
[$+000] 010ffa18 (addr <010ffa18>)
[$+004] 00a42274 (from <00a42274>)
[$+008] 7559fa27 (from <7559fa27>)
[$+00c] 00f00000 (addr <00f00000>)
[$+010] 7559fa10 (addr <7559fa10>)
[$+014] 010ffa74 (addr <010ffa74>)
[$+018] 770775f2 (from <770775f2>)
[$+01c] 00f00000 (addr <00f00000>)
[$+020] ba49f40e
[$+024] 00000000
[$+028] 00000000
[$+02c] 00f00000 (addr <00f00000>)
[$+030] 00000000
[$+034] 00000000

IOCTL

This commands works over serial by sending the serial packets to the remote computer.
First of all, you should fill the following structure, set the Is32Bitto your target execution context, set the Size and count of frames FrameCount, the base address (setting NULL as based address indicates that debuggee needs the current rsp register as the base address).
After allocating the below structure, you should also allocate as many frames structure (DEBUGGER_SINGLE_CALLSTACK_FRAME) that you want to read from the stack (FrameCount * sizeof(DEBUGGER_SINGLE_CALLSTACK_FRAME)).
typedef struct _DEBUGGER_CALLSTACK_REQUEST
{
BOOLEAN Is32Bit;
UINT32 KernelStatus;
DEBUGGER_CALLSTACK_DISPLAY_METHOD DisplayMethod;
UINT32 Size;
UINT32 FrameCount;
UINT64 BaseAddress;
UINT64 BufferSize;
//
// Here is the size of stack frames
//
} DEBUGGER_CALLSTACK_REQUEST, *PDEBUGGER_CALLSTACK_REQUEST;
The following structure shows the different fields of the frame structure.
typedef struct _DEBUGGER_SINGLE_CALLSTACK_FRAME
{
BOOLEAN IsStackAddressValid;
BOOLEAN IsValidAddress;
BOOLEAN IsExecutable;
UINT64 Value;
BYTE InstructionBytesOnRip[MAXIMUM_CALL_INSTR_SIZE];
} DEBUGGER_SINGLE_CALLSTACK_FRAME, *PDEBUGGER_SINGLE_CALLSTACK_FRAME;
The DisplayMethod can be selected from the below enum:
typedef enum _DEBUGGER_CALLSTACK_DISPLAY_METHOD
{
DEBUGGER_CALLSTACK_DISPLAY_METHOD_WITHOUT_PARAMS,
DEBUGGER_CALLSTACK_DISPLAY_METHOD_WITH_PARAMS,
} DEBUGGER_CALLSTACK_DISPLAY_METHOD;
The next step is sending the above structure to the debuggee when debuggee is paused and waiting for new command on vmx-root mode.
You should send the above structure with DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CALLSTACK as RequestedAction and DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT as PacketType.
In return, the debuggee sends the above structure with the following type.
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_CALLSTACK
In the returned structure, the KernelStatus and frames structures are filled by the kernel.
If the KernelStatus is DEBUGEER_OPERATION_WAS_SUCCESSFULL, then the operation was successful. Otherwise, the returned result is an error.
The following function is responsible for sending interpreting frames in the debugger.
VOID
CallstackShowFrames(PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFrames,
UINT32 FrameCount,
DEBUGGER_CALLSTACK_DISPLAY_METHOD DisplayMethod,
BOOLEAN Is32Bit);

Remarks

  • If you don't specify the length, the default length for HyperDbg is 0x100 Bytes for 32-bit contexts and 0x200 for 64-bit contexts.
  • HyperDbg automatically switches between 32-bit and 64-bit environments based on the debuggee's execution context.
Please note that you should specify a space between 'l' and the length in HyperDbg. For example, 'l100' is invalid, but 'l 100' is valid. (It's opposed to windbg).
This command is guaranteed to keep debuggee in a halt state (in Debugger Mode); thus, nothing will change during its execution.

Requirements

None
None
Copy link
Edit on GitHub
On this page
Command
Syntax
Description
Parameters
Examples
IOCTL
Remarks
Requirements
Related