description |
---|
Description of 'k, kd, kq' commands in HyperDbg. |
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
k
kd
kq
k [base StackAddress (hex)] [l Length (hex)]
kd [base StackAddress (hex)] [l Length (hex)]
kq [base StackAddress (hex)] [l Length (hex)]
Displays stack backtrace and optionally show the parameter in the stack.
[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.
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
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 Is32Bit
to 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);
- If you don't specify the length, the default length for HyperDbg is
0x100
Bytes for 32-bit contexts and0x200
for 64-bit contexts. - HyperDbg automatically switches between 32-bit and 64-bit environments based on the debuggee's execution context.
{% hint style="warning" %} 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). {% endhint %}
This command is guaranteed to keep debuggee in a halt state (in Debugger Mode); thus, nothing will change during its execution.
None