HyperDbg/hyperdbg/libhyperdbg/code/debugger/tests/tests.cpp

415 lines
10 KiB
C++
Raw Normal View History

2020-09-14 09:07:17 -07:00
/**
* @file tests.cpp
2022-01-18 22:38:56 +03:30
* @author Sina Karvandi (sina@hyperdbg.org)
2020-09-14 09:07:17 -07:00
* @brief perform tests
* @details
* @version 0.1
* @date 2020-09-14
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
2020-09-14 09:07:17 -07:00
//
// Global Variables
//
extern TCHAR g_TestLocation[MAX_PATH];
2020-09-16 09:36:26 -07:00
/**
* @brief
*
* @param BufferLength Setup test process name
* @return BOOLEAN
*/
2026-07-22 11:46:23 +02:00
#ifdef _WIN32
2020-09-14 09:07:17 -07:00
BOOLEAN
SetupTestName(_Inout_updates_bytes_all_(BufferLength) PCHAR TestLocation,
2021-03-22 18:19:39 +04:30
ULONG BufferLength)
{
HANDLE fileHandle;
DWORD driverLocLen = 0;
HMODULE ProcHandle = GetModuleHandle(NULL);
CHAR * Pos;
2020-09-14 09:07:17 -07:00
2021-03-22 18:19:39 +04:30
//
// Get the current directory.
//
2020-09-14 09:07:17 -07:00
2021-04-09 15:44:49 +04:30
//
// We use the location of running exe instead of
// finding driver based on current directory
//
2021-03-22 18:19:39 +04:30
/*
2020-09-14 09:07:17 -07:00
driverLocLen = GetCurrentDirectory(BufferLength, DriverLocation);
if (driverLocLen == 0) {
2021-09-30 12:31:51 +03:30
ShowMessages("err, GetCurrentDirectory failed (%x)\n", GetLastError());
2020-09-14 09:07:17 -07:00
return FALSE;
}
*/
2021-03-22 18:19:39 +04:30
GetModuleFileName(ProcHandle, TestLocation, BufferLength);
Pos = strrchr(TestLocation, '\\');
if (Pos != NULL)
{
//
// this will put the null terminator here. you can also copy to
// another string if you want, we can also use PathCchRemoveFileSpec
//
*Pos = '\0';
}
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
// Setup path name to driver file.
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
if (FAILED(StringCbCat(TestLocation, BufferLength, "\\" TEST_PROCESS_NAME)))
{
return FALSE;
}
2020-09-14 09:07:17 -07:00
//
// Insure test file is in the specified directory
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
if ((fileHandle = CreateFile(TestLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) ==
INVALID_HANDLE_VALUE)
{
ShowMessages("%s.exe is not loaded\n", TEST_PROCESS_NAME);
2020-09-14 09:07:17 -07:00
2021-03-22 18:19:39 +04:30
//
// Indicate failure.
//
return FALSE;
}
2020-09-14 09:07:17 -07:00
2021-03-22 18:19:39 +04:30
//
// Close open file handle.
//
if (fileHandle)
{
CloseHandle(fileHandle);
}
2020-09-14 09:07:17 -07:00
2021-03-22 18:19:39 +04:30
//
// Indicate success.
//
return TRUE;
2020-09-14 09:07:17 -07:00
}
2026-07-22 11:46:23 +02:00
#endif // _WIN32
2020-09-14 09:07:17 -07:00
/**
* @brief Create a Process And Open Pipe Connection object
2020-09-16 09:36:26 -07:00
*
* @param ConnectionPipeHandle Pointer to receive Pipe Handle
* @param ThreadHandle Pointer to receive Thread Handle
* @param ProcessHandle Pointer to receive Process Handle
2020-09-16 09:36:26 -07:00
* @return BOOLEAN
*/
2021-03-22 18:19:39 +04:30
BOOLEAN
2024-06-08 22:10:20 +09:00
CreateProcessAndOpenPipeConnection(PHANDLE ConnectionPipeHandle,
2021-03-22 18:19:39 +04:30
PHANDLE ThreadHandle,
PHANDLE ProcessHandle)
{
2026-07-22 11:46:23 +02:00
#ifdef _WIN32
HANDLE PipeHandle;
BOOLEAN SentMessageResult;
UINT32 ReadBytes;
CHAR * BufferToRead;
CHAR * BufferToSend;
CHAR HandshakeBuffer[] = "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)";
2021-03-22 18:19:39 +04:30
PROCESS_INFORMATION ProcessInfo;
STARTUPINFO StartupInfo;
CHAR CmdArgs[] = TEST_PROCESS_NAME " im-hyperdbg";
2021-03-22 18:19:39 +04:30
PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests",
2021-04-09 15:44:49 +04:30
TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE,
TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-03-22 18:19:39 +04:30
if (!PipeHandle)
{
//
// Error in creating handle
//
return FALSE;
}
BufferToRead = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2024-06-08 22:10:20 +09:00
if (!BufferToRead)
{
//
// Enable to allocate buffer
//
return FALSE;
}
BufferToSend = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2024-06-08 22:10:20 +09:00
if (!BufferToSend)
{
//
// Enable to allocate buffer
//
free(BufferToSend);
return FALSE;
}
RtlZeroMemory(BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
RtlZeroMemory(BufferToSend, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
strcpy(BufferToSend, HandshakeBuffer);
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
// Create the Test Process
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
// the only compulsory field
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
StartupInfo.cb = sizeof StartupInfo;
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
// Set-up path
2020-09-14 09:07:17 -07:00
//
2021-03-22 18:19:39 +04:30
if (!SetupTestName(g_TestLocation, sizeof(g_TestLocation)))
{
//
2021-03-22 18:19:39 +04:30
// Test process not found
//
free(BufferToRead);
free(BufferToSend);
return FALSE;
2021-03-22 18:19:39 +04:30
}
2021-03-22 18:19:39 +04:30
if (CreateProcess(g_TestLocation, CmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo))
{
//
2024-03-17 01:23:40 +09:00
// Wait for message from the target process
//
2021-03-22 18:19:39 +04:30
if (!NamedPipeServerWaitForClientConntection(PipeHandle))
{
//
// Error in connection
//
free(BufferToRead);
free(BufferToSend);
2021-03-22 18:19:39 +04:30
return FALSE;
}
ReadBytes =
NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-03-22 18:19:39 +04:30
if (!ReadBytes)
{
//
// Nothing to read
//
free(BufferToRead);
free(BufferToSend);
2021-03-22 18:19:39 +04:30
return FALSE;
}
2021-03-22 18:19:39 +04:30
if (strcmp(BufferToRead, "Hey there, Are you HyperDbg?") == 0)
{
2021-03-22 18:19:39 +04:30
//
// *** Connected to the remote process ***
//
2021-03-22 18:19:39 +04:30
//
// Send the hand shake message
//
SentMessageResult = NamedPipeServerSendMessageToClient(
PipeHandle,
BufferToSend,
2024-03-14 14:02:18 +09:00
(UINT32)strlen(BufferToSend) + 1);
2021-03-22 18:19:39 +04:30
if (!SentMessageResult)
{
//
// error in sending
//
free(BufferToRead);
free(BufferToSend);
2021-03-22 18:19:39 +04:30
return FALSE;
}
//
2021-03-22 18:19:39 +04:30
// Receive the request for the test case number
//
RtlZeroMemory(BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-03-22 18:19:39 +04:30
ReadBytes = NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
2021-03-22 18:19:39 +04:30
if (!ReadBytes)
{
//
// Nothing to read
//
free(BufferToRead);
free(BufferToSend);
2021-03-22 18:19:39 +04:30
return FALSE;
}
2024-06-08 22:10:20 +09:00
if (strcmp(BufferToRead, "Wow! I miss you... Would you plz send test cases?") == 0)
2021-03-22 18:19:39 +04:30
{
2024-06-08 22:10:20 +09:00
//
// Set the output handles
//
*ConnectionPipeHandle = PipeHandle;
*ThreadHandle = ProcessInfo.hThread;
*ProcessHandle = ProcessInfo.hProcess;
free(BufferToRead);
free(BufferToSend);
return TRUE;
2021-03-22 18:19:39 +04:30
}
2024-06-08 22:10:20 +09:00
ShowMessages("err, could not handshake with the test process\n");
2021-03-22 18:19:39 +04:30
free(BufferToRead);
free(BufferToSend);
2024-06-08 22:10:20 +09:00
return FALSE;
2021-03-22 18:19:39 +04:30
}
else
{
2024-06-08 22:10:20 +09:00
ShowMessages("err, the process could not be started\n");
free(BufferToRead);
free(BufferToSend);
return FALSE;
}
}
free(BufferToRead);
free(BufferToSend);
2021-03-22 18:19:39 +04:30
return FALSE;
2026-07-22 11:46:23 +02:00
#else
//
// TODO(Linux): the test harness spawns a Windows test executable
// (hyperdbg-test.exe) and handshakes with it over a named pipe. There is no
// Linux backend yet — both the process spawn (CreateProcess / STARTUPINFO)
// and the named pipe are stubbed — so this returns failure for now.
//
UNREFERENCED_PARAMETER(ConnectionPipeHandle);
UNREFERENCED_PARAMETER(ThreadHandle);
UNREFERENCED_PARAMETER(ProcessHandle);
return FALSE;
#endif // _WIN32
}
/**
* @brief Opens test process
*
* @param ThreadHandle Pointer to receive Thread Handle
* @param ProcessHandle Pointer to receive Process Handle
* @param Args Arguments
*
* @return BOOLEAN
*/
BOOLEAN
OpenHyperDbgTestProcess(PHANDLE ThreadHandle,
PHANDLE ProcessHandle,
CHAR * Args)
{
2026-07-22 11:46:23 +02:00
#ifdef _WIN32
PROCESS_INFORMATION ProcessInfo = {0};
STARTUPINFO StartupInfo = {0};
CHAR CmdArgs[MAX_PATH] = {0};
//
// the only compulsory field
//
StartupInfo.cb = sizeof(StartupInfo);
//
// Set-up path
//
if (!SetupTestName(g_TestLocation, sizeof(g_TestLocation)))
{
return FALSE;
}
//
// Format CmdArgs to include executable and its arguments
//
sprintf_s(CmdArgs, sizeof(CmdArgs), "\"%s\" %s", g_TestLocation, Args);
//
// Open test process
//
if (CreateProcessA(NULL, CmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo))
{
//
// Set the output handles
//
*ThreadHandle = ProcessInfo.hThread;
*ProcessHandle = ProcessInfo.hProcess;
return TRUE;
}
else
{
ShowMessages("err, CreateProcess failed with error %x\n", GetLastError());
}
return FALSE;
2026-07-22 11:46:23 +02:00
#else
//
// TODO(Linux): no Linux process-spawn backend yet (the future home is a
// narrow variant of PlatformCreateProcess). STARTUPINFO is Windows-only.
//
UNREFERENCED_PARAMETER(ThreadHandle);
UNREFERENCED_PARAMETER(ProcessHandle);
UNREFERENCED_PARAMETER(Args);
return FALSE;
#endif // _WIN32
}
/**
* @brief Close the pipe connection and the remote process
2020-09-16 09:36:26 -07:00
*
* @param ConnectionPipeHandle Handle of remote pipe connection
* @param ThreadHandle Handle of test thread
* @param ProcessHandle Handle of test process
2020-09-16 09:36:26 -07:00
* @return VOID
*/
2021-03-22 18:19:39 +04:30
VOID
2021-04-05 19:35:58 +04:30
CloseProcessAndClosePipeConnection(HANDLE ConnectionPipeHandle,
HANDLE ThreadHandle,
HANDLE ProcessHandle)
2021-03-22 18:19:39 +04:30
{
2026-07-22 11:46:23 +02:00
#ifdef _WIN32
2021-03-22 18:19:39 +04:30
//
// Close the connection and handles
//
NamedPipeServerCloseHandle(ConnectionPipeHandle);
CloseHandle(ThreadHandle);
CloseHandle(ProcessHandle);
2026-07-22 11:46:23 +02:00
#else
//
// TODO(Linux): counterpart of the stubbed test-process spawn above; the
// handles are never created on Linux, so there is nothing to close yet.
//
UNREFERENCED_PARAMETER(ConnectionPipeHandle);
UNREFERENCED_PARAMETER(ThreadHandle);
UNREFERENCED_PARAMETER(ProcessHandle);
#endif // _WIN32
2020-09-14 09:07:17 -07:00
}