3 Commits

Author SHA1 Message Date
yuanyuanxiang
36ba9ccc1d Release v1.3.2 2026-05-01 11:36:56 +02:00
yuanyuanxiang
ed4b9eeb25 Fix: Web remote desktop double-click not working for macOS clients 2026-05-01 11:08:12 +02:00
yuanyuanxiang
cfa9b581fc Fix: Full Disk Access permission check using actual file read 2026-05-01 09:32:15 +02:00
15 changed files with 238 additions and 59 deletions

View File

@@ -12,7 +12,7 @@
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
</a>
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
@@ -56,7 +56,7 @@
## 项目简介
**SimpleRemoter** 是一个功能完整的远程控制解决方案,基于经典的 Gh0st 框架重构,采用现代 C++17 开发。项目始于 2019 年,经过持续迭代已发展为支持 **Windows + Linux** 平台的企业级远程管理工具。
**SimpleRemoter** 是一个功能完整的远程控制解决方案,基于经典的 Gh0st 框架重构,采用现代 C++17 开发。项目始于 2019 年,经过持续迭代已发展为支持 **Windows + Linux + macOS** 平台的企业级远程管理工具。
### 核心能力
@@ -354,6 +354,7 @@ struct FileChunkPacketV2 {
| `TestRun.exe` + `ServerDll.dll` | 分离加载,支持内存加载 DLL |
| Windows 服务 | 后台运行,支持锁屏控制 |
| Linux 客户端 | 跨平台支持v1.2.5+ |
| macOS 客户端 | 跨平台支持v1.3.2+ |
---
@@ -489,10 +490,60 @@ cmake .
make
```
### macOS 客户端v1.3.2+
**系统要求**
- macOS 10.15 (Catalina) 及以上
- 需要授予系统权限:屏幕录制、辅助功能、完全磁盘访问
**功能支持**
| 功能 | 状态 | 实现 |
|------|------|------|
| 远程桌面 | ✅ | CoreGraphics 屏幕捕获H.264 硬件编码 |
| 鼠标控制 | ✅ | CGEvent 模拟,支持双击、拖拽 |
| 键盘控制 | ✅ | CGEvent 模拟,完整键码映射 |
| 光标同步 | ✅ | 实时同步远程光标样式 |
| 心跳/RTT | ✅ | RFC 6298 RTT 估算 |
| 文件管理 | ⏳ | 开发中 |
| 远程终端 | ⏳ | 开发中 |
**编译方式**
```bash
cd macos
mkdir build && cd build
cmake ..
make
```
---
## 更新日志
### v1.3.2 (2026.5.1)
**macOS 客户端 & Web 远程桌面增强**
**新功能:**
- macOS 客户端支持:全新实现的 macOS 原生客户端支持屏幕捕获、H.264 编码、键鼠控制、系统权限管理
- Web 远程桌面光标同步:浏览器端实时显示远程主机光标样式
- 触发器功能:支持主机上线事件触发自定义操作
- 用户管理功能:新增角色权限管理,支持多用户分级控制
- DLL 执行增强:参数持久化存储、支持自动运行配置
- 远程桌面输入法切换:支持远程切换被控端输入语言
**改进:**
- Web 远程桌面手势优化改进双指手势识别、双击拖拽、Shift 组合键支持
**Bug 修复:**
- 修复 Web 远程桌面在 macOS 客户端上双击无法打开文件的问题
- 修复 macOS 完全磁盘访问权限检测不准确的问题
- 修复 RestoreMemDLL 因 DLL 信息大小错误导致还原失败
- 修复多个 DLL 同时执行可能因全局变量冲突而失败
- 修复鼠标双击和远程桌面切换问题
- 修复 Linux 客户端编译缺少 libzstd.a 的问题
### v1.3.1 (2026.4.15)
**Web 远程桌面 & 多主控共享增强**

View File

@@ -12,7 +12,7 @@
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
</a>
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
@@ -55,7 +55,7 @@
## Overview
**SimpleRemoter** is a full-featured remote control solution, rebuilt from the classic Gh0st framework using modern C++17. Started in 2019, it has evolved into an enterprise-grade remote management tool supporting both **Windows and Linux** platforms.
**SimpleRemoter** is a full-featured remote control solution, rebuilt from the classic Gh0st framework using modern C++17. Started in 2019, it has evolved into an enterprise-grade remote management tool supporting **Windows, Linux, and macOS** platforms.
### Core Capabilities
@@ -354,6 +354,7 @@ The master program **YAMA.exe** provides a graphical management interface:
| `TestRun.exe` + `ServerDll.dll` | Separate loading, supports in-memory DLL loading |
| Windows Service | Background operation, supports lock screen control |
| Linux Client | Cross-platform support (v1.2.5+) |
| macOS Client | Cross-platform support (v1.3.2+) |
---
@@ -474,10 +475,60 @@ cmake .
make
```
### macOS Client (v1.3.2+)
**System Requirements**:
- macOS 10.15 (Catalina) or later
- Required permissions: Screen Recording, Accessibility, Full Disk Access
**Feature Support**:
| Feature | Status | Implementation |
|---------|--------|----------------|
| Remote Desktop | ✅ | CoreGraphics screen capture, H.264 hardware encoding |
| Mouse Control | ✅ | CGEvent simulation, supports double-click, drag |
| Keyboard Control | ✅ | CGEvent simulation, full keycode mapping |
| Cursor Sync | ✅ | Real-time remote cursor style synchronization |
| Heartbeat/RTT | ✅ | RFC 6298 RTT estimation |
| File Management | ⏳ | In development |
| Remote Terminal | ⏳ | In development |
**Build Instructions**:
```bash
cd macos
mkdir build && cd build
cmake ..
make
```
---
## Changelog
### v1.3.2 (2026.5.1)
**macOS Client & Web Remote Desktop Enhancement**
**New Features:**
- macOS client support: Native macOS client with screen capture, H.264 encoding, keyboard/mouse control, system permission management
- Web remote desktop cursor sync: Real-time display of remote host cursor style in browser
- Trigger functionality: Support custom actions triggered by host online events
- User management: Role-based permission management, multi-user hierarchical control
- DLL execution enhancements: Parameter persistence, auto-run configuration support
- Remote desktop input language switching: Support switching remote host input language
**Improvements:**
- Web remote desktop gesture optimization: Improved two-finger gesture recognition, double-tap drag, Shift key combination support
**Bug Fixes:**
- Fixed Web remote desktop double-click not working for macOS clients
- Fixed macOS Full Disk Access permission detection inaccuracy
- Fixed RestoreMemDLL failure due to incorrect DLL info size
- Fixed multiple DLLs execution failure due to global variable conflict
- Fixed mouse double-click and remote desktop switching issues
- Fixed Linux client build missing libzstd.a
### v1.3.1 (2026.4.15)
**Web Remote Desktop & Multi-Master Sharing Enhancement**

View File

@@ -12,7 +12,7 @@
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
</a>
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
@@ -55,7 +55,7 @@
## 專案簡介
**SimpleRemoter** 是一個功能完整的遠端控制解決方案,基於經典的 Gh0st 框架重構,採用現代 C++17 開發。專案始於 2019 年,經過持續迭代已發展為支援 **Windows + Linux** 平台的企業級遠端管理工具。
**SimpleRemoter** 是一個功能完整的遠端控制解決方案,基於經典的 Gh0st 框架重構,採用現代 C++17 開發。專案始於 2019 年,經過持續迭代已發展為支援 **Windows + Linux + macOS** 平台的企業級遠端管理工具。
### 核心能力
@@ -353,6 +353,7 @@ struct FileChunkPacketV2 {
| `TestRun.exe` + `ServerDll.dll` | 分離載入,支援記憶體載入 DLL |
| Windows 服務 | 背景執行,支援鎖定畫面控制 |
| Linux 用戶端 | 跨平台支援v1.2.5+ |
| macOS 用戶端 | 跨平台支援v1.3.2+ |
---
@@ -473,10 +474,60 @@ cmake .
make
```
### macOS 用戶端v1.3.2+
**系統要求**
- macOS 10.15 (Catalina) 及以上
- 需要授予系統權限:螢幕錄製、輔助使用、完全磁碟存取
**功能支援**
| 功能 | 狀態 | 實作 |
|------|------|------|
| 遠端桌面 | ✅ | CoreGraphics 螢幕擷取H.264 硬體編碼 |
| 滑鼠控制 | ✅ | CGEvent 模擬,支援雙擊、拖曳 |
| 鍵盤控制 | ✅ | CGEvent 模擬,完整鍵碼對應 |
| 游標同步 | ✅ | 即時同步遠端游標樣式 |
| 心跳/RTT | ✅ | RFC 6298 RTT 估算 |
| 檔案管理 | ⏳ | 開發中 |
| 遠端終端 | ⏳ | 開發中 |
**編譯方式**
```bash
cd macos
mkdir build && cd build
cmake ..
make
```
---
## 更新日誌
### v1.3.2 (2026.5.1)
**macOS 用戶端 & Web 遠端桌面增強**
**新功能:**
- macOS 用戶端支援:全新實現的 macOS 原生用戶端支援螢幕擷取、H.264 編碼、鍵鼠控制、系統權限管理
- Web 遠端桌面游標同步:瀏覽器端即時顯示遠端主機游標樣式
- 觸發器功能:支援主機上線事件觸發自訂操作
- 使用者管理功能:新增角色權限管理,支援多使用者分級控制
- DLL 執行增強:參數持久化儲存、支援自動執行設定
- 遠端桌面輸入法切換:支援遠端切換被控端輸入語言
**改進:**
- Web 遠端桌面手勢最佳化改進雙指手勢識別、雙擊拖曳、Shift 組合鍵支援
**Bug 修復:**
- 修復 Web 遠端桌面在 macOS 用戶端上雙擊無法開啟檔案的問題
- 修復 macOS 完全磁碟存取權限偵測不準確的問題
- 修復 RestoreMemDLL 因 DLL 資訊大小錯誤導致還原失敗
- 修復多個 DLL 同時執行可能因全域變數衝突而失敗
- 修復滑鼠雙擊和遠端桌面切換問題
- 修復 Linux 用戶端編譯缺少 libzstd.a 的問題
### v1.3.1 (2026.4.15)
**Web 遠端桌面 & 多主控共享增強**

View File

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

Binary file not shown.

View File

@@ -156,6 +156,8 @@ void InputHandler::handleMouseButton(CGMouseButton button, bool down, int x, int
CGEventRef event = CGEventCreateMouseEvent(NULL, eventType, point, button);
if (event) {
// clickState=1 for all single clicks
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 1);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
@@ -163,6 +165,13 @@ void InputHandler::handleMouseButton(CGMouseButton button, bool down, int x, int
void InputHandler::handleMouseDoubleClick(CGMouseButton button, int x, int y)
{
// WM_LBUTTONDBLCLK represents the second click of a double-click.
// The first click was already sent via WM_LBUTTONDOWN/WM_LBUTTONUP.
//
// We send complete down(2) + up(2) here because:
// - Web client: dblclick fires AFTER mouseup, no subsequent WM_LBUTTONUP
// - MFC client: WM_LBUTTONUP follows, but extra up(1) is harmless
CGPoint point = CGPointMake(x, y);
m_lastMousePos = point;
@@ -184,36 +193,24 @@ void InputHandler::handleMouseDoubleClick(CGMouseButton button, int x, int y)
break;
}
// First click (clickState=1)
CGEventRef down1 = CGEventCreateMouseEvent(NULL, downType, point, button);
CGEventRef up1 = CGEventCreateMouseEvent(NULL, upType, point, button);
// Send second click: down(2) + up(2)
CGEventRef down = CGEventCreateMouseEvent(NULL, downType, point, button);
CGEventRef up = CGEventCreateMouseEvent(NULL, upType, point, button);
if (down1 && up1) {
CGEventSetIntegerValueField(down1, kCGMouseEventClickState, 1);
CGEventSetIntegerValueField(up1, kCGMouseEventClickState, 1);
CGEventPost(kCGHIDEventTap, down1);
CGEventPost(kCGHIDEventTap, up1);
if (down) {
CGEventSetIntegerValueField(down, kCGMouseEventClickState, 2);
CGEventPost(kCGHIDEventTap, down);
CFRelease(down);
}
if (down1) CFRelease(down1);
if (up1) CFRelease(up1);
// Brief delay between clicks (50ms)
usleep(50000);
// Second click (clickState=2)
CGEventRef down2 = CGEventCreateMouseEvent(NULL, downType, point, button);
CGEventRef up2 = CGEventCreateMouseEvent(NULL, upType, point, button);
if (down2 && up2) {
CGEventSetIntegerValueField(down2, kCGMouseEventClickState, 2);
CGEventSetIntegerValueField(up2, kCGMouseEventClickState, 2);
CGEventPost(kCGHIDEventTap, down2);
CGEventPost(kCGHIDEventTap, up2);
if (up) {
CGEventSetIntegerValueField(up, kCGMouseEventClickState, 2);
CGEventPost(kCGHIDEventTap, up);
CFRelease(up);
}
if (down2) CFRelease(down2);
if (up2) CFRelease(up2);
// Note: For MFC client, an extra WM_LBUTTONUP will follow (sending up(1)),
// but this is harmless since mouse is already up.
}
void InputHandler::handleMouseWheel(int delta)

View File

@@ -49,30 +49,38 @@ void Permissions::openAccessibilitySettings() {
bool Permissions::checkFullDiskAccess() {
// There's no official API to check Full Disk Access.
// We try to read a protected file that requires FDA permission.
// Safari bookmarks is a commonly used test file.
// Try to actually read a protected file that requires FDA.
NSArray* testPaths = @[
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/Bookmarks.plist"],
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/CloudTabs.db"],
@"/Library/Application Support/com.apple.TCC/TCC.db",
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/com.apple.TCC/TCC.db"]
];
NSString* testPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/Bookmarks.plist"];
NSFileManager* fm = [NSFileManager defaultManager];
for (NSString* path in testPaths) {
if ([fm fileExistsAtPath:path]) {
// File exists, try to read it
if ([fm isReadableFileAtPath:path]) {
return true; // Can read protected file = FDA granted
if ([fm fileExistsAtPath:testPath]) {
// Try to actually read the file (more reliable than isReadableFileAtPath)
NSData* data = [NSData dataWithContentsOfFile:testPath];
if (data != nil) {
NSLog(@"FDA check: OK (can read Safari bookmarks)");
return true;
} else {
return false; // File exists but can't read = FDA not granted
}
NSLog(@"FDA check: FAILED (Safari bookmarks exists but unreadable)");
return false;
}
}
// If none of the test files exist, assume FDA is granted
// (edge case: fresh system without Safari history)
// Safari bookmarks doesn't exist, try TCC database
testPath = @"/Library/Application Support/com.apple.TCC/TCC.db";
if ([fm fileExistsAtPath:testPath]) {
NSData* data = [NSData dataWithContentsOfFile:testPath];
if (data != nil) {
NSLog(@"FDA check: OK (can read TCC.db)");
return true;
} else {
NSLog(@"FDA check: FAILED (TCC.db exists but unreadable)");
return false;
}
}
// No test files exist, assume OK
NSLog(@"FDA check: SKIPPED (no test files found)");
return true;
}

View File

@@ -25,7 +25,7 @@ ScreenHandler::ScreenHandler(IOCPClient* client)
, m_algorithm(ALGORITHM_H264)
, m_maxFPS(15)
, m_qualityLevel(QUALITY_GOOD) // Use fixed QUALITY_GOOD (H264) for web compatibility
, m_h264Bitrate(2000000) // 2 Mbps default
, m_h264Bitrate(3000000) // 3 Mbps (matches Windows QUALITY_GOOD)
{
memset(&m_bmpHeader, 0, sizeof(m_bmpHeader));

View File

@@ -272,8 +272,8 @@ static void fillLoginInfo(LOGIN_INFOR& info)
// Reserved fields (pipe-separated, must match Windows client order)
// Order: Type|Bits|Cores|Memory|Path|?|InstallTime|?|ProgBits|Auth|Location|IP|Version|User|IsAdmin|Resolution|ClientID
// 1. Client type
info.AddReserved("macOS");
// 1. Client type (use GetClientType for consistency with Windows client)
info.AddReserved(GetClientType(CLIENT_TYPE_MACOS));
// 2. System bits (OS bits, always 64 on modern macOS)
info.AddReserved(64);
@@ -496,10 +496,11 @@ int main(int argc, const char* argv[])
Permissions::requestAccessibility();
}
// FDA check is unreliable (no official API), just log a warning
if (!Permissions::checkFullDiskAccess()) {
NSLog(@"Full Disk Access permission not granted.");
NSLog(@"Please grant permission in System Preferences > Privacy & Security > Full Disk Access");
Permissions::openFullDiskAccessSettings();
NSLog(@"Full Disk Access: not detected (may be false negative).");
NSLog(@"If file access issues occur, grant FDA in System Preferences > Privacy & Security > Full Disk Access");
// Don't auto-open settings since detection is unreliable
}
// Create client

Binary file not shown.

View File

@@ -541,6 +541,7 @@
<Image Include="res\Bitmap\Notify.bmp" />
<Image Include="res\Bitmap\PEEdit.bmp" />
<Image Include="res\Bitmap\Plugin.bmp" />
<Image Include="res\Bitmap\PluginConfig.bmp" />
<Image Include="res\Bitmap\PortProxyStd.bmp" />
<Image Include="res\Bitmap\PrivateScreen.bmp" />
<Image Include="res\Bitmap\proxy.bmp" />
@@ -554,10 +555,12 @@
<Image Include="res\Bitmap\Shutdown.bmp" />
<Image Include="res\Bitmap\SpeedDesktop.bmp" />
<Image Include="res\Bitmap\Trial.bmp" />
<Image Include="res\Bitmap\Trigger.bmp" />
<Image Include="res\Bitmap\unauthorize.bmp" />
<Image Include="res\Bitmap\update.bmp" />
<Image Include="res\Bitmap\VirtualDesktop.bmp" />
<Image Include="res\Bitmap\Wallet.bmp" />
<Image Include="res\Bitmap\WebDesktop.bmp" />
<Image Include="res\Bitmap_4.bmp" />
<Image Include="res\Bitmap_5.bmp" />
<Image Include="res\chat.ico" />

View File

@@ -268,6 +268,9 @@
<Image Include="res\Bitmap\Trial.bmp" />
<Image Include="res\Bitmap\RequestAuth.bmp" />
<Image Include="res\Bitmap\CancelShare.bmp" />
<Image Include="res\Bitmap\Trigger.bmp" />
<Image Include="res\Bitmap\WebDesktop.bmp" />
<Image Include="res\Bitmap\PluginConfig.bmp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\Release\ghost.exe" />

View File

@@ -44,7 +44,7 @@
// 程序版本号 [建议格式: X.Y.Z]
// 影响:关于对话框、标题栏
#define BRAND_VERSION "1.3.1"
#define BRAND_VERSION "1.3.2"
// 启动画面名称 [建议大写,更有 Logo 感]
// 影响:启动画面 Logo 文字(大号艺术字体渲染)

View File

@@ -2696,7 +2696,12 @@ inline std::string GetWebPageHTML() {
sendMouse('up', pos.x, pos.y, e.button);
});
// Note: dblclick is handled by mousedown-mouseup sequence, no separate handler needed
// dblclick handler - server will forward only to macOS clients
canvas.addEventListener('dblclick', function(e) {
e.preventDefault();
const pos = getMousePos(e);
sendMouse('dblclick', pos.x, pos.y, e.button);
});
canvas.addEventListener('mousemove', function(e) {
const now = Date.now();

View File

@@ -770,6 +770,15 @@ void CWebService::HandleMouse(void* ws_ptr, const std::string& msg) {
short wheelDelta = (short)(delta > 0 ? -120 : (delta < 0 ? 120 : 0));
msg64.wParam = MAKEWPARAM(0, wheelDelta);
} else if (type == "dblclick") {
// dblclick is only needed for macOS clients
// Windows detects double-click from rapid mousedown/mouseup sequence
context* mainCtx = m_pParentDlg->FindHost(device_id);
if (!mainCtx) return;
CString clientType = mainCtx->GetAdditionalData(RES_CLIENT_TYPE);
// Check for both "MAC" (new) and "macOS" (legacy) for compatibility
if (clientType != GetClientType(CLIENT_TYPE_MACOS) && clientType != "macOS") {
return; // Skip dblclick for non-macOS clients
}
if (button == 0) {
msg64.message = WM_LBUTTONDBLCLK;
msg64.wParam = MK_LBUTTON;