mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-09 17:19:26 +00:00
add user mode side of initializing LBR
This commit is contained in:
parent
e040a1c711
commit
2329fd3c19
15 changed files with 320 additions and 44 deletions
|
|
@ -10,6 +10,59 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the hyper trace module
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitHyperTrace()
|
||||
{
|
||||
HYPERTRACE_CALLBACKS HyperTraceCallbacks = {0};
|
||||
|
||||
//
|
||||
// *** Fill the callbacks for using hypertrace ***
|
||||
//
|
||||
|
||||
//
|
||||
// Fill the callbacks for using hyperlog in hypertrace
|
||||
// We use the callbacks directly to avoid two calls to the same function
|
||||
//
|
||||
HyperTraceCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = LogCallbackPrepareAndSendMessageToQueueWrapper;
|
||||
HyperTraceCallbacks.LogCallbackSendMessageToQueue = LogCallbackSendMessageToQueue;
|
||||
HyperTraceCallbacks.LogCallbackSendBuffer = LogCallbackSendBuffer;
|
||||
HyperTraceCallbacks.LogCallbackCheckIfBufferIsFull = LogCallbackCheckIfBufferIsFull;
|
||||
|
||||
//
|
||||
// Memory callbacks
|
||||
//
|
||||
HyperTraceCallbacks.CheckAccessValidityAndSafety = CheckAccessValidityAndSafety;
|
||||
HyperTraceCallbacks.MemoryMapperReadMemorySafeOnTargetProcess = MemoryMapperReadMemorySafeOnTargetProcess;
|
||||
HyperTraceCallbacks.MemoryMapperWriteMemorySafeOnTargetProcess = MemoryMapperWriteMemorySafeOnTargetProcess;
|
||||
|
||||
//
|
||||
// Common callbacks
|
||||
//
|
||||
HyperTraceCallbacks.CommonGetProcessNameFromProcessControlBlock = CommonGetProcessNameFromProcessControlBlock;
|
||||
|
||||
//
|
||||
// Initialize hypertrace module
|
||||
//
|
||||
if (HyperTraceInit(&HyperTraceCallbacks))
|
||||
{
|
||||
LogDebugInfo("HyperDbg's hypertrace loaded successfully");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We won't fail the loading just because of hypertrace, so we just log the error and continue without loading hypertrace
|
||||
//
|
||||
LogDebugInfo("Err, HyperDbg's hypertrace was not loaded");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the VMM and Debugger
|
||||
*
|
||||
|
|
@ -20,7 +73,6 @@ LoaderInitVmmAndDebugger()
|
|||
{
|
||||
MESSAGE_TRACING_CALLBACKS MsgTracingCallbacks = {0};
|
||||
VMM_CALLBACKS VmmCallbacks = {0};
|
||||
HYPERTRACE_CALLBACKS HyperTraceCallbacks = {0};
|
||||
|
||||
//
|
||||
// Allow to server IOCTL
|
||||
|
|
@ -70,31 +122,6 @@ LoaderInitVmmAndDebugger()
|
|||
//
|
||||
VmmCallbacks.InterceptionCallbackTriggerCr3ProcessChange = ProcessTriggerCr3ProcessChange;
|
||||
|
||||
//
|
||||
// *** Fill the callbacks for using hypertrace ***
|
||||
//
|
||||
|
||||
//
|
||||
// Fill the callbacks for using hyperlog in hypertrace
|
||||
// We use the callbacks directly to avoid two calls to the same function
|
||||
//
|
||||
HyperTraceCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = LogCallbackPrepareAndSendMessageToQueueWrapper;
|
||||
HyperTraceCallbacks.LogCallbackSendMessageToQueue = LogCallbackSendMessageToQueue;
|
||||
HyperTraceCallbacks.LogCallbackSendBuffer = LogCallbackSendBuffer;
|
||||
HyperTraceCallbacks.LogCallbackCheckIfBufferIsFull = LogCallbackCheckIfBufferIsFull;
|
||||
|
||||
//
|
||||
// Memory callbacks
|
||||
//
|
||||
HyperTraceCallbacks.CheckAccessValidityAndSafety = CheckAccessValidityAndSafety;
|
||||
HyperTraceCallbacks.MemoryMapperReadMemorySafeOnTargetProcess = MemoryMapperReadMemorySafeOnTargetProcess;
|
||||
HyperTraceCallbacks.MemoryMapperWriteMemorySafeOnTargetProcess = MemoryMapperWriteMemorySafeOnTargetProcess;
|
||||
|
||||
//
|
||||
// Common callbacks
|
||||
//
|
||||
HyperTraceCallbacks.CommonGetProcessNameFromProcessControlBlock = CommonGetProcessNameFromProcessControlBlock;
|
||||
|
||||
//
|
||||
// Initialize message tracer
|
||||
//
|
||||
|
|
@ -119,23 +146,6 @@ LoaderInitVmmAndDebugger()
|
|||
//
|
||||
g_HandleInUse = TRUE;
|
||||
|
||||
//
|
||||
// Initialize hypertrace module
|
||||
//
|
||||
/*
|
||||
if (HyperTraceInit(&HyperTraceCallbacks))
|
||||
{
|
||||
LogDebugInfo("HyperDbg's hypertrace loaded successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We won't fail the loading just because of hypertrace, so we just log the error and continue without loading hypertrace
|
||||
//
|
||||
LogDebugInfo("Err, HyperDbg's hypertrace was not loaded");
|
||||
}
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -19,5 +19,8 @@
|
|||
BOOLEAN
|
||||
LoaderInitVmmAndDebugger();
|
||||
|
||||
BOOLEAN
|
||||
LoaderInitHyperTrace();
|
||||
|
||||
VOID
|
||||
LoaderUninitializeLogTracer();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "pch.h"
|
||||
#include "Lbr.h"
|
||||
|
||||
/**
|
||||
* @brief Hide debugger on transparent-mode (activate transparent-mode)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION
|
|||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCIDEVINFO,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_IDT_ENTRIES,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_SMI_OPERATION,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_LBR_OPERATION,
|
||||
|
||||
//
|
||||
// Debuggee to debugger
|
||||
|
|
|
|||
|
|
@ -330,3 +330,10 @@
|
|||
*/
|
||||
#define IOCTL_PERFORM_SMI_OPERATION \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x826, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/**
|
||||
* @brief ioctl, to perform LBR operations
|
||||
*
|
||||
*/
|
||||
#define IOCTL_PERFORM_LBR_OPERATION \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x827, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,38 @@ typedef struct _SMI_OPERATION_PACKETS
|
|||
/* ==============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform actions related to LBR
|
||||
*
|
||||
*/
|
||||
typedef enum _LBR_OPERATION_REQUEST_TYPE
|
||||
{
|
||||
LBR_OPERATION_REQUEST_TYPE_ENABLE,
|
||||
LBR_OPERATION_REQUEST_TYPE_DISABLE,
|
||||
|
||||
} LBR_OPERATION_REQUEST_TYPE;
|
||||
|
||||
/**
|
||||
* @brief The structure of LBR result packet in HyperDbg
|
||||
*
|
||||
*/
|
||||
typedef struct _LBR_OPERATION_PACKETS
|
||||
{
|
||||
LBR_OPERATION_REQUEST_TYPE LbrOperationType;
|
||||
UINT32 KernelStatus;
|
||||
|
||||
} LBR_OPERATION_PACKETS, *PLBR_OPERATION_PACKETS;
|
||||
|
||||
/**
|
||||
* @brief Debugger size of LBR_OPERATION_PACKETS
|
||||
*
|
||||
*/
|
||||
#define SIZEOF_LBR_OPERATION_PACKETS \
|
||||
sizeof(LBR_OPERATION_PACKETS)
|
||||
|
||||
/* ==============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Maximum number of IDT entries
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* @file lbr.cpp
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief !lbr command
|
||||
* @details
|
||||
* @version 0.19
|
||||
* @date 2026-04-05
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
|
||||
|
||||
/**
|
||||
* @brief help of the !lbr command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandLbrHelp()
|
||||
{
|
||||
ShowMessages("!lbr : enables and disables Last Branch Record (LBR).\n");
|
||||
|
||||
ShowMessages("syntax : \t!lbr [Function (string)]\n");
|
||||
|
||||
ShowMessages("\n");
|
||||
ShowMessages("\t\te.g : !lbr enable\n");
|
||||
ShowMessages("\t\te.g : !lbr disable\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send LBR requests
|
||||
*
|
||||
* @param LbrRequest
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
BOOLEAN
|
||||
CommandLbrSendRequest(LBR_OPERATION_PACKETS * LbrRequest)
|
||||
{
|
||||
BOOL Status;
|
||||
ULONG ReturnedLength;
|
||||
|
||||
if (g_IsSerialConnectedToRemoteDebuggee)
|
||||
{
|
||||
//
|
||||
// Send the request over serial kernel debugger
|
||||
//
|
||||
if (!KdSendLbrPacketsToDebuggee(LbrRequest, SIZEOF_LBR_OPERATION_PACKETS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
|
||||
|
||||
//
|
||||
// Send IOCTL
|
||||
//
|
||||
Status = DeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_PERFORM_LBR_OPERATION, // IO Control Code (IOCTL)
|
||||
LbrRequest, // Input Buffer to driver.
|
||||
SIZEOF_LBR_OPERATION_PACKETS, // Input buffer length
|
||||
LbrRequest, // Output Buffer from driver.
|
||||
SIZEOF_LBR_OPERATION_PACKETS, // Length of output buffer in bytes.
|
||||
&ReturnedLength, // Bytes placed in buffer.
|
||||
NULL // synchronous call
|
||||
);
|
||||
|
||||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (LbrRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request to perform an LBR operation
|
||||
*
|
||||
* @param LbrRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
HyperDbgPerformLbrOperation(LBR_OPERATION_PACKETS * LbrRequest)
|
||||
{
|
||||
return CommandLbrSendRequest(LbrRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief !lbr command handler
|
||||
*
|
||||
* @param CommandTokens
|
||||
* @param Command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandLbr(vector<CommandToken> CommandTokens, string Command)
|
||||
{
|
||||
LBR_OPERATION_PACKETS LbrRequest = {0};
|
||||
|
||||
if (CommandTokens.size() != 2)
|
||||
{
|
||||
ShowMessages("incorrect use of the '%s'\n\n",
|
||||
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
|
||||
|
||||
CommandLbrHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CompareLowerCaseStrings(CommandTokens.at(1), "enable"))
|
||||
{
|
||||
LbrRequest.LbrOperationType = LBR_OPERATION_REQUEST_TYPE_ENABLE;
|
||||
}
|
||||
else if (CompareLowerCaseStrings(CommandTokens.at(1), "disable"))
|
||||
{
|
||||
LbrRequest.LbrOperationType = LBR_OPERATION_REQUEST_TYPE_DISABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("incorrect use of the '%s'\n\n",
|
||||
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
|
||||
CommandLbrHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Send the LBR operation request
|
||||
//
|
||||
if (CommandLbrSendRequest(&LbrRequest))
|
||||
{
|
||||
if (LbrRequest.LbrOperationType == LBR_OPERATION_REQUEST_TYPE_ENABLE)
|
||||
{
|
||||
ShowMessages("LBR enabled successfully\n");
|
||||
}
|
||||
else if (LbrRequest.LbrOperationType == LBR_OPERATION_REQUEST_TYPE_DISABLE)
|
||||
{
|
||||
ShowMessages("LBR disabled successfully\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessage(LbrRequest.KernelStatus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1629,6 +1629,8 @@ InitializeCommandsDictionary()
|
|||
|
||||
g_CommandsList["!smi"] = {&CommandSmi, &CommandSmiHelp, DEBUGGER_COMMAND_SMI_ATTRIBUTES};
|
||||
|
||||
g_CommandsList["!lbr"] = {&CommandLbr, &CommandLbrHelp, DEBUGGER_COMMAND_LBR_ATTRIBUTES};
|
||||
|
||||
//
|
||||
// hwdbg commands
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1055,6 +1055,41 @@ KdSendSmiPacketsToDebuggee(PSMI_OPERATION_PACKETS SmiOperationRequest, UINT32 Ex
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send requests for LBR operation packet to the debuggee
|
||||
*
|
||||
* @param LbrOperationRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdSendLbrPacketsToDebuggee(PLBR_OPERATION_PACKETS LbrOperationRequest, UINT32 ExpectedRequestSize)
|
||||
{
|
||||
//
|
||||
// Set the request data
|
||||
//
|
||||
DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_LBR_OPERATION_RESULT, LbrOperationRequest, ExpectedRequestSize);
|
||||
|
||||
//
|
||||
// Send the LBR request packets
|
||||
//
|
||||
if (!KdCommandPacketAndBufferToDebuggee(
|
||||
DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_LBR_OPERATION,
|
||||
(CHAR *)LbrOperationRequest,
|
||||
SIZEOF_LBR_OPERATION_PACKETS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the result of actions to LBR is received
|
||||
//
|
||||
DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_LBR_OPERATION_RESULT);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send requests for IDT packet to the debuggee
|
||||
* @param IdtRequest
|
||||
|
|
|
|||
|
|
@ -477,6 +477,9 @@ typedef std::map<std::string, COMMAND_DETAIL> CommandType;
|
|||
#define DEBUGGER_COMMAND_SMI_ATTRIBUTES \
|
||||
DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE
|
||||
|
||||
#define DEBUGGER_COMMAND_LBR_ATTRIBUTES \
|
||||
DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Command Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
@ -763,6 +766,9 @@ CommandIdt(vector<CommandToken> CommandTokens, string Command);
|
|||
VOID
|
||||
CommandSmi(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandLbr(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
//
|
||||
// hwdbg commands
|
||||
//
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCIDEVINFO_RESULT 0x1d
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES 0x1e
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT 0x1f
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_LBR_OPERATION_RESULT 0x20
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Event Details //
|
||||
|
|
|
|||
|
|
@ -309,6 +309,9 @@ CommandIdtHelp();
|
|||
VOID
|
||||
CommandSmiHelp();
|
||||
|
||||
VOID
|
||||
CommandLbrHelp();
|
||||
|
||||
//
|
||||
// hwdbg commands
|
||||
//
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ KdSendApicActionPacketsToDebuggee(PDEBUGGER_APIC_REQUEST ApicRequest, UINT32 Exp
|
|||
BOOLEAN
|
||||
KdSendSmiPacketsToDebuggee(PSMI_OPERATION_PACKETS SmiOperationRequest, UINT32 ExpectedRequestSize);
|
||||
|
||||
BOOLEAN
|
||||
KdSendLbrPacketsToDebuggee(PLBR_OPERATION_PACKETS LbrOperationRequest, UINT32 ExpectedRequestSize);
|
||||
|
||||
BOOLEAN
|
||||
KdSendQueryIdtPacketsToDebuggee(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtRequest);
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@
|
|||
<ClCompile Include="code\debugger\commands\extension-commands\crwrite.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\idt.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\ioapic.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\lbr.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\pcicam.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\pcitree.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\rev.cpp" />
|
||||
|
|
|
|||
|
|
@ -598,6 +598,9 @@
|
|||
<ClCompile Include="code\debugger\misc\pci-id.cpp">
|
||||
<Filter>code\debugger\misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\lbr.cpp">
|
||||
<Filter>code\debugger\commands\extension-commands</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="code\assembly\asm-vmx-checks.asm">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue