mirror of
https://github.com/HyperDbg/HyperDbg
synced 2026-08-15 06:29:09 -04:00
New socket platform API and named-pipe linux file
This commit is contained in:
parent
1abac35edc
commit
6683c2dc3d
11 changed files with 450 additions and 62 deletions
83
hyperdbg/include/platform/user/code/platform-socket.c
Normal file
83
hyperdbg/include/platform/user/code/platform-socket.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @file platform-socket.c
|
||||
* @author Max Raulea (max.raulea@hyperdbg.org)
|
||||
* @brief User mode cross-platform implementation of the TCP remote-debugging transport
|
||||
* @details See platform-socket.h. The few Winsock/POSIX primitives that diverge
|
||||
* (close, shutdown flag, last-error) are mapped onto a common spelling
|
||||
* by the macros below so each wrapper body is written once; only the
|
||||
* startup/cleanup lifecycle, whose structure genuinely differs, keeps a
|
||||
* small in-body guard. The portable socket calls themselves stay at the
|
||||
* tcpclient/tcpserver call sites unchanged.
|
||||
*
|
||||
* @version 0.21
|
||||
* @date 2026-07-22
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "../header/platform-socket.h"
|
||||
# include <errno.h>
|
||||
#endif // defined(__linux__)
|
||||
|
||||
//
|
||||
// Map the Winsock/POSIX primitives that diverge onto a common spelling.
|
||||
//
|
||||
#if defined(_WIN32)
|
||||
# define PLATFORM_CLOSE_SOCKET(Socket) closesocket(Socket)
|
||||
# define PLATFORM_SHUTDOWN_SEND_FLAG SD_SEND
|
||||
# define PLATFORM_LAST_SOCKET_ERROR WSAGetLastError()
|
||||
#elif defined(__linux__)
|
||||
# define PLATFORM_CLOSE_SOCKET(Socket) close(Socket)
|
||||
# define PLATFORM_SHUTDOWN_SEND_FLAG SHUT_WR
|
||||
# define PLATFORM_LAST_SOCKET_ERROR errno
|
||||
#endif
|
||||
|
||||
INT
|
||||
PlatformSocketInitialize(VOID)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
WSADATA WsaData;
|
||||
|
||||
//
|
||||
// Request Winsock 2.2; the WSADATA is not needed by the caller.
|
||||
//
|
||||
return WSAStartup(MAKEWORD(2, 2), &WsaData);
|
||||
#else
|
||||
//
|
||||
// No global socket-library initialization is needed on Linux.
|
||||
//
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID
|
||||
PlatformSocketCleanup(VOID)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
WSACleanup();
|
||||
#endif
|
||||
//
|
||||
// Nothing to tear down on Linux.
|
||||
//
|
||||
}
|
||||
|
||||
INT
|
||||
PlatformCloseSocket(SOCKET Socket)
|
||||
{
|
||||
return PLATFORM_CLOSE_SOCKET(Socket);
|
||||
}
|
||||
|
||||
INT
|
||||
PlatformShutdownSocketSend(SOCKET Socket)
|
||||
{
|
||||
return shutdown(Socket, PLATFORM_SHUTDOWN_SEND_FLAG);
|
||||
}
|
||||
|
||||
INT
|
||||
PlatformGetSocketError(VOID)
|
||||
{
|
||||
return PLATFORM_LAST_SOCKET_ERROR;
|
||||
}
|
||||
78
hyperdbg/include/platform/user/header/platform-socket.h
Normal file
78
hyperdbg/include/platform/user/header/platform-socket.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @file platform-socket.h
|
||||
* @author Max Raulea (max.raulea@hyperdbg.org)
|
||||
* @brief User mode cross-platform interface for the TCP remote-debugging transport
|
||||
* @details The remote-debugging command/result exchange in tcpclient.cpp /
|
||||
* tcpserver.cpp is written against the BSD-socket API, which Winsock and
|
||||
* POSIX share almost verbatim (socket / connect / bind / listen / accept /
|
||||
* send / recv / shutdown / getaddrinfo). Only a handful of things diverge:
|
||||
* Winsock's startup/cleanup lifecycle, closesocket vs close(2), the
|
||||
* SD_SEND vs SHUT_WR shutdown flag, WSAGetLastError vs errno, and the
|
||||
* address-length out-parameter type of accept() (int vs socklen_t). Those
|
||||
* are isolated behind the Platform* wrappers / typedef below so the socket
|
||||
* call sites stay shared. On Linux this header also pulls in the POSIX
|
||||
* socket headers that back the portable calls; on Windows they come from
|
||||
* <winsock2.h>/<ws2tcpip.h> (included by pch.h).
|
||||
*
|
||||
* @version 0.21
|
||||
* @date 2026-07-22
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "../../../../include/SDK/HyperDbgSdk.h"
|
||||
# include <sys/socket.h>
|
||||
# include <netdb.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <unistd.h>
|
||||
#endif // defined(__linux__)
|
||||
|
||||
//
|
||||
// Length type for the address-size out-parameter of accept() (and friends).
|
||||
// Winsock uses int; POSIX uses socklen_t. Kept as a platform typedef so the
|
||||
// call sites declare the right type without an inline #ifdef.
|
||||
//
|
||||
#if defined(_WIN32)
|
||||
typedef int PLATFORM_SOCKLEN;
|
||||
#elif defined(__linux__)
|
||||
typedef socklen_t PLATFORM_SOCKLEN;
|
||||
#endif
|
||||
|
||||
//
|
||||
// INITIALIZE the socket subsystem before any socket call. Mirrors WSAStartup:
|
||||
// returns 0 on success and non-zero on failure. The Winsock version request is
|
||||
// kept internal. No-op on Linux (always returns 0).
|
||||
//
|
||||
INT
|
||||
PlatformSocketInitialize(VOID);
|
||||
|
||||
//
|
||||
// CLEAN UP the socket subsystem (Winsock WSACleanup; no-op on Linux).
|
||||
//
|
||||
VOID
|
||||
PlatformSocketCleanup(VOID);
|
||||
|
||||
//
|
||||
// CLOSE a socket (Winsock closesocket; POSIX close(2)).
|
||||
//
|
||||
INT
|
||||
PlatformCloseSocket(SOCKET Socket);
|
||||
|
||||
//
|
||||
// SHUT DOWN the sending side of a socket (Winsock shutdown(.., SD_SEND);
|
||||
// POSIX shutdown(.., SHUT_WR)). Returns 0 on success, SOCKET_ERROR on failure.
|
||||
//
|
||||
INT
|
||||
PlatformShutdownSocketSend(SOCKET Socket);
|
||||
|
||||
//
|
||||
// LAST socket error for the calling thread (Winsock WSAGetLastError; POSIX
|
||||
// errno). See the last-error caveat in platform-lib-calls.h: the numeric code
|
||||
// spaces still differ; callers that only log or check non-zero are fine.
|
||||
//
|
||||
INT
|
||||
PlatformGetSocketError(VOID);
|
||||
|
|
@ -32,6 +32,7 @@ set(SourceFiles
|
|||
"../include/platform/user/code/platform-serial.c"
|
||||
"../include/platform/user/code/platform-ioctl.c"
|
||||
"../include/platform/user/code/platform-signal.c"
|
||||
"../include/platform/user/code/platform-socket.c"
|
||||
"../include/platform/user/code/windows-only/windows-privilege.c"
|
||||
"../script-eval/code/Functions.c"
|
||||
"../script-eval/code/Keywords.c"
|
||||
|
|
@ -177,6 +178,7 @@ set_source_files_properties(
|
|||
"../include/platform/user/code/platform-serial.c"
|
||||
"../include/platform/user/code/platform-ioctl.c"
|
||||
"../include/platform/user/code/platform-signal.c"
|
||||
"../include/platform/user/code/platform-socket.c"
|
||||
"../include/platform/user/code/windows-only/windows-privilege.c"
|
||||
"../script-eval/code/Functions.c"
|
||||
"../script-eval/code/Keywords.c"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
/**
|
||||
* @file namedpipe-linux.cpp
|
||||
* @author Max Raulea (max.raulea@hyperdbg.org)
|
||||
* @brief Linux stub implementations of the named-pipe transport (namedpipe.cpp)
|
||||
* @details The Windows implementation (namedpipe.cpp) is a thin wrapper over the
|
||||
* Win32 named-pipe IPC API: the server side uses
|
||||
* CreateNamedPipe/ConnectNamedPipe/ReadFile/WriteFile, and the client
|
||||
* side uses CreateFileA against the "\\.\pipe\..." name plus overlapped
|
||||
* ReadFile/WriteFile with the g_OverlappedIoStructureFor*Debugger
|
||||
* events. None of that maps 1:1 onto Linux, so the whole translation
|
||||
* unit is swapped out on Linux (CMake `if(UNIX)` REMOVE_ITEM
|
||||
* namedpipe.cpp + APPEND namedpipe-linux.cpp), mirroring the
|
||||
* symbol.cpp -> symbol-linux.cpp / pe-parser.cpp -> pe-parser-linux.cpp
|
||||
* / install.cpp -> install-linux.cpp pattern. namedpipe.cpp itself is
|
||||
* left 100% untouched for the Windows build. Only the 10 public
|
||||
* functions declared in namedpipe.h are provided here; the two internal
|
||||
* *Example() demo functions are not part of the interface and simply do
|
||||
* not exist in the Linux TU.
|
||||
*
|
||||
* The Create* entry points return INVALID_HANDLE_VALUE, so every caller
|
||||
* bails before reaching the send/read/close paths — those stay silent to
|
||||
* avoid spamming a message on each loop iteration; only the Create*
|
||||
* functions emit the "not supported" note.
|
||||
*
|
||||
* TODO(Linux) to make these real: back the transport with either a
|
||||
* filesystem FIFO (mkfifo(3), matching the "named pipe" naming most
|
||||
* closely) or, more usefully for bidirectional message framing, a Unix
|
||||
* domain socket (AF_UNIX, socket/bind/listen/accept on the server side,
|
||||
* socket/connect on the client side) whose path is derived from the
|
||||
* "\\.\pipe\NAME" string. The overlapped/event machinery collapses to
|
||||
* plain blocking read()/write() (or poll()) since a dedicated thread
|
||||
* already owns each direction.
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2026-07-22
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Server Side //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Create a named-pipe server endpoint.
|
||||
* @return HANDLE INVALID_HANDLE_VALUE — named pipes are not supported on Linux
|
||||
* yet (see file header for the FIFO / AF_UNIX plan).
|
||||
*/
|
||||
HANDLE
|
||||
NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize, UINT32 InputBufferSize)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeName);
|
||||
UNREFERENCED_PARAMETER(OutputBufferSize);
|
||||
UNREFERENCED_PARAMETER(InputBufferSize);
|
||||
|
||||
ShowMessages("err, named-pipe communication is not supported on Linux yet\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for a client to connect to the server pipe.
|
||||
* @return BOOLEAN FALSE — not supported on Linux yet.
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeServerWaitForClientConntection(HANDLE PipeHandle)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a message sent by the connected client.
|
||||
* @return UINT32 0 — not supported on Linux yet.
|
||||
*/
|
||||
UINT32
|
||||
NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT MaximumReadBufferLength)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
UNREFERENCED_PARAMETER(BufferToSave);
|
||||
UNREFERENCED_PARAMETER(MaximumReadBufferLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a message to the connected client.
|
||||
* @return BOOLEAN FALSE — not supported on Linux yet.
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeServerSendMessageToClient(HANDLE PipeHandle,
|
||||
CHAR * BufferToSend,
|
||||
INT BufferSize)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
UNREFERENCED_PARAMETER(BufferToSend);
|
||||
UNREFERENCED_PARAMETER(BufferSize);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Close the server pipe handle.
|
||||
* @return VOID no-op — not supported on Linux yet.
|
||||
*/
|
||||
VOID
|
||||
NamedPipeServerCloseHandle(HANDLE PipeHandle)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Client Side //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Connect to a named-pipe server endpoint.
|
||||
* @return HANDLE INVALID_HANDLE_VALUE — not supported on Linux yet.
|
||||
*/
|
||||
HANDLE
|
||||
NamedPipeClientCreatePipe(LPCSTR PipeName)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeName);
|
||||
|
||||
ShowMessages("err, named-pipe communication is not supported on Linux yet\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect to a named-pipe server endpoint using overlapped I/O.
|
||||
* @return HANDLE INVALID_HANDLE_VALUE — not supported on Linux yet.
|
||||
*/
|
||||
HANDLE
|
||||
NamedPipeClientCreatePipeOverlappedIo(LPCSTR PipeName)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeName);
|
||||
|
||||
ShowMessages("err, named-pipe communication is not supported on Linux yet\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a message to the server over the client pipe.
|
||||
* @return BOOLEAN FALSE — not supported on Linux yet.
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT BufferSize)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
UNREFERENCED_PARAMETER(BufferToSend);
|
||||
UNREFERENCED_PARAMETER(BufferSize);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a message from the server over the client pipe.
|
||||
* @return UINT32 0 — not supported on Linux yet.
|
||||
*/
|
||||
UINT32
|
||||
NamedPipeClientReadMessage(HANDLE PipeHandle, CHAR * BufferToRead, INT MaximumSizeOfBuffer)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
UNREFERENCED_PARAMETER(BufferToRead);
|
||||
UNREFERENCED_PARAMETER(MaximumSizeOfBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Close the client pipe handle.
|
||||
* @return VOID no-op — not supported on Linux yet.
|
||||
*/
|
||||
VOID
|
||||
NamedPipeClientClosePipe(HANDLE PipeHandle)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PipeHandle);
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
|
|
@ -134,7 +134,7 @@ RemoteConnectionListen(PCSTR Port)
|
|||
//
|
||||
// Zero the buffer for next command
|
||||
//
|
||||
RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
|
||||
PlatformZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -175,7 +175,7 @@ RemoteConnectionListen(PCSTR Port)
|
|||
//
|
||||
// Zero the buffer for next command
|
||||
//
|
||||
RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
|
||||
PlatformZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -271,13 +271,13 @@ RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam)
|
|||
//
|
||||
// Trigger the event
|
||||
//
|
||||
SetEvent(g_EndOfMessageReceivedEvent);
|
||||
PlatformSetEvent(g_EndOfMessageReceivedEvent);
|
||||
}
|
||||
|
||||
//
|
||||
// Clear the buffer
|
||||
//
|
||||
RtlZeroMemory(RecvBuf, COMMUNICATION_BUFFER_SIZE);
|
||||
PlatformZeroMemory(RecvBuf, COMMUNICATION_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -314,7 +314,6 @@ RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam)
|
|||
VOID
|
||||
RemoteConnectionConnect(PCSTR Ip, PCSTR Port)
|
||||
{
|
||||
DWORD ThreadId;
|
||||
CHAR Recv[3] = {0};
|
||||
UINT32 BuffRecv = 0;
|
||||
|
||||
|
|
@ -412,7 +411,7 @@ RemoteConnectionConnect(PCSTR Ip, PCSTR Port)
|
|||
//
|
||||
if (g_EndOfMessageReceivedEvent == NULL)
|
||||
{
|
||||
g_EndOfMessageReceivedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
g_EndOfMessageReceivedEvent = PlatformCreateEvent(FALSE, FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -420,13 +419,9 @@ RemoteConnectionConnect(PCSTR Ip, PCSTR Port)
|
|||
// the remote debuggee for new messages
|
||||
// Listen for upcoming messages
|
||||
//
|
||||
g_RemoteDebuggeeListeningThread = CreateThread(
|
||||
NULL,
|
||||
0,
|
||||
g_RemoteDebuggeeListeningThread = PlatformCreateThread(
|
||||
RemoteConnectionThreadListeningToDebuggee,
|
||||
NULL,
|
||||
0,
|
||||
&ThreadId);
|
||||
NULL);
|
||||
|
||||
ShowMessages("connected to %s:%s\n", Ip, Port);
|
||||
}
|
||||
|
|
@ -458,7 +453,7 @@ RemoteConnectionSendCommand(const CHAR * sendbuf, INT len)
|
|||
//
|
||||
// We wait for the debuggee to send the message
|
||||
//
|
||||
WaitForSingleObject(
|
||||
PlatformWaitForSingleObject(
|
||||
g_EndOfMessageReceivedEvent,
|
||||
INFINITE);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
INT
|
||||
CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketArg)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
SOCKET ConnectSocket = INVALID_SOCKET;
|
||||
struct addrinfo *result = NULL, *ptr = NULL, hints;
|
||||
INT IResult;
|
||||
|
|
@ -30,14 +29,14 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA
|
|||
//
|
||||
// Initialize Winsock
|
||||
//
|
||||
IResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
IResult = PlatformSocketInitialize();
|
||||
if (IResult != 0)
|
||||
{
|
||||
ShowMessages("err, WSAStartup failed (%x)\n", IResult);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
PlatformZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
|
@ -49,7 +48,7 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA
|
|||
if (IResult != 0)
|
||||
{
|
||||
ShowMessages("getaddrinfo failed (%x)\n", IResult);
|
||||
WSACleanup();
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -64,8 +63,8 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA
|
|||
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
|
||||
if (ConnectSocket == INVALID_SOCKET)
|
||||
{
|
||||
ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
|
||||
WSACleanup();
|
||||
ShowMessages("socket failed with error: %ld\n", PlatformGetSocketError());
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +74,7 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA
|
|||
IResult = connect(ConnectSocket, ptr->ai_addr, (INT)ptr->ai_addrlen);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
closesocket(ConnectSocket);
|
||||
PlatformCloseSocket(ConnectSocket);
|
||||
ConnectSocket = INVALID_SOCKET;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -87,7 +86,7 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA
|
|||
if (ConnectSocket == INVALID_SOCKET)
|
||||
{
|
||||
ShowMessages("unable to connect to the server\n");
|
||||
WSACleanup();
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -118,9 +117,9 @@ CommunicationClientSendMessage(SOCKET ConnectSocket, const CHAR * sendbuf, INT b
|
|||
IResult = send(ConnectSocket, sendbuf, buflen, 0);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
ShowMessages("err, send failed (%x)\n", WSAGetLastError());
|
||||
closesocket(ConnectSocket);
|
||||
WSACleanup();
|
||||
ShowMessages("err, send failed (%x)\n", PlatformGetSocketError());
|
||||
PlatformCloseSocket(ConnectSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +140,7 @@ CommunicationClientShutdownConnection(SOCKET ConnectSocket)
|
|||
//
|
||||
// shutdown the connection since no more data will be sent
|
||||
//
|
||||
IResult = shutdown(ConnectSocket, SD_SEND);
|
||||
IResult = PlatformShutdownSocketSend(ConnectSocket);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
//
|
||||
|
|
@ -150,11 +149,11 @@ CommunicationClientShutdownConnection(SOCKET ConnectSocket)
|
|||
//
|
||||
|
||||
/*
|
||||
ShowMessages("err, shutdown failed (%x)\n", WSAGetLastError());
|
||||
ShowMessages("err, shutdown failed (%x)\n", PlatformGetSocketError());
|
||||
*/
|
||||
|
||||
closesocket(ConnectSocket);
|
||||
WSACleanup();
|
||||
PlatformCloseSocket(ConnectSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -197,7 +196,7 @@ CommunicationClientReceiveMessage(SOCKET ConnectSocket, CHAR * RecvBuf, UINT32 M
|
|||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("\nrecv failed with error: %d\n", WSAGetLastError());
|
||||
ShowMessages("\nrecv failed with error: %d\n", PlatformGetSocketError());
|
||||
ShowMessages("the remote system closes the connection.\n\n");
|
||||
|
||||
return 1;
|
||||
|
|
@ -218,8 +217,8 @@ CommunicationClientCleanup(SOCKET ConnectSocket)
|
|||
//
|
||||
// cleanup
|
||||
//
|
||||
closesocket(ConnectSocket);
|
||||
WSACleanup();
|
||||
PlatformCloseSocket(ConnectSocket);
|
||||
PlatformSocketCleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
SOCKET * ClientSocketArg,
|
||||
SOCKET * ListenSocketArg)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
INT IResult;
|
||||
INT IResult;
|
||||
|
||||
SOCKET ListenSocket = INVALID_SOCKET;
|
||||
SOCKET ClientSocket = INVALID_SOCKET;
|
||||
|
|
@ -44,14 +43,14 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
//
|
||||
// Initialize Winsock
|
||||
//
|
||||
IResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
IResult = PlatformSocketInitialize();
|
||||
if (IResult != 0)
|
||||
{
|
||||
ShowMessages("err, WSAStartup failed (%x)\n", IResult);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
PlatformZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
|
@ -64,7 +63,7 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
if (IResult != 0)
|
||||
{
|
||||
ShowMessages("err, getaddrinfo failed (%x)\n", IResult);
|
||||
WSACleanup();
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -75,9 +74,9 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
if (ListenSocket == INVALID_SOCKET)
|
||||
{
|
||||
ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
|
||||
ShowMessages("socket failed with error: %ld\n", PlatformGetSocketError());
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -87,10 +86,10 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
IResult = ::bind(ListenSocket, result->ai_addr, (INT)result->ai_addrlen);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
ShowMessages("err, bind failed (%x)\n", WSAGetLastError());
|
||||
ShowMessages("err, bind failed (%x)\n", PlatformGetSocketError());
|
||||
freeaddrinfo(result);
|
||||
closesocket(ListenSocket);
|
||||
WSACleanup();
|
||||
PlatformCloseSocket(ListenSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -99,25 +98,25 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
|
|||
IResult = listen(ListenSocket, SOMAXCONN);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
ShowMessages("err, listen failed (%x)\n", WSAGetLastError());
|
||||
closesocket(ListenSocket);
|
||||
WSACleanup();
|
||||
ShowMessages("err, listen failed (%x)\n", PlatformGetSocketError());
|
||||
PlatformCloseSocket(ListenSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Accept a client socket
|
||||
//
|
||||
sockaddr_in name = {0};
|
||||
INT AddrLen = sizeof(name);
|
||||
sockaddr_in name = {0};
|
||||
PLATFORM_SOCKLEN AddrLen = sizeof(name);
|
||||
|
||||
ClientSocket = accept(ListenSocket, (struct sockaddr *)&name, &AddrLen);
|
||||
|
||||
if (ClientSocket == INVALID_SOCKET)
|
||||
{
|
||||
ShowMessages("err, accept failed (%x)\n", WSAGetLastError());
|
||||
closesocket(ListenSocket);
|
||||
WSACleanup();
|
||||
ShowMessages("err, accept failed (%x)\n", PlatformGetSocketError());
|
||||
PlatformCloseSocket(ListenSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +165,9 @@ CommunicationServerReceiveMessage(SOCKET ClientSocket, CHAR * recvbuf, INT recvb
|
|||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("err, recv failed (%x)\n", WSAGetLastError());
|
||||
closesocket(ClientSocket);
|
||||
WSACleanup();
|
||||
ShowMessages("err, recv failed (%x)\n", PlatformGetSocketError());
|
||||
PlatformCloseSocket(ClientSocket);
|
||||
PlatformSocketCleanup();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -196,9 +195,9 @@ CommunicationServerSendMessage(SOCKET ClientSocket, const CHAR * sendbuf, INT le
|
|||
if (ISendResult == SOCKET_ERROR)
|
||||
{
|
||||
/*
|
||||
ShowMessages("err, send failed (%x)\n", WSAGetLastError());
|
||||
closesocket(ClientSocket);
|
||||
WSACleanup();
|
||||
ShowMessages("err, send failed (%x)\n", PlatformGetSocketError());
|
||||
PlatformCloseSocket(ClientSocket);
|
||||
PlatformSocketCleanup();
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -221,12 +220,12 @@ CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket,
|
|||
//
|
||||
// No longer need server socket
|
||||
//
|
||||
closesocket(ListenSocket);
|
||||
PlatformCloseSocket(ListenSocket);
|
||||
|
||||
//
|
||||
// shutdown the connection since we're done
|
||||
//
|
||||
IResult = shutdown(ClientSocket, SD_SEND);
|
||||
IResult = PlatformShutdownSocketSend(ClientSocket);
|
||||
if (IResult == SOCKET_ERROR)
|
||||
{
|
||||
//
|
||||
|
|
@ -235,19 +234,19 @@ CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket,
|
|||
//
|
||||
|
||||
/*
|
||||
ShowMessages("err, shutdown failed (%x)\n", WSAGetLastError());
|
||||
ShowMessages("err, shutdown failed (%x)\n", PlatformGetSocketError());
|
||||
*/
|
||||
|
||||
closesocket(ClientSocket);
|
||||
WSACleanup();
|
||||
PlatformCloseSocket(ClientSocket);
|
||||
PlatformSocketCleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// cleanup
|
||||
//
|
||||
closesocket(ClientSocket);
|
||||
WSACleanup();
|
||||
PlatformCloseSocket(ClientSocket);
|
||||
PlatformSocketCleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="R
|
|||
<ClInclude Include="..\include\platform\user\header\platform-serial.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\platform-ioctl.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\platform-signal.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\platform-socket.h" />
|
||||
<ClInclude Include="..\include\platform\general\header\nt-list.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\windows-only\windows-privilege.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\Windows.h" />
|
||||
|
|
@ -179,6 +180,7 @@ msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="R
|
|||
<ClCompile Include="..\include\platform\user\code\platform-serial.c" />
|
||||
<ClCompile Include="..\include\platform\user\code\platform-ioctl.c" />
|
||||
<ClCompile Include="..\include\platform\user\code\platform-signal.c" />
|
||||
<ClCompile Include="..\include\platform\user\code\platform-socket.c" />
|
||||
<ClCompile Include="..\include\platform\user\code\windows-only\windows-privilege.c" />
|
||||
<ClCompile Include="..\script-eval\code\Functions.c" />
|
||||
<ClCompile Include="..\script-eval\code\Keywords.c" />
|
||||
|
|
|
|||
|
|
@ -179,6 +179,9 @@
|
|||
<ClInclude Include="..\include\platform\user\header\platform-signal.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\platform\user\header\platform-socket.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\platform\general\header\nt-list.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -721,6 +724,9 @@
|
|||
<ClCompile Include="..\include\platform\user\code\platform-signal.c">
|
||||
<Filter>code\platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\platform\user\code\platform-socket.c">
|
||||
<Filter>code\platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\app\messaging.cpp">
|
||||
<Filter>code\app</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -173,6 +173,11 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
|
|||
//
|
||||
#include "platform/user/header/platform-signal.h"
|
||||
|
||||
//
|
||||
// Platform socket transport (cross-platform TCP remote-debugging I/O)
|
||||
//
|
||||
#include "platform/user/header/platform-socket.h"
|
||||
|
||||
//
|
||||
// NT-style intrusive linked-list helpers + CONTAINING_RECORD (self-guards to
|
||||
// non-Windows; Windows gets these from <windows.h> / the native-SDK shim)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ User-mode abstractions in `include/platform/user/` (`header/` = interface,
|
|||
| `platform-serial.{h,c}` | Serial byte transport for remote kernel debugging | **Stub** — Linux branch returns false; termios impl TODO |
|
||||
| `platform-ioctl.{h,c}` | Local kernel-driver IOCTL interface (`PlatformDeviceIoControl`) + device open (`PlatformOpenDevice`) | **Stub** — no Linux kernel module yet; `PlatformOpenDevice` returns `INVALID_HANDLE_VALUE` |
|
||||
| `platform-signal.{h,c}` | Console control handler (Ctrl-C / Ctrl-Break) | Implemented (blocks signals + `sigwait` thread) |
|
||||
| `platform-socket.{h,c}` | TCP remote-debugging transport: the few Winsock ops that diverge from POSIX (`WSAStartup`/`WSACleanup` lifecycle, `closesocket`, `SD_SEND` shutdown, `WSAGetLastError`) + the `accept()` length-type (`PLATFORM_SOCKLEN`). Also owns the Linux POSIX socket-header includes | Implemented (BSD sockets) — the portable socket calls stay at the tcpclient/tcpserver call sites |
|
||||
|
||||
Kernel-mode equivalents live in `include/platform/kernel/`. Two were extended for
|
||||
the port because the shared `script-eval/` code compiles in both user and kernel
|
||||
|
|
@ -371,6 +372,45 @@ Followed pattern-2 (like symbol/pe-parser/install): new `namedpipe-linux.cpp`
|
|||
6 callers link the stubs transparently (forwarding/kd/debug/export/tests/test).
|
||||
See the Linux-replacement-files table above for the FIFO/AF_UNIX TODO.
|
||||
|
||||
### TCP transport (tcpclient/tcpserver/remote-connection) — DONE (2026-07-22)
|
||||
|
||||
The TCP remote-debugging path. Unlike namedpipe, the socket code is genuinely
|
||||
cross-platform — Winsock and POSIX share the BSD-socket API almost verbatim — so
|
||||
it stays as shared `.cpp` (no `-linux.cpp` fork). A new **`platform-socket.{h,c}`
|
||||
module** (sibling to platform-serial/-signal; wired into pch.h, top-level +
|
||||
libhyperdbg CMake, and the Windows `.vcxproj`/`.filters`) isolates the handful of
|
||||
things that actually diverge. User chose the platform-API route over Winsock-name
|
||||
shims in `Environment.h`.
|
||||
|
||||
- **`communication/tcpclient.cpp` / `tcpserver.cpp`** — the portable calls
|
||||
(`socket`/`connect`/`bind`/`listen`/`accept`/`send`/`recv`/`shutdown`/
|
||||
`getaddrinfo`) stay at the call sites unchanged. Swapped only the divergent
|
||||
ones to `Platform*`: `WSAStartup(MAKEWORD(2,2),&wsaData)`→`PlatformSocketInitialize()`
|
||||
(WSADATA local + MAKEWORD dropped; keeps the `IResult != 0` shape — wrapper
|
||||
returns 0 on success), `WSACleanup()`→`PlatformSocketCleanup()`,
|
||||
`closesocket`→`PlatformCloseSocket`, `shutdown(...,SD_SEND)`→`PlatformShutdownSocketSend`,
|
||||
`WSAGetLastError()`→`PlatformGetSocketError()`, plus the bucket-1
|
||||
`ZeroMemory`→`PlatformZeroMemory`. tcpserver's `accept()` length out-param
|
||||
`INT AddrLen`→`PLATFORM_SOCKLEN AddrLen` — the one genuine type incompatibility
|
||||
(Winsock `int*` vs POSIX `socklen_t*`).
|
||||
- **`communication/remote-connection.cpp`** — bucket-1 sweep (`.listen`/`.connect`
|
||||
command layer over the sockets): `RtlZeroMemory`×3→`PlatformZeroMemory`,
|
||||
`SetEvent`→`PlatformSetEvent`, `CreateEvent(NULL,FALSE,FALSE,NULL)`→`PlatformCreateEvent(FALSE,FALSE)`,
|
||||
`CreateThread(...)`→`PlatformCreateThread(fn,NULL)` (unused `DWORD ThreadId` local
|
||||
dropped), `WaitForSingleObject`→`PlatformWaitForSingleObject`.
|
||||
- **`platform-socket.{h,c}`** (pure addition): `PlatformSocketInitialize`/
|
||||
`PlatformSocketCleanup`/`PlatformCloseSocket`/`PlatformShutdownSocketSend`/
|
||||
`PlatformGetSocketError` + the `PLATFORM_SOCKLEN` typedef. The `.c` maps the
|
||||
divergent primitives (close / shutdown-flag / last-error) via small per-OS
|
||||
macros so each wrapper body is written once; only the WSAStartup vs no-op
|
||||
lifecycle keeps a small in-body guard. The `.h` also owns the Linux POSIX
|
||||
socket-header includes (`<sys/socket.h>`/`<netdb.h>`/`<netinet/in.h>`/
|
||||
`<arpa/inet.h>`/`<unistd.h>`), so any TU using sockets gets them via pch.
|
||||
⚠️ Linux branches not yet exercised at runtime (compile-verified only).
|
||||
|
||||
Note the pre-existing latent teardown-ordering issue is unchanged; see the
|
||||
`PlatformTerminateThread` TODO below (remote-connection's listening thread).
|
||||
|
||||
---
|
||||
|
||||
## TODO ledger — revisit before Linux is functional
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue