mirror of
https://github.com/nccgroup/SocksOverRDP
synced 2026-06-08 16:21:17 +00:00
640 lines
18 KiB
C++
640 lines
18 KiB
C++
/*
|
|
TODO: check closing flag at negotiation phases - two functions.
|
|
TODO: slotevent hslot passed from socksoverrdp-server.cpp
|
|
*/
|
|
|
|
|
|
#include <winsock2.h>
|
|
#include <Ws2tcpip.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <process.h>
|
|
#include "SocksServer.h"
|
|
#include "SocksOverRDP-Server.h"
|
|
|
|
#pragma comment(lib, "Ws2_32.lib")
|
|
|
|
#define METHOD_NUMBER 1
|
|
#define BUF_SIZE 4096
|
|
|
|
// hardcoded inactive creds, use proper creds check if you want this
|
|
#define PREDEF_USERNAME "hello"
|
|
#define PREDEF_PASSWORD "bello"
|
|
|
|
extern threads *LookupThread(DWORD dwThreadId);
|
|
extern VOID DeleteThread(DWORD dwThreadId);
|
|
|
|
extern HANDLE ghMutex;
|
|
extern HANDLE hChannel;
|
|
extern BOOL bVerbose, bDebug;
|
|
|
|
int method_no_auth_required(HANDLE c, int count, char *rv);
|
|
|
|
typedef int(*fn)(HANDLE, int, char*);
|
|
static fn method_functions[METHOD_NUMBER] =
|
|
{
|
|
method_no_auth_required,
|
|
// method_username_password, // disabled for security purposes
|
|
};
|
|
static char method_numbers[METHOD_NUMBER] =
|
|
{
|
|
0,
|
|
// 2,
|
|
};
|
|
|
|
int method_no_auth_required(HANDLE c, int count, char *rv)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// dedicated function to handle writes on the virtual channel
|
|
BOOL WriteChannel(char *Buffer, DWORD nBytesToWrite, DWORD *nBytesWrittes, DWORD dwRemoteThreadId, BOOL bClose)
|
|
{
|
|
HANDLE hEvent;
|
|
OVERLAPPED Overlapped;
|
|
DWORD i, dwLimit, dwToWrite, dwLocalSent, dwWaitResult;
|
|
DWORD dwHeaderSize = sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE);
|
|
BOOL bSucc = FALSE;
|
|
|
|
dwToWrite = BUF_SIZE;
|
|
dwLocalSent = 0;
|
|
|
|
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
Overlapped = { 0 };
|
|
Overlapped.hEvent = hEvent;
|
|
|
|
// number of writes
|
|
dwLimit = (unsigned int)ceil(nBytesToWrite / (double)BUF_SIZE);
|
|
// no content but close connection request.
|
|
if (!dwLimit && bClose)
|
|
dwLimit = 1;
|
|
|
|
// mandatory header with
|
|
memcpy_s(Buffer - dwHeaderSize, 4, &dwRemoteThreadId, sizeof(DWORD));
|
|
memcpy_s(Buffer + sizeof(DWORD) - dwHeaderSize, 4, &dwToWrite, sizeof(DWORD));
|
|
Buffer[sizeof(DWORD) + sizeof(DWORD) - dwHeaderSize] = 0;
|
|
|
|
dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
|
|
switch (dwWaitResult)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
for (i = 0; i < dwLimit; i++)
|
|
{
|
|
if (i == dwLimit - 1)
|
|
{
|
|
dwToWrite = nBytesToWrite % (BUF_SIZE + 1);
|
|
memcpy_s(Buffer + sizeof(DWORD) - 9, 4, &dwToWrite, sizeof(DWORD));
|
|
if (bClose) Buffer[sizeof(DWORD) + sizeof(DWORD) - 9] = 0x01;
|
|
}
|
|
//printf("%08X: CHANNEL Sent: %ld content length: %ld\n", dwRemoteThreadId, dwToWrite + 9, dwToWrite);
|
|
|
|
bSucc = WriteFile(hChannel, Buffer - 9, dwToWrite + 9, &dwLocalSent, &Overlapped);
|
|
if (!bSucc)
|
|
{
|
|
if (GetLastError() == ERROR_IO_PENDING)
|
|
{
|
|
WaitForSingleObject(Overlapped.hEvent, INFINITE);
|
|
bSucc = GetOverlappedResult(hChannel, &Overlapped, &dwLocalSent, TRUE);
|
|
}
|
|
}
|
|
if (!bSucc)
|
|
{
|
|
if (bVerbose) printf("[-] hChannel thread(%08X) WriteChannel: %ld\n", GetCurrentThreadId(), GetLastError());
|
|
if (!ReleaseMutex(ghMutex))
|
|
{
|
|
printf("Release failed1\n");
|
|
}
|
|
return FALSE;
|
|
}
|
|
*nBytesWrittes += dwLocalSent;
|
|
}
|
|
|
|
if (!ReleaseMutex(ghMutex))
|
|
{
|
|
printf("Release failed2\n");
|
|
}
|
|
return bSucc;
|
|
break;
|
|
|
|
case WAIT_ABANDONED:
|
|
return FALSE;
|
|
}
|
|
|
|
return bSucc;
|
|
}
|
|
|
|
int CheckAuthentication(char *buf_full, int ret)
|
|
{
|
|
DWORD i, j, dwWritten = 2;
|
|
char *answer, *buf, answer_tosend[2 + sizeof(DWORD) + sizeof(DWORD) + 1];
|
|
struct threads *pta;
|
|
|
|
buf = buf_full + 1;
|
|
answer = answer_tosend + sizeof(DWORD) + sizeof(DWORD) + 1;
|
|
|
|
pta = LookupThread(GetCurrentThreadId());
|
|
|
|
answer[0] = 5;
|
|
|
|
for (i = 0; i < METHOD_NUMBER; i++)
|
|
for (j = 0; j < (unsigned char)buf[1]; j++)
|
|
if (buf[j + 2] == method_numbers[i])
|
|
{
|
|
answer[1] = method_numbers[i];
|
|
WriteChannel(answer, 2, &dwWritten, pta->dwRemoteThreadId, FALSE);
|
|
return i;
|
|
}
|
|
|
|
answer[1] = (unsigned)0xFF;
|
|
|
|
WriteChannel(answer, 2, &dwWritten, pta->dwRemoteThreadId, FALSE);
|
|
|
|
return -1;
|
|
}
|
|
|
|
void sendReply(char replyField, char addressType, char *addr, char *port)
|
|
{
|
|
char null[20], *answer, answer2[300 + sizeof(DWORD) + sizeof(DWORD) + 1];
|
|
DWORD dwWritten, ret;
|
|
|
|
struct threads *pta;
|
|
|
|
answer = answer2 + sizeof(DWORD) + sizeof(DWORD) + 1;
|
|
memset(answer, 0, 300 + sizeof(DWORD) + sizeof(DWORD) + 1);
|
|
memset(null, 0, 20);
|
|
|
|
pta = LookupThread(GetCurrentThreadId());
|
|
|
|
// if addr or port set to NULL, we will send nulls instead of the address
|
|
// it isn't RFC compliant but I do not support info leak either.
|
|
if (addr == NULL) addr = null;
|
|
if (port == NULL) port = null;
|
|
|
|
answer[0] = 5;
|
|
|
|
answer[1] = replyField;
|
|
answer[3] = addressType;
|
|
|
|
switch (addressType)
|
|
{
|
|
case 3:
|
|
memcpy_s(answer + 4, 296, (void *)(addr + 1), (unsigned char)(addr[0]));
|
|
memcpy_s(answer + 4 + (unsigned char)(addr[0]), 396 - (unsigned char)(addr[0]), port, 2);
|
|
ret = (unsigned char)(addr[0]) + 2;
|
|
break;
|
|
case 4:
|
|
memcpy_s(answer + 4, 296, addr, 16);
|
|
memcpy_s(answer + 20, 280, port, 2);
|
|
ret = 22;
|
|
break;
|
|
default:
|
|
memcpy_s(answer + 4, 296, addr, 4);
|
|
memcpy_s(answer + 8, 292, port, 2);
|
|
ret = 10;
|
|
break;
|
|
}
|
|
|
|
if (replyField == 0x00)
|
|
WriteChannel(answer, ret, &dwWritten, pta->dwRemoteThreadId, FALSE);
|
|
else
|
|
WriteChannel(answer, ret, &dwWritten, pta->dwRemoteThreadId, TRUE);
|
|
}
|
|
|
|
int getAddressInfo(sockaddr_in *sockaddrin, sockaddr_in6 *sockaddrin6, char *buf, int ret)
|
|
{
|
|
ADDRINFOA hints;
|
|
ADDRINFOA *result = NULL;
|
|
|
|
char domain[256];
|
|
|
|
//IPv4
|
|
if (buf[3] == 1)
|
|
{
|
|
if (ret != 10)
|
|
{
|
|
if (bVerbose) printf("[-] SOCKS thread(%08Xd) getAddressInfo IPv4 selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
|
|
return -1;
|
|
}
|
|
sockaddrin->sin_family = AF_INET;
|
|
memcpy_s(&(sockaddrin->sin_port), 2, buf + 8, 2);
|
|
memcpy_s(&(sockaddrin->sin_addr), 4, buf + 4, 4);
|
|
|
|
char *s = (char *)malloc(INET_ADDRSTRLEN);
|
|
inet_ntop(AF_INET, &(sockaddrin->sin_addr), s, INET_ADDRSTRLEN);
|
|
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT IPv4: %s:%hd\n", GetCurrentThreadId(), s, htons(sockaddrin->sin_port));
|
|
free(s);
|
|
}
|
|
//DNS
|
|
if (buf[3] == 3)
|
|
{
|
|
if ((7 + (unsigned char)buf[4]) != ret)
|
|
{
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo DNS selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
|
|
return -1;
|
|
}
|
|
ZeroMemory(&hints, sizeof(hints));
|
|
ZeroMemory(domain, 256);
|
|
|
|
// change for IPv6?
|
|
hints.ai_family = AF_INET;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
hints.ai_flags = AI_PASSIVE;
|
|
|
|
memcpy_s(domain, 256, (void *)(buf + 5), (unsigned char)(buf[4]));
|
|
|
|
if ((ret = GetAddrInfoA(domain, "1", &hints, &result)) != 0) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo GetAddrInfoA failed with error: %ld %ld\n", GetCurrentThreadId(), ret, WSAGetLastError());
|
|
return -1;
|
|
}
|
|
memcpy_s(sockaddrin, sizeof(sockaddr_in), result->ai_addr, sizeof(sockaddr_in));
|
|
memcpy_s(&(sockaddrin->sin_port), 2, buf + ((unsigned char)buf[4]) + 5, 2);
|
|
|
|
char *s = (char *)malloc(INET_ADDRSTRLEN);
|
|
inet_ntop(AF_INET, &(sockaddrin->sin_addr), s, INET_ADDRSTRLEN);
|
|
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT DNS: %s(%s):%hd\n", GetCurrentThreadId(), domain, s, htons(sockaddrin->sin_port));
|
|
free(s);
|
|
}
|
|
//IPv6
|
|
if (buf[3] == 4)
|
|
{
|
|
if (ret != 22)
|
|
{
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo IPv6 selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
|
|
return -1;
|
|
}
|
|
sockaddrin6->sin6_family = AF_INET6;
|
|
memcpy_s(&(sockaddrin6->sin6_port), 2, buf + 20, 2);
|
|
memcpy_s(&(sockaddrin6->sin6_addr), 30, buf + 4, 16);
|
|
|
|
char *s = (char *)malloc(INET6_ADDRSTRLEN);
|
|
inet_ntop(AF_INET6, &(sockaddrin6->sin6_addr), s, INET6_ADDRSTRLEN);
|
|
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT IPv6: %s:%hd\n", GetCurrentThreadId(), s, htons(sockaddrin6->sin6_port));
|
|
free(s);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SOCKET DoConnection(char *buf, int ret)
|
|
{
|
|
SOCKET sock;
|
|
sockaddr_in sockaddrin;
|
|
sockaddr_in6 sockaddrin6;
|
|
|
|
if (buf[0] == 5)
|
|
{
|
|
if (getAddressInfo(&sockaddrin, &sockaddrin6, buf, ret) < 0) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection could not create socket structs\n", GetCurrentThreadId());
|
|
// this isnt "general SOCKS server failure", but there no better error code
|
|
sendReply(0x01, 0x01, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
// CONNECT
|
|
if (buf[1] == 1)
|
|
{
|
|
if (buf[3] == 4)
|
|
{
|
|
if ((sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection socket6() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
|
|
sendReply(0x01, 0x04, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((ret = connect(sock, (SOCKADDR *)&sockaddrin6, sizeof(sockaddrin6))) == SOCKET_ERROR) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection connect6() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
|
|
sendReply(0x05, 0x04, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection socket() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
|
|
sendReply(0x01, 0x01, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((ret = connect(sock, (SOCKADDR *)&sockaddrin, sizeof(sockaddrin))) == SOCKET_ERROR) {
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection connect() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
|
|
sendReply(0x05, 0x01, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
sendReply(0x00, 0x01, NULL, NULL);
|
|
|
|
return sock;
|
|
}
|
|
// BIND
|
|
if (buf[1] == 2)
|
|
{
|
|
printf("[+] SOCKS DoConnection BIND\n");
|
|
}
|
|
// UDP ASSOCIATE
|
|
if (buf[1] == 3)
|
|
{
|
|
//SOCK_DGRAM
|
|
printf("[+] SOCKS DoConnection UDP ASSOCIATE\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection unknown SOCKS version\n", GetCurrentThreadId());
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Thread's main function that handles all communication of the corresponding
|
|
// connection. It's remote ThreadID attribute matches the server's threadID
|
|
// which will be used to track the connections.
|
|
DWORD WINAPI HandleClient(void *param)
|
|
{
|
|
struct threads *pta = (struct threads *)param;
|
|
WSANETWORKEVENTS NetworkEvents;
|
|
WSAOVERLAPPED SendOverlapped;
|
|
OVERLAPPED Overlapped_MailSlot;
|
|
HANDLE hEvents[2], hMailSlot = pta->hSlot_r;
|
|
DWORD dwRet, dwRecvN, dwSentN, dwSentPointer, Flags;
|
|
SOCKET sRelayConnection;
|
|
BOOL bClose = FALSE;
|
|
WSABUF DataBuf;
|
|
char buf[BUF_SIZE + 1];
|
|
int rc, iSrecvN, iAuthNum = -1;
|
|
|
|
Overlapped_MailSlot = { 0 };
|
|
|
|
// socks basics
|
|
if (ReadFile(hMailSlot, buf, BUF_SIZE + 1, &dwRet, NULL))
|
|
{
|
|
if (buf[0] == 0x01)
|
|
goto exitthread;
|
|
|
|
if (buf[1] == 4)
|
|
{
|
|
//socks4
|
|
if (bDebug) printf("%08X: SOCKS HandleClient Socks4 request\n", pta->dwRemoteThreadId);
|
|
goto exitthread;
|
|
}
|
|
else
|
|
if (buf[1] == 5)
|
|
{
|
|
// socks5
|
|
if (dwRet - 3 != buf[2])
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient wrong list length: %ld\n", pta->dwRemoteThreadId, dwRet);
|
|
goto exitthread;
|
|
}
|
|
|
|
if ((iAuthNum = CheckAuthentication(buf, dwRet)) < 0)
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient auth failed: %ld\n", pta->dwRemoteThreadId, iAuthNum);
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug)
|
|
{
|
|
printf("%08X: SOCKS HandleClient unknown Socks version number\n", pta->dwRemoteThreadId);
|
|
printf("%08X: Readfile ret: %ld\n", pta->dwRemoteThreadId, dwRet);
|
|
for (DWORD i = 0; i < dwRet; i++)
|
|
printf("%02X ", (unsigned char)buf[i]);
|
|
printf("\n");
|
|
}
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient while ReadFile error: %ld\n", pta->dwRemoteThreadId, GetLastError());
|
|
goto exitthread;
|
|
}
|
|
|
|
if (iAuthNum == -1)
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient wrong authnum: %ld\n", pta->dwRemoteThreadId, iAuthNum);
|
|
goto exitthread;
|
|
}
|
|
|
|
// socks authentication
|
|
if (iAuthNum > 0)
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient authentication invoked: %ld\n", pta->dwRemoteThreadId, iAuthNum);
|
|
|
|
if (ReadFile(hMailSlot, buf, BUF_SIZE, &dwRet, NULL))
|
|
{
|
|
if (dwRet > 2)
|
|
{
|
|
if (!method_functions[iAuthNum](hMailSlot, dwRet, buf))
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient authentication failed: %ld\n", pta->dwRemoteThreadId, iAuthNum);
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient less than 2 recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient authentication recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
|
|
goto exitthread;
|
|
}
|
|
}
|
|
|
|
// socks connection phase
|
|
if (ReadFile(hMailSlot, buf, BUF_SIZE, &dwRet, NULL))
|
|
{
|
|
if (dwRet > 0)
|
|
if (buf[0] == 0x01)
|
|
goto exitthread;
|
|
if (dwRet > 6)
|
|
{
|
|
if ((sRelayConnection = DoConnection(buf + 1, dwRet - 1)) == NULL)
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient no socket created\n", pta->dwRemoteThreadId);
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient connection request less than 6 error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
|
|
goto exitthread;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) printf("%08X: SOCKS HandleClient connection request recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
|
|
goto exitthread;
|
|
}
|
|
|
|
|
|
hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
pta->hSlot_event = hEvents[0];
|
|
|
|
Overlapped_MailSlot.hEvent = hEvents[0];
|
|
|
|
SecureZeroMemory((PVOID)& SendOverlapped, sizeof(WSAOVERLAPPED));
|
|
SendOverlapped.hEvent = WSACreateEvent();
|
|
if (SendOverlapped.hEvent == NULL) {
|
|
printf("Mailslot thread(%08X) WSACreateEvent failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
|
|
goto exitthread;
|
|
}
|
|
|
|
if ((hEvents[0] == NULL) || ((hEvents[1] == NULL)))
|
|
{
|
|
printf("[-] Mailslot thread(%08X) CreateEvent failed with %ld\n", pta->dwRemoteThreadId, GetLastError());
|
|
goto exitthread;
|
|
}
|
|
|
|
WSAEventSelect(sRelayConnection, hEvents[1], FD_READ | FD_CLOSE);
|
|
|
|
BOOL read = true;
|
|
|
|
while (pta->run)
|
|
{
|
|
if (read)
|
|
{
|
|
if (ReadFile(hMailSlot, buf, BUF_SIZE + 1, &dwRecvN, &Overlapped_MailSlot) == FALSE)
|
|
{
|
|
if (GetLastError() != ERROR_IO_PENDING)
|
|
{
|
|
printf("[-] Mailslot thread(%08X) ReadFile error %ld\n", pta->dwRemoteThreadId, GetLastError());
|
|
pta->run = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
read = FALSE;
|
|
}
|
|
|
|
dwRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
|
|
if ((dwRet - WAIT_OBJECT_0) < 0 || (dwRet - WAIT_OBJECT_0) > (2 - 1))
|
|
{
|
|
printf("[-] Mailslot thread(%08X) WaitForMultipleObjects index out of range %ld\n", pta->dwRemoteThreadId, dwRet);
|
|
pta->run = FALSE;
|
|
break;
|
|
}
|
|
if (pta->run == FALSE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
switch (dwRet - WAIT_OBJECT_0)
|
|
{
|
|
case 0:
|
|
if (bDebug) printf("%08X: READ recvn: %ld - internalhigh: %ld - internal: %ld\n", pta->dwRemoteThreadId, dwRecvN, Overlapped_MailSlot.InternalHigh, Overlapped_MailSlot.Internal);
|
|
dwRecvN = Overlapped_MailSlot.InternalHigh;
|
|
if (buf[0] == 0x01)
|
|
{
|
|
pta->run = FALSE;
|
|
}
|
|
|
|
dwSentPointer = 1;
|
|
while (dwSentPointer < dwRecvN)
|
|
{
|
|
if (!pta->run)
|
|
{
|
|
//printf("%08X: was set to exit1\n", pta->dwRemoteThreadId);
|
|
break;
|
|
}
|
|
|
|
DataBuf.len = dwRecvN - dwSentPointer;
|
|
DataBuf.buf = buf + dwSentPointer;
|
|
|
|
rc = WSASend(sRelayConnection, &DataBuf, 1, &dwSentN, NULL, &SendOverlapped, NULL);
|
|
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != WSAGetLastError()))
|
|
{
|
|
printf("[-] Mailslot thread(%08X) WSASend failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
|
|
pta->run = FALSE;
|
|
break;
|
|
}
|
|
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE, TRUE);
|
|
if (rc == WSA_WAIT_FAILED)
|
|
{
|
|
printf("[-] Mailslot thread(%08X) WSAWaitForMultipleEvents failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
|
|
pta->run = FALSE;
|
|
break;
|
|
}
|
|
rc = WSAGetOverlappedResult(sRelayConnection, &SendOverlapped, &dwSentN, FALSE, &Flags);
|
|
if (rc == FALSE)
|
|
{
|
|
printf("[-] Mailslot thread(%08X) WSASend failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
|
|
pta->run = FALSE;
|
|
break;
|
|
}
|
|
WSAResetEvent(SendOverlapped.hEvent);
|
|
|
|
dwSentPointer += dwSentN;
|
|
}
|
|
read = TRUE;
|
|
|
|
break;
|
|
case 1:
|
|
if (WSAEnumNetworkEvents(sRelayConnection, hEvents[1], &NetworkEvents) == SOCKET_ERROR) {
|
|
printf("[-] SOCKS thread(%08X) HandleClient WSAEnumNetworkEvents error: %ld\n", pta->dwRemoteThreadId, GetLastError());
|
|
}
|
|
else
|
|
{
|
|
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
|
|
{
|
|
if (bDebug) printf("%08X: bClose FD_CLOSE was set\n", pta->dwRemoteThreadId);
|
|
bClose = TRUE;
|
|
}
|
|
}
|
|
do
|
|
{
|
|
if ((iSrecvN = recv(sRelayConnection, buf + sizeof(DWORD) + sizeof(DWORD) + 1, BUF_SIZE, 0)) > 0)
|
|
{
|
|
if (bDebug) printf("%08X: RECV recvn: %ld\n", pta->dwRemoteThreadId, iSrecvN);
|
|
dwSentPointer = 0;
|
|
if (!WriteChannel(buf + sizeof(DWORD) + sizeof(DWORD) + 1, iSrecvN, &dwSentPointer, pta->dwRemoteThreadId, FALSE))
|
|
{
|
|
pta->run = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bClose = TRUE;
|
|
}
|
|
|
|
// run again the loop only if there is more data and the last data packet was set to FIN
|
|
} while (bClose && (iSrecvN > 0));
|
|
if (bClose)
|
|
{
|
|
if (bDebug) printf("%08X: CLOSE\n", pta->dwRemoteThreadId);
|
|
|
|
if (!WriteChannel(buf + sizeof(DWORD) + sizeof(DWORD) + 1, 0, &dwSentPointer, pta->dwRemoteThreadId, TRUE))
|
|
printf("[-] Mailslot thread(%08X) HandleClient select1 WriteChannel error: %ld %ld\n", pta->dwRemoteThreadId, dwSentN, GetLastError());
|
|
|
|
// FIN recv'd
|
|
if (iSrecvN == SOCKET_ERROR)
|
|
{
|
|
if (bVerbose) printf("[-] SOCKS thread(%08X) HandleClient select1 recv error: %ld %ld\n", pta->dwRemoteThreadId, iSrecvN, WSAGetLastError());
|
|
}
|
|
pta->run = FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
WSACloseEvent(SendOverlapped.hEvent);
|
|
exitthread:
|
|
// closing down the thread
|
|
shutdown(sRelayConnection, SD_SEND);
|
|
CloseHandle(pta->hSlot_r);
|
|
CloseHandle(pta->hSlot_w);
|
|
CloseHandle(hEvents[0]);
|
|
CloseHandle(hEvents[1]);
|
|
DeleteThread(GetCurrentThreadId());
|
|
|
|
return 0;
|
|
}
|