Release v1.1.3

This commit is contained in:
yuanyuanxiang
2025-07-19 21:37:50 +08:00
parent e7f06abcea
commit 1b1ce090c8
14 changed files with 184 additions and 27 deletions

View File

@@ -273,6 +273,22 @@
* 插件:#145 支持远程画板功能 * 插件:#145 支持远程画板功能
* 插件:增加远程桌面隐私屏幕功能 * 插件:增加远程桌面隐私屏幕功能
**2025.07.19**
Release v1.1.3
- 添加加密和解密函数
- 修改弹出消息为通过 `NM_DBLCLK` 触发
- 改进:将 DLL 数据保存到注册表中
- 新功能:支持 HTTP 协议并添加构建选项
- 新功能:为客户端构建添加加密选项
- 改进:减少鼠标移动消息的传输
- 修复:在操作高权限窗口时失去控制的问题
- 改进:通过异常处理提升客户端稳定性
- 新功能:远程桌面支持多显示器
- 改进:支持授权在线主机数量
- 修复:#159 在 TestRun 注入模式下授权无效的问题
--- ---
# 6.其他项目 <a id="6-other-projects"></a> # 6.其他项目 <a id="6-other-projects"></a>

View File

@@ -290,6 +290,22 @@ Release v1.1.2:
* Plugin: #145 Support remote drawing board * Plugin: #145 Support remote drawing board
* Plugin: Add remote desktop privacy screen feature * Plugin: Add remote desktop privacy screen feature
**2025.07.19**
Release v1.1.3
* Add encrypt and decrypt functions
* Modify the popup message to be triggered by `NM_DBLCLK`
* Improve: Save DLL data to registry
* Feature: Support HTTP protocol and add building option
* Feature: Add encryption option for client building
* Improvement: Reduce transmit mouse move message
* fix: Lost control when operating high permission windows
* Improve client stability by handling exceptions
* feature: Remote desktop support multi monitor
* Improve: Support authorizing the online host quantity
* fix#159 Authorization doesn't work under TestRun injection
--- ---
# 6. Related Projects # 6. Related Projects

BIN
Releases/v1.1.3/Yama.exe Normal file

Binary file not shown.

View File

@@ -233,8 +233,9 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
HANDLE hMutex = OpenMutex(SYNCHRONIZE, FALSE, "MASTER.EXE"); HANDLE hMutex = OpenMutex(SYNCHRONIZE, FALSE, "MASTER.EXE");
hMutex = hMutex ? hMutex : OpenMutex(SYNCHRONIZE, FALSE, "YAMA.EXE"); hMutex = hMutex ? hMutex : OpenMutex(SYNCHRONIZE, FALSE, "YAMA.EXE");
#ifndef _DEBUG #ifndef _DEBUG
if (hMutex == NULL) // û<>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD> if (hMutex == NULL) { // û<>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>
break; Mprintf("!!! [WARN] Master program is not running.\n");
}
#endif #endif
CloseHandle(hMutex); CloseHandle(hMutex);
@@ -244,14 +245,19 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
const char* pwdHash = m_conn->pwdHash[0] ? m_conn->pwdHash : masterHash.c_str(); const char* pwdHash = m_conn->pwdHash[0] ? m_conn->pwdHash : masterHash.c_str();
if (passCode[0] == 0) { if (passCode[0] == 0) {
std::string devId = getDeviceID(); std::string devId = getDeviceID();
memcpy(buf + 24, buf + 12, 8); // <20><>Ϣǩ<CFA2><C7A9>
memcpy(buf + 96, buf + 8, 4); // ʱ<><CAB1><EFBFBD><EFBFBD>
memcpy(buf + 5, devId.c_str(), devId.length()); // 16<31>ֽ<EFBFBD> memcpy(buf + 5, devId.c_str(), devId.length()); // 16<31>ֽ<EFBFBD>
memcpy(buf + 32, pwdHash, 64); // 64<36>ֽ<EFBFBD> memcpy(buf + 32, pwdHash, 64); // 64<36>ֽ<EFBFBD>
m_ClientObject->Send2Server((char*)buf, sizeof(buf)); m_ClientObject->Send2Server((char*)buf, sizeof(buf));
Mprintf("Request for authorization update.\n");
} else { } else {
int* days = (int*)(buf + 1); unsigned short* days = (unsigned short*)(buf + 1);
unsigned short* num = (unsigned short*)(buf + 3);
config* cfg = pwdHash == masterHash ? new config : new iniFile; config* cfg = pwdHash == masterHash ? new config : new iniFile;
cfg->SetStr("settings", "Password", *days <= 0 ? "" : passCode); cfg->SetStr("settings", "Password", *days <= 0 ? "" : passCode);
cfg->SetStr("settings", "HMAC", *days <= 0 ? "" : buf + 64); cfg->SetStr("settings", "HMAC", *days <= 0 ? "" : buf + 64);
Mprintf("Update authorization: %s, HMAC: %s\n", passCode, buf+64);
delete cfg; delete cfg;
g_bExit = S_SERVER_EXIT; g_bExit = S_SERVER_EXIT;
} }

View File

@@ -88,7 +88,7 @@ IDR_WAVE WAVE "Res\\msg.wav"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,1,2 FILEVERSION 1,0,1,3
PRODUCTVERSION 1,0,0,1 PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
@@ -106,7 +106,7 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "FUCK THE UNIVERSE" VALUE "CompanyName", "FUCK THE UNIVERSE"
VALUE "FileDescription", "A GHOST" VALUE "FileDescription", "A GHOST"
VALUE "FileVersion", "1.0.1.2" VALUE "FileVersion", "1.0.1.3"
VALUE "InternalName", "ServerDll.dll" VALUE "InternalName", "ServerDll.dll"
VALUE "LegalCopyright", "Copyright (C) 2019-2025" VALUE "LegalCopyright", "Copyright (C) 2019-2025"
VALUE "OriginalFilename", "ServerDll.dll" VALUE "OriginalFilename", "ServerDll.dll"

Binary file not shown.

View File

@@ -948,7 +948,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
return FALSE; return FALSE;
} }
#ifdef _DEBUG #ifdef _DEBUG
SetTimer(TIMER_CHECK, 60 * 1000, NULL); SetTimer(TIMER_CHECK, 10 * 1000, NULL);
#else #else
SetTimer(TIMER_CHECK, 600 * 1000, NULL); SetTimer(TIMER_CHECK, 600 * 1000, NULL);
#endif #endif
@@ -1464,11 +1464,7 @@ std::string joinString(const std::vector<std::string>& tokens, char delimiter) {
bool CMy2015RemoteDlg::CheckValid(int trail) { bool CMy2015RemoteDlg::CheckValid(int trail) {
DateVerify verify; DateVerify verify;
#ifdef _DEBUG
BOOL isTrail = verify.isTrail(0);
#else
BOOL isTrail = verify.isTrail(trail); BOOL isTrail = verify.isTrail(trail);
#endif
if (!isTrail) { if (!isTrail) {
const Validation *verify = GetValidation(); const Validation *verify = GetValidation();
@@ -1845,13 +1841,32 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
if (n < 100) break; if (n < 100) break;
char resp[100] = { 0 }, *devId = resp + 5, *pwdHash = resp + 32; char resp[100] = { 0 }, *devId = resp + 5, *pwdHash = resp + 32;
ContextObject->InDeCompressedBuffer.CopyBuffer(resp, min(n, sizeof(resp)), 0); ContextObject->InDeCompressedBuffer.CopyBuffer(resp, min(n, sizeof(resp)), 0);
int *days = (int*)(resp+1); unsigned short* days = (unsigned short*)(resp + 1);
if (devId[0] == 0 || pwdHash[0] == 0)break; unsigned short* num = (unsigned short*)(resp + 3);
// 密码形式20250209 - 20350209: SHA256 BYTE msg[12] = {};
std::string hash = pwdHash; memcpy(msg, resp, 5);
std::string password = getDateStr(0) + " - " + getDateStr(*days) + ": " + pwdHash; memcpy(msg+8, resp+96, 4);
std::string finalKey = deriveKey(password, devId); uint32_t now = clock();
std::string fixedKey = getDateStr(0) + std::string("-") + getDateStr(*days) + std::string("-") + getFixedLengthID(finalKey); uint32_t tm = *(uint32_t*)(resp + 96);
if (now < tm || now - tm > 30000) {
Mprintf("Get authorization timeout[%s], devId: %s, pwdHash:%s", ContextObject->PeerName.c_str(),
devId, pwdHash);
break;
}
uint64_t signature = *(uint64_t*)(resp + 24);
if (devId[0] == 0 || pwdHash[0] == 0 || !VerifyMessage(m_superPass, msg, sizeof(msg), signature)){
Mprintf("Get authorization failed[%s], devId: %s, pwdHash:%s\n", ContextObject->PeerName.c_str(),
devId, pwdHash);
break;
}
char hostNum[10] = {};
sprintf(hostNum, "%04d", *num);
// 密码形式20250209 - 20350209: SHA256: HostNum
std::string hash = std::string(pwdHash, pwdHash+64);
std::string password = getDateStr(0) + " - " + getDateStr(*days) + ": " + hash + ": " + hostNum;
std::string finalKey = deriveKey(password, std::string(devId, devId+19));
std::string fixedKey = getDateStr(0) + std::string("-") + getDateStr(*days) + "-" + hostNum +
std::string("-") + getFixedLengthID(finalKey);
memcpy(devId, fixedKey.c_str(), fixedKey.length()); memcpy(devId, fixedKey.c_str(), fixedKey.length());
devId[fixedKey.length()] = 0; devId[fixedKey.length()] = 0;
std::string hmac = genHMAC(hash, m_superPass); std::string hmac = genHMAC(hash, m_superPass);
@@ -2726,11 +2741,19 @@ void CMy2015RemoteDlg::OnOnlineAuthorize()
CInputDialog dlg(this); CInputDialog dlg(this);
dlg.Init("延长授权", "主控程序授权天数:"); dlg.Init("延长授权", "主控程序授权天数:");
dlg.Init2("并发上线机器数量:", std::to_string(100).c_str());
if (dlg.DoModal() != IDOK || atoi(dlg.m_str) <= 0) if (dlg.DoModal() != IDOK || atoi(dlg.m_str) <= 0)
return; return;
BYTE bToken[32] = { CMD_AUTHORIZATION }; BYTE bToken[32] = { CMD_AUTHORIZATION };
int days = atoi(dlg.m_str); unsigned short days = atoi(dlg.m_str);
unsigned short num = atoi(dlg.m_sSecondInput);
uint32_t tm = clock();
// 2字节天数+2字节主机数+4字节时间戳+消息签名
memcpy(bToken+1, &days, sizeof(days)); memcpy(bToken+1, &days, sizeof(days));
memcpy(bToken+3, &num, sizeof(num));
memcpy(bToken + 8, &tm, sizeof(tm));
uint64_t signature = SignMessage(m_superPass, bToken, 12);
memcpy(bToken + 12, &signature, sizeof(signature));
SendSelectedCommand(bToken, sizeof(bToken)); SendSelectedCommand(bToken, sizeof(bToken));
} }
@@ -2814,8 +2837,15 @@ void CMy2015RemoteDlg::OnOnlineUnauthorize()
} }
BYTE bToken[32] = { CMD_AUTHORIZATION }; BYTE bToken[32] = { CMD_AUTHORIZATION };
int days = -1; unsigned short days = 0;
unsigned short num = 1;
uint32_t tm = clock();
// 2字节天数+2字节主机数+4字节时间戳+消息签名
memcpy(bToken + 1, &days, sizeof(days)); memcpy(bToken + 1, &days, sizeof(days));
memcpy(bToken + 3, &num, sizeof(num));
memcpy(bToken + 8, &tm, sizeof(tm));
uint64_t signature = SignMessage(m_superPass, bToken, 12);
memcpy(bToken + 12, &signature, sizeof(signature));
SendSelectedCommand(bToken, sizeof(bToken)); SendSelectedCommand(bToken, sizeof(bToken));
} }

View File

@@ -1778,7 +1778,8 @@ void CFileManagerDlg::WriteLocalRecvFile()
} }
if (i == MAX_WRITE_RETRY && nRet <= 0) if (i == MAX_WRITE_RETRY && nRet <= 0)
{ {
::MessageBox(m_hWnd, m_strReceiveLocalFile + " <20>ļ<EFBFBD>д<EFBFBD><D0B4>ʧ<EFBFBD><CAA7>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_OK|MB_ICONWARNING); ::MessageBox(m_hWnd, m_strReceiveLocalFile + " <20>ļ<EFBFBD>д<EFBFBD><D0B4>ʧ<EFBFBD><CAA7>!", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_OK|MB_ICONWARNING);
m_bIsStop = true;
} }
CloseHandle(hFile); CloseHandle(hFile);
// Ϊ<>˱Ƚϣ<C8BD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // Ϊ<>˱Ƚϣ<C8BD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -12,6 +12,7 @@ IMPLEMENT_DYNAMIC(CInputDialog, CDialogEx)
CInputDialog::CInputDialog(CWnd* pParent /*=nullptr*/) CInputDialog::CInputDialog(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG_INPUT, pParent) : CDialogEx(IDD_DIALOG_INPUT, pParent)
, m_sSecondInput(_T(""))
{ {
m_hIcon = NULL; m_hIcon = NULL;
} }
@@ -23,6 +24,10 @@ CInputDialog::~CInputDialog()
void CInputDialog::DoDataExchange(CDataExchange* pDX) void CInputDialog::DoDataExchange(CDataExchange* pDX)
{ {
CDialogEx::DoDataExchange(pDX); CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_SECOND, m_Static2thInput);
DDX_Control(pDX, IDC_EDIT_SECOND, m_Edit2thInput);
DDX_Text(pDX, IDC_EDIT_SECOND, m_sSecondInput);
DDV_MaxChars(pDX, m_sSecondInput, 100);
} }
@@ -39,6 +44,11 @@ BOOL CInputDialog::Init(LPCTSTR caption, LPCTSTR prompt) {
return TRUE; return TRUE;
} }
void CInputDialog::Init2(LPCTSTR name, LPCTSTR defaultValue) {
m_sItemName = name;
m_sSecondInput = defaultValue;
}
BOOL CInputDialog::OnInitDialog() BOOL CInputDialog::OnInitDialog()
{ {
CDialogEx::OnInitDialog(); CDialogEx::OnInitDialog();
@@ -47,6 +57,11 @@ BOOL CInputDialog::OnInitDialog()
SetWindowText(m_sCaption); SetWindowText(m_sCaption);
GetDlgItem(IDC_STATIC)->SetWindowText(m_sPrompt); GetDlgItem(IDC_STATIC)->SetWindowText(m_sPrompt);
m_Static2thInput.SetWindowTextA(m_sItemName);
m_Static2thInput.ShowWindow(m_sItemName.IsEmpty() ? SW_HIDE : SW_SHOW);
m_Edit2thInput.SetWindowTextA(m_sSecondInput);
m_Edit2thInput.ShowWindow(m_sItemName.IsEmpty() ? SW_HIDE : SW_SHOW);
return TRUE; // return TRUE unless you set the focus to a control return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE // 异常: OCX 属性页应返回 FALSE

View File

@@ -14,6 +14,8 @@ public:
BOOL Init(LPCTSTR caption, LPCTSTR prompt); BOOL Init(LPCTSTR caption, LPCTSTR prompt);
void Init2(LPCTSTR name, LPCTSTR defaultValue);
// 对话框数据 // 对话框数据
#ifdef AFX_DESIGN_TIME #ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_INPUT }; enum { IDD = IDD_DIALOG_INPUT };
@@ -32,4 +34,8 @@ public:
CString m_str; CString m_str;
virtual BOOL OnInitDialog(); virtual BOOL OnInitDialog();
afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedOk();
CStatic m_Static2thInput;
CEdit m_Edit2thInput;
CString m_sItemName;
CString m_sSecondInput;
}; };

