HyperDbg/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/test.cpp

568 lines
15 KiB
C++
Raw Permalink Normal View History

2020-07-14 05:06:02 -07:00
/**
* @file test.cpp
2022-01-18 22:38:56 +03:30
* @author Sina Karvandi (sina@hyperdbg.org)
2020-07-14 05:06:02 -07:00
* @brief test command
* @details
* @version 0.1
* @date 2020-06-11
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
2020-07-14 05:06:02 -07:00
//
// Global Variables
//
extern BOOLEAN g_IsKdModuleLoaded;
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
2020-08-28 04:03:12 -07:00
/**
2023-07-13 16:05:42 +09:00
* @brief help of the test command
2020-09-14 09:07:17 -07:00
*
* @return VOID
2020-08-28 04:03:12 -07:00
*/
2021-03-22 18:19:39 +04:30
VOID
CommandTestHelp()
{
ShowMessages(
2022-04-10 22:24:56 +04:30
"test : tests essential features of HyperDbg in current machine.\n");
ShowMessages("syntax : \ttest [Task (string)]\n");
2021-03-22 18:19:39 +04:30
ShowMessages("\n");
ShowMessages("\t\te.g : test query\n");
2023-11-15 18:27:54 +09:00
ShowMessages("\t\te.g : test trap-status\n");
2023-07-24 16:25:50 +09:00
ShowMessages("\t\te.g : test pool\n");
ShowMessages("\t\te.g : test query\n");
ShowMessages("\t\te.g : test breakpoint on\n");
ShowMessages("\t\te.g : test breakpoint off\n");
2023-11-15 18:27:54 +09:00
ShowMessages("\t\te.g : test trap on\n");
ShowMessages("\t\te.g : test trap off\n");
2020-07-14 05:06:02 -07:00
}
2021-04-15 03:13:35 +04:30
/**
2022-07-15 14:52:07 -07:00
* @brief Send an IOCTL to the kernel to run the
2021-04-15 03:13:35 +04:30
*
* @return BOOLEAN
*/
BOOLEAN
CommandTestPerformKernelTestsIoctl()
{
BOOL Status;
ULONG ReturnedLength;
DEBUGGER_PERFORM_KERNEL_TESTS KernelTestRequest = {0};
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
2021-04-15 03:13:35 +04:30
//
// By the way, we don't need to send an input buffer
// to the kernel, but let's keep it like this, if we
2024-03-17 01:01:22 +09:00
// want to pass some other arguments to the kernel in
2021-04-15 03:13:35 +04:30
// the future
//
Status = PlatformDeviceIoControl(
2021-04-15 03:13:35 +04:30
g_DeviceHandle, // Handle to device
IOCTL_PERFORM_KERNEL_SIDE_TESTS, // IO Control Code (IOCTL)
2021-04-15 03:13:35 +04:30
&KernelTestRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS, // Input buffer length
&KernelTestRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS, // Length of output buffer in
// bytes.
&ReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if (!Status)
{
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
2021-04-15 03:13:35 +04:30
return FALSE;
}
2022-10-06 17:45:07 +09:00
if (KernelTestRequest.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
2021-04-15 03:13:35 +04:30
{
//
// Nothing to show
//
return TRUE;
}
else
{
//
// Show err message
//
ShowErrorMessage(KernelTestRequest.KernelStatus);
return FALSE;
}
}
/**
* @brief perform test on for all functionalities
*
* @return VOID
*/
VOID
CommandTestAllFunctionalities()
{
HANDLE ThreadHandle;
HANDLE ProcessHandle;
//
// Test command parser
//
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_MAIN_COMMAND_PARSER))
{
ShowMessages("err, start HyperDbg test process for testing the main command parser\n");
return;
}
2026-06-02 11:20:05 +01:00
//
// Test PE parser helpers
//
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_PE_PARSER))
{
ShowMessages("err, start HyperDbg test process for testing the PE parser\n");
return;
}
//
// Test CodeView RSDS parser helpers
//
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_CODEVIEW_RSDS_PARSER))
{
ShowMessages("err, start HyperDbg test process for testing the CodeView RSDS parser\n");
return;
}
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_FLOATING_POINT))
{
ShowMessages("err, start HyperDbg test process for testing floating-point scripts\n");
return;
}
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_VARIABLE_TYPES))
{
ShowMessages("err, start HyperDbg test process for testing variable-type scripts\n");
return;
}
//
// Test script engine (script parser) using semantic tests
//
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES))
{
ShowMessages("err, start HyperDbg test process for testing semantic tests\n");
return;
}
}
2024-10-02 15:04:02 +02:00
/**
* @brief perform test for all functionalities of hwdbg
*
* @return VOID
*/
VOID
CommandTestAllHwdbg()
{
HANDLE ThreadHandle;
HANDLE ProcessHandle;
//
// Test hwdbg functionalities
//
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_HWDBG_FUNCTIONALITIES))
{
ShowMessages("err, start HyperDbg test process for testing hwdbg functionalities\n");
return;
}
}
2020-09-14 09:07:17 -07:00
/**
* @brief perform test on the remote process
*
* @return BOOLEAN returns true if the results was true and false if the results
* was not ok
*/
2021-03-22 18:19:39 +04:30
BOOLEAN
2024-06-08 22:10:20 +09:00
CommandTestPerformTest()
2021-03-22 18:19:39 +04:30
{
2021-04-09 15:44:49 +04:30
BOOLEAN ResultOfTest = FALSE;
HANDLE PipeHandle;
HANDLE ThreadHandle;
HANDLE ProcessHandle;
UINT32 ReadBytes;
2024-06-08 22:10:20 +09:00
CHAR * Buffer = NULL;
//
// Allocate memory
//
Buffer = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2024-06-08 22:10:20 +09:00
if (!Buffer)
{
ShowMessages("err, enable allocate communication buffer\n");
return FALSE;
}
PlatformZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-04-05 19:35:58 +04:30
//
// Create tests process to create a thread for us
//
2024-06-08 22:10:20 +09:00
if (!CreateProcessAndOpenPipeConnection(&PipeHandle,
&ThreadHandle,
&ProcessHandle))
2021-03-22 18:19:39 +04:30
{
2021-04-05 19:35:58 +04:30
ShowMessages("err, enable to connect to the test process\n");
free(Buffer);
2021-04-05 19:35:58 +04:30
return FALSE;
2021-03-22 18:19:39 +04:30
}
2021-04-05 19:35:58 +04:30
//
// ***** Perform test specific routines *****
//
//
2021-04-09 15:44:49 +04:30
// Wait for the result of test to be received
2021-04-05 19:35:58 +04:30
//
2021-04-15 03:13:35 +04:30
2024-06-08 22:10:20 +09:00
SendCommandAndWaitForResponse:
CHAR TestCommand[] = "this is a test command";
BOOLEAN SentMessageResult = NamedPipeServerSendMessageToClient(
PipeHandle,
TestCommand,
(UINT32)strlen(TestCommand) + 1);
if (!SentMessageResult)
{
//
// error in sending
//
return FALSE;
}
2021-04-15 03:13:35 +04:30
PlatformZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-04-05 19:35:58 +04:30
ReadBytes =
2026-06-02 19:28:19 +02:00
NamedPipeServerReadClientMessage(PipeHandle, (CHAR *)Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-04-05 19:35:58 +04:30
if (!ReadBytes)
{
//
// Nothing to read
//
free(Buffer);
2021-04-05 19:35:58 +04:30
return FALSE;
2021-03-22 18:19:39 +04:30
}
2020-09-14 09:07:17 -07:00
2024-06-08 22:10:20 +09:00
goto SendCommandAndWaitForResponse;
2021-04-05 19:35:58 +04:30
//
// Close connection and remote process
//
CloseProcessAndClosePipeConnection(PipeHandle, ThreadHandle, ProcessHandle);
free(Buffer);
2021-03-22 18:19:39 +04:30
return ResultOfTest;
2020-09-14 09:07:17 -07:00
}
/**
* @brief test command for query the state
*
* @return VOID
*/
VOID
CommandTestQueryState()
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the query to the debuggee
//
KdSendTestQueryPacketToDebuggee(TEST_QUERY_HALTING_CORE_STATUS);
}
2023-07-21 21:51:56 +09:00
/**
* @brief test command for query the trap state
*
* @return VOID
*/
VOID
CommandTestQueryTrapState()
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the query to the debuggee
//
KdSendTestQueryPacketToDebuggee(TEST_QUERY_TRAP_STATE);
}
/**
* @brief test command for query the state of pre-allocated pools
*
* @return VOID
*/
VOID
CommandTestQueryPreAllocPoolsState()
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the query to the debuggee
//
KdSendTestQueryPacketToDebuggee(TEST_QUERY_PREALLOCATED_POOL_STATE);
}
2023-09-30 22:01:46 +09:00
/**
* @brief test command for setting target tasks to halted cores
* @param Synchronous
2023-09-30 22:01:46 +09:00
*
* @return VOID
*/
VOID
CommandTestSetTargetTaskToHaltedCores(BOOLEAN Synchronous)
2023-09-30 22:01:46 +09:00
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the target tasks to the halted cores
//
KdSendTestQueryPacketToDebuggee(Synchronous ? TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS : TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS);
2023-09-30 22:01:46 +09:00
}
/**
* @brief test command for setting target task to the specified core
* @param CoreNumber
*
* @return VOID
*/
VOID
CommandTestSetTargetTaskToTargetCore(UINT32 CoreNumber)
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the target task to the target halted core
//
KdSendTestQueryPacketWithContextToDebuggee(TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES, (UINT64)CoreNumber);
}
/**
2023-11-15 18:27:54 +09:00
* @brief test command for turning on/off the breakpoints (#DB)
* @param State
* @return VOID
*/
VOID
CommandTestSetBreakpointState(BOOLEAN State)
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the breakpoint settings to the debuggee
//
if (State)
{
KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_ON_BPS);
}
else
{
KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_OFF_BPS);
}
}
2023-11-15 18:27:54 +09:00
/**
* @brief test command for turning on/off the debug breaks (#DB)
* @param State
* @return VOID
*/
VOID
CommandTestSetDebugBreakState(BOOLEAN State)
{
if (!g_IsSerialConnectedToRemoteDebuggee)
{
ShowMessages("err, query state of the debuggee is only possible when you connected "
"in debugger mode\n");
return;
}
//
// Send the debug break settings to the debuggee
//
if (State)
{
KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_ON_DBS);
}
else
{
KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_OFF_DBS);
}
}
/**
* @brief test command handler
*
2024-07-30 14:17:06 +09:00
* @param CommandTokens
* @param Command
2024-07-30 14:17:06 +09:00
*
* @return VOID
*/
VOID
CommandTest(vector<CommandToken> CommandTokens, string Command)
{
UINT64 Context = NULL;
2024-07-30 14:17:06 +09:00
UINT32 CommandSize = (UINT32)CommandTokens.size();
if (CommandSize == 1)
{
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandTestHelp();
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "query"))
{
//
// Query the state of debuggee in debugger mode
//
CommandTestQueryState();
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "trap-status"))
2023-07-21 21:51:56 +09:00
{
//
// Query the state of trap flag in debugger mode
//
CommandTestQueryTrapState();
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "pool"))
{
//
// Query the state of pre-allocated pools in debugger mode
//
CommandTestQueryPreAllocPoolsState();
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "sync-task"))
2023-09-30 22:01:46 +09:00
{
//
// Send target task to the halted cores in debugger mode (synchronous)
2023-09-30 22:01:46 +09:00
//
CommandTestSetTargetTaskToHaltedCores(TRUE);
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "async-task"))
{
//
// Send target task to the halted cores in debugger mode (asynchronous)
//
CommandTestSetTargetTaskToHaltedCores(FALSE);
2023-09-30 22:01:46 +09:00
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "target-core-task"))
{
2024-07-30 14:17:06 +09:00
if (!ConvertTokenToUInt64(CommandTokens.at(2), &Context))
{
ShowMessages("err, you should enter a valid hex number as the core id\n\n");
return;
}
//
// Send target task to the specific halted core in debugger mode
//
CommandTestSetTargetTaskToTargetCore((UINT32)Context);
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "breakpoint"))
{
//
// Change breakpoint state
//
2024-07-30 14:17:06 +09:00
if (CompareLowerCaseStrings(CommandTokens.at(2), "on"))
{
CommandTestSetBreakpointState(TRUE);
}
2024-07-30 14:17:06 +09:00
else if (CompareLowerCaseStrings(CommandTokens.at(2), "off"))
{
CommandTestSetBreakpointState(FALSE);
}
else
{
2024-07-30 14:17:06 +09:00
ShowMessages("err, couldn't resolve error at '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str());
return;
}
}
2024-07-30 14:17:06 +09:00
else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "trap"))
2023-11-15 18:27:54 +09:00
{
//
// Change debug break state
//
2024-07-30 14:17:06 +09:00
if (CompareLowerCaseStrings(CommandTokens.at(2), "on"))
2023-11-15 18:27:54 +09:00
{
CommandTestSetDebugBreakState(TRUE);
}
2024-07-30 14:17:06 +09:00
else if (CompareLowerCaseStrings(CommandTokens.at(2), "off"))
2023-11-15 18:27:54 +09:00
{
CommandTestSetDebugBreakState(FALSE);
}
else
{
2024-07-30 14:17:06 +09:00
ShowMessages("err, couldn't resolve error at '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str());
2023-11-15 18:27:54 +09:00
return;
}
}
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "all"))
{
//
// For testing functionalities
//
CommandTestAllFunctionalities();
}
2024-10-02 15:04:02 +02:00
else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "hwdbg"))
{
//
// For testing functionalities of hwdbg
//
CommandTestAllHwdbg();
}
else
{
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandTestHelp();
return;
}
}