# V2 文件/文本传输功能清单 ## 一、文件传输 | 方向 | 触发方式 | 断点续传 | 进度显示 | 备注 | |------|----------|:--------:|:--------:|------| | 服务端 → 客户端 | 文件管理器拖放/Ctrl+V | ✅ | ✅ | 支持大文件(>4GB) | | 客户端 → 服务端 | 文件管理器下载 | ✅ | ✅ | 支持大文件(>4GB) | | 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | ✅ | ✅ | 自动捕获目标目录 | ## 二、文本传输 | 方向 | 触发方式 | 说明 | |------|----------|------| | 服务端 → 客户端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_SET_CLIPBOARD` | | 客户端 → 服务端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_GET_CLIPBOARD` | | 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | 自动粘贴 | ## 三、C2C 传输流程 ``` ┌─────────────┐ Ctrl+V ┌─────────────┐ CLIPBOARD_V2 ┌─────────────┐ │ 远程桌面B │ ───────────────>│ 服务端 │ ──────────────────>│ 远程桌面A │ │ (目标) │ │ │ │ (源) │ └─────────────┘ └─────────────┘ └─────────────┘ ▲ │ │ │ │ C2C_PREPARE │ │<──────────────────────────────┘ │ │ │ │ ┌─────────────┐ │ │ SEND_FILE_V2/C2C_TEXT │ 服务端 │ SEND_FILE_V2/C2C_TEXT │ │<────────────────────────│ (转发) │<──────────────────────────┘ │ └─────────────┘ ``` ## 四、协议命令 | 命令 | 值 | 用途 | |------|:--:|------| | `COMMAND_SEND_FILE_V2` | 85 | V2文件数据包 | | `COMMAND_FILE_RESUME` | 86 | 断点续传响应 | | `COMMAND_CLIPBOARD_V2` | 87 | C2C剪贴板请求 | | `COMMAND_FILE_QUERY_RESUME` | 88 | 断点续传查询 | | `COMMAND_C2C_PREPARE` | 89 | C2C准备接收通知 | | `COMMAND_C2C_TEXT` | 90 | C2C文本传输 | | `COMMAND_FILE_COMPLETE_V2` | 91 | V2文件完成校验包 | | `COMMAND_C2C_PREPARE_RESP` | 92 | C2C准备响应(返回目标目录) | ## 五、核心特性 - **断点续传**: 基于 transferID + 文件特征匹配,支持传输中断后恢复 - **大文件支持**: 使用 uint64_t 存储文件大小和偏移,突破4GB限制 - **自动目标目录**: C2C传输自动捕获目标客户端当前焦点窗口的目录 - **自动粘贴**: C2C文本传输完成后自动模拟 Ctrl+V 完成粘贴 - **版本协商**: 能力位 `CLIENT_CAP_V2` + 版本日期双重检测 - **文件完整性校验**: 传输完成后发送 SHA-256 校验包,接收端自动验证 - **服务端开关**: 参数菜单可控制是否启用 V2(默认关闭) - **自动清理**: 状态文件超过 7 天自动删除 ## 5.1 文件完整性校验 每个文件传输完成后,发送端计算并发送 `COMMAND_FILE_COMPLETE_V2` 校验包: ```cpp struct FileCompletePacketV2 { uint8_t cmd; // = 91 uint64_t transferID; uint64_t srcClientID; uint64_t dstClientID; uint32_t fileIndex; uint64_t fileSize; uint8_t sha256[32]; // SHA-256 哈希 }; // 69 bytes ``` **工作流程**: 1. 发送端在发送文件数据同时计算 SHA-256 2. 文件最后一个块发送完成后,发送 `FILE_COMPLETE_V2` 校验包 3. 接收端在接收数据时同步计算 SHA-256(流式计算,无需重读文件) 4. 收到校验包后对比哈希值,输出校验结果 **支持的传输方向**: | 方向 | 校验位置 | |------|----------| | 客户端 → 服务端 | 服务端校验 | | 服务端 → 客户端 | 客户端校验 | | 客户端A → 客户端B (C2C) | 服务端转发,客户端B校验 | **校验失败处理**: - 校验失败时自动删除损坏文件 - 日志输出期望和实际的 SHA-256 哈希值 **断点续传与校验**: - 断点续传时无法使用流式 SHA-256(缺少历史数据) - 自动切换为从文件重新计算完整 SHA-256 ## 六、相关文件 | 文件 | 说明 | |------|------| | `common/commands.h` | 协议命令定义 | | `common/file_upload.h/cpp` | V2传输核心实现 | | `client/KernelManager.cpp` | 客户端主连接处理 | | `client/ScreenManager.cpp` | 客户端远程桌面会话处理 | | `server/2015Remote/2015RemoteDlg.cpp` | 服务端主逻辑 | | `server/2015Remote/ScreenSpyDlg.cpp` | 服务端远程桌面会话处理 | | `server/2015Remote/CDlgFileSend.cpp` | 文件传输进度对话框 | ## 七、使用说明 ### C2C 文件传输 1. 打开两个远程桌面窗口(源A和目标B) 2. 在源A上选中文件,按 Ctrl+C 3. 按 X 切换到目标B 4. 按 Ctrl+V,文件自动传输到B当前目录 ### C2C 文本传输 1. 在源A上复制文本(Ctrl+C) 2. 按 X 切换到目标B 3. 在目标B的应用中按 Ctrl+V,文本自动粘贴 ### 断点续传 - 传输中断后,重新执行相同操作 - 系统自动检测已传输部分,从断点继续 - 状态文件保存在 `%TEMP%\FileTransfer\` - 状态文件超过 7 天自动删除 ### 状态文件说明 | 后缀 | 用途 | 说明 | |------|------|------| | `.resume` | 断点续传状态 | 记录 transferID、文件列表、已接收字节数 | | `.recv` | C2C 接收方目录 | 记录目标客户端当前焦点窗口目录 | | `.send` | C2C 发送方目录 | 记录源客户端剪贴板文件路径 | 所有状态文件统一存放在 `%TEMP%\FileTransfer\` 目录,文件名格式为 `{transferID}.{后缀}`。 --- ## 八、代码审查报告 ### 8.1 审查范围 | 文件 | 改动行数 | 审查结果 | |------|:--------:|:--------:| | `common/commands.h` | +16 | ✅ | | `common/file_upload.h` | +288 | ✅ | | `SimplePlugins/file_upload.cpp` | 核心实现 | ✅ | | `client/KernelManager.cpp` | +294 | ✅ | | `client/ScreenManager.cpp` | +360 | ✅ | | `server/2015Remote/2015RemoteDlg.cpp` | +698 | ✅ | | `server/2015Remote/CDlgFileSend.cpp` | +116 | ✅ | | `server/2015Remote/context.h` | +34 | ✅ | ### 8.2 代码质量评估 #### 优点 1. **协议设计清晰** - 结构体使用 `#pragma pack(push, 1)` 确保跨平台对齐,注释详尽 2. **版本兼容性** - V1/V2 协议共存,旧客户端仍可使用 3. **能力协商机制完善** - `CLIENT_CAP_V2` 能力位 + 版本日期双重检测 4. **断点续传设计** - `transferID + fileIndex` 组合键唯一标识,状态持久化 5. **线程安全** - 使用 `std::mutex` 保护共享状态(`g_fileStatesV2Mtx` 等) 6. **智能指针** - `std::unique_ptr` 管理内存,RAII 处理文件句柄 7. **SHA-256 校验** - 使用 Windows bcrypt API,流式计算 #### 待改进项 | 优先级 | 问题 | 位置 | 建议 | |:------:|------|------|------| | 🟠 中 | 路径穿越未验证 | `file_upload.cpp:712` | `GetRelativePath` 添加 `..` 检查 | | 🟠 中 | 变量命名误导 | `file_upload.cpp:2463` | `utf8Name` 实际是 ANSI,应改名 | | 🟡 低 | 重复代码 | `KernelManager.cpp` / `ScreenManager.cpp` | C2C_TEXT 处理逻辑可提取公共函数 | ### 8.3 安全审查 | 检查项 | 状态 | 说明 | |--------|:----:|------| | 缓冲区溢出 | ✅ | 有长度校验 `if (len < sizeof(...) + nameLength + dataLength)` | | 认证校验 | ✅ | 使用 hash + hmac 验证 | | 路径穿越 | ⚠️ | `GetRelativePath` 未检查 `..` 序列(实际风险低) | | 客户端ID伪造 | ✅ | 通过 `FindHost` 验证客户端存在 | | 文件句柄泄漏 | ✅ | RAII 析构函数处理 | | 整数溢出 | ✅ | 使用 `uint64_t` 支持大文件 | **路径穿越风险分析**: - `GetRelativePath` 未过滤 `..` 序列 - 实际风险较低:C2C 由服务端键盘钩子触发,非任意用户输入 - 建议后续版本加固 ### 8.4 边界条件测试建议 | 场景 | 测试点 | |------|--------| | 大文件 | >4GB 文件传输和断点续传 | | 网络抖动 | 传输中断后恢复 | | 并发传输 | 多个 C2C 同时进行 | | 客户端重启 | `.resume` 文件恢复 + SHA-256 重算 | | 目录结构 | 深层嵌套目录创建 | | 空文件 | 0 字节文件传输和校验 | --- ## 九、提交评估 ### 9.1 总体评估:✅ 可发布 | 指标 | 状态 | 说明 | |------|:----:|------| | 功能完整性 | ✅ | C2C/断点续传/SHA-256 校验均已实现 | | 编译通过 | ✅ | 无编译错误 | | 向后兼容 | ✅ | V1 协议仍可用,能力协商正确 | | 崩溃风险 | ✅ | 无明显崩溃点 | | 数据安全 | ✅ | HMAC 认证、长度校验完善 | ### 9.2 问题分类 | 严重程度 | 数量 | 是否阻塞提交 | |:--------:|:----:|:------------:| | 🔴 致命 | 0 | - | | 🟠 中等 | 2 | 否 | | 🟡 低危 | 1 | 否 | ### 9.3 后续改进建议 1. **路径安全加固** - 在 `GetRelativePath` 添加 `..` 过滤 2. **重复代码重构** - 提取 C2C_TEXT 处理为公共函数 3. **变量命名修正** - `utf8Name` → `ansiName` 4. **日志级别控制** - 添加 verbose 模式开关 --- *审查日期: 2026-02-27*