View File

@@ -1423,14 +1423,17 @@ void CFileManagerDlg::WriteLocalRecvFile()
break; break;
} }
if (i == MAX_WRITE_RETRY && !bResult) { if (i == MAX_WRITE_RETRY && !bResult) {
::MessageBox(m_hWnd, m_strReceiveLocalFile + _T(" <20>ļ<EFBFBD>д<EFBFBD><D0B4>ʧ<EFBFBD><CAA7>"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONWARNING); ::MessageBox(m_hWnd, m_strReceiveLocalFile + _T(" <20>ļ<EFBFBD>д<EFBFBD><D0B4>ʧ<EFBFBD><CAA7>!"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONWARNING);
m_bIsStop = true;
}
else {
dwOffsetLow = 0;
dwOffsetHigh = 0;
dwOffsetLow = SetFilePointer(m_hFileRecv, dwOffsetLow, &dwOffsetHigh, FILE_CURRENT);
// Ϊ<>˱Ƚϣ<C8BD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_nCounter += dwBytesWrite;
ShowProgress();
} }
dwOffsetLow = 0;
dwOffsetHigh = 0;
dwOffsetLow = SetFilePointer(m_hFileRecv, dwOffsetLow, &dwOffsetHigh, FILE_CURRENT);
// Ϊ<>˱Ƚϣ<C8BD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_nCounter += dwBytesWrite;
ShowProgress();
} }
if (m_bIsStop) if (m_bIsStop)
SendStop(TRUE); SendStop(TRUE);

