add user mode side of initializing LBR

This commit is contained in:
sina 2026-04-05 22:56:59 +02:00
parent e040a1c711
commit 2329fd3c19
15 changed files with 320 additions and 44 deletions

View file

@ -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

View file

@ -19,5 +19,8 @@
BOOLEAN
LoaderInitVmmAndDebugger();
BOOLEAN
LoaderInitHyperTrace();
VOID
LoaderUninitializeLogTracer();

View file

@ -10,7 +10,7 @@
*/
#include "pch.h"
#include "Lbr.h"
/**
* @brief Hide debugger on transparent-mode (activate transparent-mode)
*

View file

@ -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

View file

@ -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)

View file

@ -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
*

View file

@ -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;
}
}

View file

@ -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
//

View file

@ -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

View file

@ -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
//

View file

@ -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 //

View file

@ -309,6 +309,9 @@ CommandIdtHelp();
VOID
CommandSmiHelp();
VOID
CommandLbrHelp();
//
// hwdbg commands
//

View file

@ -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);

View file

@ -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" />

View file

@ -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">