mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-14 03:29:44 +00:00
378 lines
9 KiB
C++
378 lines
9 KiB
C++
/**
|
|
* @file tests.cpp
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @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"
|
|
|
|
//
|
|
// Global Variables
|
|
//
|
|
extern TCHAR g_TestLocation[MAX_PATH];
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param BufferLength Setup test process name
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SetupTestName(_Inout_updates_bytes_all_(BufferLength) PCHAR TestLocation,
|
|
ULONG BufferLength)
|
|
{
|
|
HANDLE fileHandle;
|
|
DWORD driverLocLen = 0;
|
|
HMODULE ProcHandle = GetModuleHandle(NULL);
|
|
CHAR * Pos;
|
|
|
|
//
|
|
// Get the current directory.
|
|
//
|
|
|
|
//
|
|
// We use the location of running exe instead of
|
|
// finding driver based on current directory
|
|
//
|
|
|
|
/*
|
|
driverLocLen = GetCurrentDirectory(BufferLength, DriverLocation);
|
|
|
|
if (driverLocLen == 0) {
|
|
|
|
ShowMessages("err, GetCurrentDirectory failed (%x)\n", GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
*/
|
|
|
|
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';
|
|
}
|
|
|
|
//
|
|
// Setup path name to driver file.
|
|
//
|
|
if (FAILED(StringCbCat(TestLocation, BufferLength, "\\" TEST_PROCESS_NAME)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Insure test file is in the specified directory
|
|
//
|
|
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);
|
|
|
|
//
|
|
// Indicate failure.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Close open file handle.
|
|
//
|
|
if (fileHandle)
|
|
{
|
|
CloseHandle(fileHandle);
|
|
}
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Create a Process And Open Pipe Connection object
|
|
*
|
|
* @param ConnectionPipeHandle Pointer to receive Pipe Handle
|
|
* @param ThreadHandle Pointer to receive Thread Handle
|
|
* @param ProcessHandle Pointer to receive Process Handle
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
CreateProcessAndOpenPipeConnection(PHANDLE ConnectionPipeHandle,
|
|
PHANDLE ThreadHandle,
|
|
PHANDLE ProcessHandle)
|
|
{
|
|
HANDLE PipeHandle;
|
|
BOOLEAN SentMessageResult;
|
|
UINT32 ReadBytes;
|
|
CHAR * BufferToRead;
|
|
CHAR * BufferToSend;
|
|
CHAR HandshakeBuffer[] = "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)";
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
STARTUPINFO StartupInfo;
|
|
CHAR CmdArgs[] = TEST_PROCESS_NAME " im-hyperdbg";
|
|
|
|
PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests",
|
|
TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE,
|
|
TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
if (!PipeHandle)
|
|
{
|
|
//
|
|
// Error in creating handle
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
BufferToRead = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
|
|
if (!BufferToRead)
|
|
{
|
|
//
|
|
// Enable to allocate buffer
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
BufferToSend = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
|
|
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);
|
|
|
|
//
|
|
// Create the Test Process
|
|
//
|
|
|
|
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
|
|
|
//
|
|
// the only compulsory field
|
|
//
|
|
StartupInfo.cb = sizeof StartupInfo;
|
|
|
|
//
|
|
// Set-up path
|
|
//
|
|
if (!SetupTestName(g_TestLocation, sizeof(g_TestLocation)))
|
|
{
|
|
//
|
|
// Test process not found
|
|
//
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (CreateProcess(g_TestLocation, CmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo))
|
|
{
|
|
//
|
|
// Wait for message from the target process
|
|
//
|
|
if (!NamedPipeServerWaitForClientConntection(PipeHandle))
|
|
{
|
|
//
|
|
// Error in connection
|
|
//
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ReadBytes =
|
|
NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
|
|
if (!ReadBytes)
|
|
{
|
|
//
|
|
// Nothing to read
|
|
//
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (strcmp(BufferToRead, "Hey there, Are you HyperDbg?") == 0)
|
|
{
|
|
//
|
|
// *** Connected to the remote process ***
|
|
//
|
|
|
|
//
|
|
// Send the hand shake message
|
|
//
|
|
SentMessageResult = NamedPipeServerSendMessageToClient(
|
|
PipeHandle,
|
|
BufferToSend,
|
|
(UINT32)strlen(BufferToSend) + 1);
|
|
|
|
if (!SentMessageResult)
|
|
{
|
|
//
|
|
// error in sending
|
|
//
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Receive the request for the test case number
|
|
//
|
|
RtlZeroMemory(BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
|
|
ReadBytes = NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE);
|
|
|
|
if (!ReadBytes)
|
|
{
|
|
//
|
|
// Nothing to read
|
|
//
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (strcmp(BufferToRead, "Wow! I miss you... Would you plz send test cases?") == 0)
|
|
{
|
|
//
|
|
// Set the output handles
|
|
//
|
|
*ConnectionPipeHandle = PipeHandle;
|
|
*ThreadHandle = ProcessInfo.hThread;
|
|
*ProcessHandle = ProcessInfo.hProcess;
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ShowMessages("err, could not handshake with the test process\n");
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, the process could not be started\n");
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
free(BufferToRead);
|
|
free(BufferToSend);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* @brief Close the pipe connection and the remote process
|
|
*
|
|
* @param ConnectionPipeHandle Handle of remote pipe connection
|
|
* @param ThreadHandle Handle of test thread
|
|
* @param ProcessHandle Handle of test process
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
CloseProcessAndClosePipeConnection(HANDLE ConnectionPipeHandle,
|
|
HANDLE ThreadHandle,
|
|
HANDLE ProcessHandle)
|
|
{
|
|
//
|
|
// Close the connection and handles
|
|
//
|
|
NamedPipeServerCloseHandle(ConnectionPipeHandle);
|
|
CloseHandle(ThreadHandle);
|
|
CloseHandle(ProcessHandle);
|
|
}
|