View File

@@ -15,6 +15,7 @@
#include "common/commands.h" #include "common/commands.h"
#pragma comment(lib, "Advapi32.lib") #pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "bcrypt.lib")
// ִ<><D6B4>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EEA3AC>ȡӲ<C8A1><D3B2><EFBFBD><EFBFBD>Ϣ // ִ<><D6B4>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EEA3AC>ȡӲ<C8A1><D3B2><EFBFBD><EFBFBD>Ϣ
std::string execCommand(const char* cmd) { std::string execCommand(const char* cmd) {
@@ -143,3 +144,61 @@ std::string getDeviceID() {
std::string deviceID = getFixedLengthID(hashedID); std::string deviceID = getFixedLengthID(hashedID);
return deviceID; return deviceID;
} }
uint64_t SignMessage(const std::string& pwd, BYTE* msg, int len) {
BCRYPT_ALG_HANDLE hAlg = nullptr;
BCRYPT_HASH_HANDLE hHash = nullptr;
BYTE hash[32]; // SHA256 = 32 bytes
DWORD hashObjectSize = 0;
DWORD dataLen = 0;
PBYTE hashObject = nullptr;
uint64_t result = 0;
if (BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, nullptr, BCRYPT_ALG_HANDLE_HMAC_FLAG) != 0)
return 0;
if (BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hashObjectSize, sizeof(DWORD), &dataLen, 0) != 0) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return 0;
}
hashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hashObjectSize);
if (!hashObject) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return 0;
}
if (BCryptCreateHash(hAlg, &hHash, hashObject, hashObjectSize,
(PUCHAR)pwd.data(), static_cast<ULONG>(pwd.size()), 0) != 0) {
HeapFree(GetProcessHeap(), 0, hashObject);
BCryptCloseAlgorithmProvider(hAlg, 0);
return 0;
}
if (BCryptHashData(hHash, msg, len, 0) != 0) {
BCryptDestroyHash(hHash);
HeapFree(GetProcessHeap(), 0, hashObject);
BCryptCloseAlgorithmProvider(hAlg, 0);
return 0;
}
if (BCryptFinishHash(hHash, hash, sizeof(hash), 0) != 0) {
BCryptDestroyHash(hHash);
HeapFree(GetProcessHeap(), 0, hashObject);
BCryptCloseAlgorithmProvider(hAlg, 0);
return 0;
}
memcpy(&result, hash, sizeof(result));
BCryptDestroyHash(hHash);
HeapFree(GetProcessHeap(), 0, hashObject);
BCryptCloseAlgorithmProvider(hAlg, 0);
return result;
}
bool VerifyMessage(const std::string& pwd, BYTE* msg, int len, uint64_t signature) {
uint64_t computed = SignMessage(pwd, msg, len);
return computed == signature;
}

View File

@@ -16,3 +16,8 @@ std::string getFixedLengthID(const std::string& hash);
std::string deriveKey(const std::string& password, const std::string& hardwareID); std::string deriveKey(const std::string& password, const std::string& hardwareID);
std::string getDeviceID(); std::string getDeviceID();
// Use HMAC to sign a message.
uint64_t SignMessage(const std::string& pwd, BYTE* msg, int len);
bool VerifyMessage(const std::string& pwd, BYTE* msg, int len, uint64_t signature);

Binary file not shown.