AdaptixC2-Mod0/AdaptixClient/Source/Workers/SocksHandshakeWorker.cpp
2026-04-06 00:20:51 -05:00

231 lines
7.9 KiB
C++

#include <Workers/SocksHandshakeWorker.h>
#include <Workers/TunnelWorker.h>
#include <Client/Requestor.h>
SocksHandshakeWorker::SocksHandshakeWorker(QTcpSocket* sock, const QString& tunnelId, const QString& type, bool useAuth, const QString& username, const QString& password, const QString& accessToken, const QString& baseUrl, const QUrl& wsUrl)
: clientSock(sock), tunnelId(tunnelId), tunnelType(type), useAuth(useAuth), username(username), password(password), accessToken(accessToken), baseUrl(baseUrl), wsUrl(wsUrl)
{
}
SocksHandshakeWorker::~SocksHandshakeWorker() = default;
void SocksHandshakeWorker::rejectAndClose(QTcpSocket* sock, const QByteArray& response)
{
sock->write(response);
sock->flush();
sock->disconnectFromHost();
}
void SocksHandshakeWorker::process()
{
QJsonObject otpData;
QString channelId;
bool success = false;
if (tunnelType == "socks4") {
success = processSocks4(otpData, channelId);
} else if (tunnelType == "socks5") {
success = processSocks5(otpData, channelId);
}
if (!success) {
if (clientSock) {
clientSock->deleteLater();
}
Q_EMIT handshakeFailed();
return;
}
QString otp;
bool otpResult = HttpReqGetOTP("channel_tunnel", otpData, baseUrl, accessToken, &otp);
if (!otpResult) {
if (clientSock)
clientSock->deleteLater();
Q_EMIT handshakeFailed();
return;
}
TunnelWorker* worker = new TunnelWorker(clientSock, otp, wsUrl);
clientSock->setParent(worker);
Q_EMIT workerReady(worker, channelId);
}
bool SocksHandshakeWorker::processSocks4(QJsonObject& otpData, QString& channelId)
{
if (!clientSock->waitForReadyRead(3000) || clientSock->bytesAvailable() < 8) {
rejectAndClose(clientSock, QByteArray("\x00\x5b\x00\x00\x00\x00\x00\x00", 8));
return false;
}
QByteArray bufArray = clientSock->read(8);
const uchar* buf = reinterpret_cast<const uchar*>(bufArray.constData());
if (buf[0] != 0x04 || buf[1] != 0x01) {
rejectAndClose(clientSock, QByteArray("\x00\x5b\x00\x00\x00\x00\x00\x00", 8));
return false;
}
int tPort = (static_cast<quint16>(buf[2]) << 8) | static_cast<quint16>(buf[3]);
QHostAddress dstIp((static_cast<quint32>(buf[4]) << 24) | (static_cast<quint32>(buf[5]) << 16) |
(static_cast<quint32>(buf[6]) << 8) | static_cast<quint32>(buf[7]));
channelId = GenerateRandomString(8, "hex");
otpData["tunnel_id"] = tunnelId;
otpData["channel_id"] = channelId;
otpData["host"] = dstIp.toString();
otpData["port"] = QString::number(tPort);
return true;
}
bool SocksHandshakeWorker::processSocks5(QJsonObject& otpData, QString& channelId)
{
if (!clientSock->waitForReadyRead(3000) || clientSock->bytesAvailable() < 2) {
rejectAndClose(clientSock, QByteArray("\x00\x01\x00", 3));
return false;
}
QByteArray buf = clientSock->read(2);
if (buf.size() != 2 || static_cast<uchar>(buf[0]) != 0x05) {
rejectAndClose(clientSock, QByteArray("\x00\x01\x00", 3));
return false;
}
uchar socksAuthCount = static_cast<uchar>(buf[1]);
buf = clientSock->read(socksAuthCount);
if (buf.size() != socksAuthCount) {
rejectAndClose(clientSock, QByteArray("\x05\xFF\x00", 3));
return false;
}
if (useAuth) {
if (!buf.contains(0x02)) {
rejectAndClose(clientSock, QByteArray("\x05\xFF\x00", 3));
return false;
}
clientSock->write(QByteArray("\x05\x02", 2));
clientSock->flush();
if (!clientSock->waitForReadyRead(3000) || clientSock->bytesAvailable() < 2) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
buf = clientSock->read(2);
if (buf.size() != 2 || static_cast<uchar>(buf[0]) != 0x01) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
uchar usernameLen = static_cast<uchar>(buf[1]);
buf = clientSock->read(usernameLen);
if (buf.size() != usernameLen) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
QString recvUsername = QString::fromUtf8(buf);
buf = clientSock->read(1);
if (buf.size() != 1) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
uchar passwordLen = static_cast<uchar>(buf[0]);
buf = clientSock->read(passwordLen);
if (buf.size() != passwordLen) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
QString recvPassword = QString::fromUtf8(buf);
if (recvUsername != username || recvPassword != password) {
rejectAndClose(clientSock, QByteArray("\x01\x01", 2));
return false;
}
clientSock->write(QByteArray("\x01\x00", 2));
clientSock->flush();
}
else {
if (!buf.contains(0x00)) {
rejectAndClose(clientSock, QByteArray("\x05\xFF\x00", 3));
return false;
}
clientSock->write(QByteArray("\x05\x00", 2));
clientSock->flush();
}
if (!clientSock->waitForReadyRead(3000)) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
buf = clientSock->read(4);
if (buf.size() != 4 || static_cast<uchar>(buf[0]) != 0x05 || static_cast<uchar>(buf[1]) != 0x01) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
uchar addrType = static_cast<uchar>(buf[3]);
QString mode = "tcp";
QString dstAddress;
switch (addrType) {
case 0x01: {
buf = clientSock->read(4);
if (buf.size() != 4) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
QHostAddress ip((static_cast<uchar>(buf[0]) << 24) | (static_cast<uchar>(buf[1]) << 16) |
(static_cast<uchar>(buf[2]) << 8) | static_cast<uchar>(buf[3]));
dstAddress = ip.toString();
break;
}
case 0x03: {
buf = clientSock->read(1);
if (buf.size() != 1) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
uchar domainLen = static_cast<uchar>(buf[0]);
buf = clientSock->read(domainLen);
if (buf.size() != domainLen) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
dstAddress = QString::fromUtf8(buf);
break;
}
case 0x04: {
buf = clientSock->read(16);
if (buf.size() != 16) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
QHostAddress ip(buf);
dstAddress = ip.toString();
break;
}
default: {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
}
buf = clientSock->read(2);
if (buf.size() != 2) {
rejectAndClose(clientSock, QByteArray("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", 10));
return false;
}
quint16 dstPort = (static_cast<uchar>(buf[0]) << 8) | static_cast<uchar>(buf[1]);
channelId = GenerateRandomString(8, "hex");
otpData["tunnel_id"] = tunnelId;
otpData["channel_id"] = channelId;
otpData["mode"] = mode;
otpData["host"] = dstAddress;
otpData["port"] = QString::number(dstPort);
return true;
}