mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
391 lines
9.6 KiB
C
391 lines
9.6 KiB
C
/**
|
|
* @file SerialConnection.c
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Serial port connection from debuggee to debugger
|
|
* @details
|
|
* @version 0.1
|
|
* @date 2020-12-15
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief A simple connection test
|
|
*
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
SerialConnectionTest()
|
|
{
|
|
for (SIZE_T i = 0; i < 100; i++)
|
|
{
|
|
KdHyperDbgTest((UINT16)i);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Send end of buffer packet
|
|
*
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
SerialConnectionSendEndOfBuffer()
|
|
{
|
|
//
|
|
// Send the end buffer
|
|
//
|
|
KdHyperDbgSendByte(SERIAL_END_OF_BUFFER_CHAR_1, TRUE);
|
|
KdHyperDbgSendByte(SERIAL_END_OF_BUFFER_CHAR_2, TRUE);
|
|
KdHyperDbgSendByte(SERIAL_END_OF_BUFFER_CHAR_3, TRUE);
|
|
KdHyperDbgSendByte(SERIAL_END_OF_BUFFER_CHAR_4, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief compares the buffer with a string
|
|
*
|
|
* @param CurrentLoopIndex Number of previously read bytes
|
|
* @param Buffer
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionCheckForTheEndOfTheBuffer(PUINT32 CurrentLoopIndex, BYTE * Buffer)
|
|
{
|
|
UINT32 ActualBufferLength;
|
|
|
|
ActualBufferLength = *CurrentLoopIndex;
|
|
|
|
//
|
|
// End of buffer is 4 character long
|
|
//
|
|
if (*CurrentLoopIndex <= 3)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (Buffer[ActualBufferLength] == SERIAL_END_OF_BUFFER_CHAR_4 &&
|
|
Buffer[ActualBufferLength - 1] == SERIAL_END_OF_BUFFER_CHAR_3 &&
|
|
Buffer[ActualBufferLength - 2] == SERIAL_END_OF_BUFFER_CHAR_2 &&
|
|
Buffer[ActualBufferLength - 3] == SERIAL_END_OF_BUFFER_CHAR_1)
|
|
{
|
|
//
|
|
// Clear the end character
|
|
//
|
|
Buffer[ActualBufferLength - 3] = NULL_ZERO;
|
|
Buffer[ActualBufferLength - 2] = NULL_ZERO;
|
|
Buffer[ActualBufferLength - 1] = NULL_ZERO;
|
|
Buffer[ActualBufferLength] = NULL_ZERO;
|
|
|
|
//
|
|
// Set the new length
|
|
//
|
|
*CurrentLoopIndex = ActualBufferLength - 3;
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Receive packet from the debugger
|
|
*
|
|
* @param BufferToSave
|
|
* @param LengthReceived
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionRecvBuffer(CHAR * BufferToSave,
|
|
UINT32 * LengthReceived)
|
|
{
|
|
UINT32 Loop = 0;
|
|
|
|
//
|
|
// Read data and store in a buffer
|
|
//
|
|
while (TRUE)
|
|
{
|
|
UCHAR RecvChar = NULL_ZERO;
|
|
|
|
if (!KdHyperDbgRecvByte(&RecvChar))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// We already now that the maximum packet size is MaxSerialPacketSize
|
|
// Check to make sure that we don't pass the boundaries
|
|
//
|
|
if (!(MaxSerialPacketSize > Loop))
|
|
{
|
|
//
|
|
// Invalid buffer (size of buffer exceeds the limitation)
|
|
//
|
|
LogError("Err, a buffer received in debuggee which exceeds the buffer limitation");
|
|
return FALSE;
|
|
}
|
|
|
|
BufferToSave[Loop] = RecvChar;
|
|
|
|
if (SerialConnectionCheckForTheEndOfTheBuffer(&Loop, (BYTE *)BufferToSave))
|
|
{
|
|
break;
|
|
}
|
|
|
|
Loop++;
|
|
}
|
|
|
|
//
|
|
// Set the length
|
|
//
|
|
*LengthReceived = Loop;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Perform sending buffer over serial
|
|
*
|
|
* @param Buffer buffer to send
|
|
* @param Length length of buffer to send
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionSend(CHAR * Buffer, UINT32 Length)
|
|
{
|
|
//
|
|
// Check if buffer not pass the boundary
|
|
//
|
|
if (Length + SERIAL_END_OF_BUFFER_CHARS_COUNT > MaxSerialPacketSize)
|
|
{
|
|
LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), "
|
|
"for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size",
|
|
Length + SERIAL_END_OF_BUFFER_CHARS_COUNT,
|
|
MaxSerialPacketSize);
|
|
return FALSE;
|
|
}
|
|
|
|
for (SIZE_T i = 0; i < Length; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send the end buffer
|
|
//
|
|
SerialConnectionSendEndOfBuffer();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Perform sending 2 not appended buffers over serial
|
|
*
|
|
* @param Buffer1 buffer to send
|
|
* @param Length1 length of buffer to send
|
|
* @param Buffer2 buffer to send
|
|
* @param Length2 length of buffer to send
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionSendTwoBuffers(CHAR * Buffer1, UINT32 Length1, CHAR * Buffer2, UINT32 Length2)
|
|
{
|
|
//
|
|
// Check if buffer not pass the boundary
|
|
//
|
|
if ((Length1 + Length2 + SERIAL_END_OF_BUFFER_CHARS_COUNT) > MaxSerialPacketSize)
|
|
{
|
|
LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), "
|
|
"for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size",
|
|
Length1 + Length2 + SERIAL_END_OF_BUFFER_CHARS_COUNT,
|
|
MaxSerialPacketSize);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Send first buffer
|
|
//
|
|
for (SIZE_T i = 0; i < Length1; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer1[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send second buffer
|
|
//
|
|
for (SIZE_T i = 0; i < Length2; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer2[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send the end buffer
|
|
//
|
|
SerialConnectionSendEndOfBuffer();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Perform sending 3 not appended buffers over serial
|
|
*
|
|
* @param Buffer1 buffer to send
|
|
* @param Length1 length of buffer to send
|
|
* @param Buffer2 buffer to send
|
|
* @param Length2 length of buffer to send
|
|
* @param Buffer3 buffer to send
|
|
* @param Length3 length of buffer to send
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionSendThreeBuffers(CHAR * Buffer1,
|
|
UINT32 Length1,
|
|
CHAR * Buffer2,
|
|
UINT32 Length2,
|
|
CHAR * Buffer3,
|
|
UINT32 Length3)
|
|
{
|
|
//
|
|
// Check if buffer not pass the boundary
|
|
//
|
|
if ((Length1 + Length2 + Length3 + SERIAL_END_OF_BUFFER_CHARS_COUNT) > MaxSerialPacketSize)
|
|
{
|
|
LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), "
|
|
"for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size",
|
|
Length1 + Length2 + Length3 + SERIAL_END_OF_BUFFER_CHARS_COUNT,
|
|
MaxSerialPacketSize);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Send first buffer
|
|
//
|
|
for (SIZE_T i = 0; i < Length1; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer1[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send second buffer
|
|
//
|
|
for (SIZE_T i = 0; i < Length2; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer2[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send third buffer
|
|
//
|
|
for (SIZE_T i = 0; i < Length3; i++)
|
|
{
|
|
KdHyperDbgSendByte(Buffer3[i], TRUE);
|
|
}
|
|
|
|
//
|
|
// Send the end buffer
|
|
//
|
|
SerialConnectionSendEndOfBuffer();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if baud rate is valid or not
|
|
*
|
|
* @param Baudrate
|
|
* @return BOOLEAN return TRUE if it's correct and returns
|
|
* FALSE if it's not correct
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionCheckBaudrate(DWORD Baudrate)
|
|
{
|
|
if (Baudrate == CBR_110 || Baudrate == CBR_300 || Baudrate == CBR_600 ||
|
|
Baudrate == CBR_1200 || Baudrate == CBR_2400 || Baudrate == CBR_4800 ||
|
|
Baudrate == CBR_9600 || Baudrate == CBR_14400 || Baudrate == CBR_19200 ||
|
|
Baudrate == CBR_38400 || Baudrate == CBR_56000 || Baudrate == CBR_57600 ||
|
|
Baudrate == CBR_115200 || Baudrate == CBR_128000 ||
|
|
Baudrate == CBR_256000)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if serial port address
|
|
*
|
|
* @param SerialPort
|
|
* @return BOOLEAN return TRUE if it's correct and returns
|
|
* FALSE if it's not correct
|
|
*/
|
|
BOOLEAN
|
|
SerialConnectionCheckPort(UINT32 SerialPort)
|
|
{
|
|
if (SerialPort == COM1_PORT || SerialPort == COM2_PORT || SerialPort == COM3_PORT ||
|
|
SerialPort == COM4_PORT)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Perform tasks relating to stepping (step-in & step-out) requests
|
|
*
|
|
* @param DebuggerPrintRequest Request to prepare debuggee
|
|
*
|
|
* @return NTSTATUS
|
|
*/
|
|
NTSTATUS
|
|
SerialConnectionPrepare(PDEBUGGER_PREPARE_DEBUGGEE DebuggeeRequest)
|
|
{
|
|
//
|
|
// Check if baud rate is valid or not
|
|
//
|
|
if (!SerialConnectionCheckBaudrate(DebuggeeRequest->Baudrate))
|
|
{
|
|
//
|
|
// Baud rate is invalid, set the status and return
|
|
//
|
|
DebuggeeRequest->Result = DEBUGGER_ERROR_PREPARING_DEBUGGEE_INVALID_BAUDRATE;
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check if port address is valid or not
|
|
//
|
|
if (!SerialConnectionCheckPort(DebuggeeRequest->PortAddress))
|
|
{
|
|
//
|
|
// Port address is invalid, set the status and return
|
|
//
|
|
DebuggeeRequest->Result = DEBUGGER_ERROR_PREPARING_DEBUGGEE_INVALID_SERIAL_PORT;
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Prepare the structures needed for connecting remote port
|
|
//
|
|
KdHyperDbgPrepareDebuggeeConnectionPort(DebuggeeRequest->PortAddress, DebuggeeRequest->Baudrate);
|
|
|
|
//
|
|
// Initialize kernel debugger
|
|
//
|
|
KdInitializeKernelDebugger();
|
|
|
|
//
|
|
// Send "Start" packet along with Windows Name
|
|
//
|
|
KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER,
|
|
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_STARTED,
|
|
(CHAR *)DebuggeeRequest,
|
|
MAXIMUM_CHARACTER_FOR_OS_NAME);
|
|
|
|
//
|
|
// Set status to successful
|
|
//
|
|
DebuggeeRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|