文章总结: 本文详细介绍了银狐远控低延迟屏幕优化方案的技术实现,对比分析了高速、差异和娱乐三种现有屏幕模式的特点,提出采用DXGI/GDI采集、H.264编码与GDI双缓冲渲染的混合架构,并阐述了协议设计、异常恢复机制及后续优化计划。 综合评分: 85 文章分类: 解决方案,应用安全,技术标准,安全工具
winos低延迟屏幕优化方案
原创
安全研究员 安全研究员
CppGuide
2026年6月16日 17:18 上海
在小说阅读器读本章
去阅读
特别申明:
本文内容仅限于用作技术交流,请勿使用本文介绍的技术做任何其他用途,否则后果自负,与本号无关。
1. 现状背景
银狐远控提供三种正常的屏幕模式,对比如下:
| 模块 | 核心方式 | 主控端 | 适合场景 | 主要代价 |
| — | — | — | — | — |
| 高速屏幕 | GDI 抓屏,提取变化矩形,编码为 JPEG 后再进行 zlib 压缩传输 | QuickScreenSpyDlg | 桌面变化较少,对画质和带宽有一定要求的场景 | JPEG 编解码存在一定 CPU 开销,实现复杂度中等 |
| 差异屏幕 | GDI 抓屏,计算原始像素差异块,仅传输变化区域,并进行 zlib 压缩 | DifScreenSpyDlg | 低色深、少量像素变化、追求实现简单的场景 | 大面积屏幕变化时,传输数据量显著增加,带宽压力较大 |
| 娱乐屏幕 | GDI 抓屏,BGRA 转换为 I420,采用 x264 编码生成 H.264 视频流 | H264ScreenSpyDlg | 连续视频播放、动画展示、高帧率远程桌面等场景 | 依赖组件较多,H.264 编码 CPU 开销较大,初始化与集成复杂度较高 |
高速屏幕
高速屏幕在 主插件/高速屏幕/高速屏幕/ScreenQuickManager.cpp:165 里发送首帧和后续帧,外层统一用 zlib。真正的关键在 主插件/高速屏幕/高速屏幕/ ScreenSpy.cpp:267:变化区域会被压成 JPEG,主控端再在 主控/Quick/QuickScreenSpyDlg.cpp:407 解 JPEG 后贴回对应矩形。
它的优势是带宽比较可控,尤其对 24/32 位彩色桌面更友好;还支持质量档位 60/85/100。缺点是每个变化矩形都走 JPEG,CPU 开销和内存分配会比较频繁。
差异屏幕
差异屏幕在 主插件/差异屏幕/差异屏幕/ScreenDifManager.cpp:152 也是首帧加后续帧、外层 zlib,但它不做 JPEG。核心差异算法在 主插件/差异屏幕/差异屏幕/ ScreenSpy.cpp:353:按 DWORD 比较旧帧和新帧,输出“偏移 + 长度 + 原始像素块”。主控端 主控/Quick/DifScreenSpyDlg.cpp:418 直接把这些块写回 DIB。
它实现更直接,支持更多色深档位,适合静态桌面、小范围变化。缺点是遇到视频、滚动、大面积刷新时,原始差异块可能迅速变大,压缩效果不如视频编码稳定。
娱乐屏幕
娱乐屏幕是完全不同的一套视频流架构。它在 主插件/娱乐屏幕/娱乐屏幕/H264ScreenManager.cpp:82 内存加载 x264,采集线程在 主插件/娱乐屏幕/娱乐屏幕/ H264ScreenManager.cpp:357 抓 BGRA,再用 libyuv 转 I420,编码线程在 主插件/娱乐屏幕/娱乐屏幕/H264ScreenManager.cpp:460 生成 H.264,输出线程发送 TOKEN_H264SCREEN。主控端 主控/Quick/H264ScreenSpyDlg.cpp:311 用解码器和 SDL 渲染。
它更像“实时视频播放”,对连续画面变化更合适;但依赖最重,包含大体积 x264 内嵌头文件、MemoryModule、libyuv、SDL/解码器相关逻辑,维护成本最高。
结论
如果目标是普通远程桌面交互:高速屏幕更均衡。 如果目标是低带宽、低色深、静态界面:差异屏幕更轻。 如果目标是连续动画/视频类画面:娱乐屏幕更合适,但复杂度和 CPU 成本最高。
可以看到不管是哪种屏幕,屏幕采集和渲染都是走的GDI,在Windows 8 系统只有有更好的方案。
2. 目标与定位
低延迟屏幕是新增的远程屏幕类型,目标是在授权远程协助、自有设备管理和内部运维场景下,降低屏幕查看延迟、减少网络带宽占用,并保留 BGRA 原始帧作为稳定回退链路。
现阶段实现采用“DXGI/GDI 采集 + BGRA/H.264 编码 + 控制端解码 + GDI 双缓冲渲染”的 MVP 架构。后续可继续升级为 D3D11 纹理渲染和 GPU 直通编码,进一步降低 CPU 拷贝和窗口缩放损耗。
3. 总体架构
被控端插件
DXGI Desktop Duplication / GDI 采集
-> CapturedFrame(BGRA)
-> Raw BGRA 或 Media Foundation H.264 编码
-> 低延迟屏幕协议包
-> 网络发送
控制端 Quick
接收低延迟协议包
-> BGRA 直接使用 / H.264 解码成 BGRA
-> 运行状态统计
-> GDI 双缓冲等比例渲染
核心原则:
- 优先使用 H.264 降低带宽,失败时自动回退 BGRA。
- 采集、编码、协议、解码、渲染分层,便于替换单个环节。
- 关键路径必须有日志,方便定位采集失败、编码失败、解码失败、网络短包和渲染异常。
4. 被控端实现
5.1 插件入口
插件工程位于:
主插件/低延迟屏幕/低延迟屏幕/
主要文件:
低延迟屏幕.cpp:插件导出入口,创建低延迟屏幕 Manager。LowLatencyScreenManager.h/.cpp:管理采集线程、配置协商、编码器选择和帧发送。LowLatencyProtocol.h:定义 token、codec、caps、config、frame header。
4.2 采集链路
采集接口为 IScreenCapturer,当前实现包括:
DxgiCapturer:优先路径,使用 DXGI Desktop Duplication 抓取桌面 BGRA。GdiCapturer:兼容回退路径,DXGI 初始化失败时使用 GDI 抓屏。
流程:
InitializePipeline()
-> 尝试 CDxgiCapturer::Initialize()
-> 失败后尝试 CGdiCapturer::Initialize()
-> Capture() 输出 CapturedFrame
CapturedFrame 包含宽、高、stride、pts 和 BGRA 像素数据。首帧决定实际分辨率,并触发配置包回传。
4.3 编码链路
编码接口为 IVideoEncoder,当前实现包括:
RawBgraEncoder:不压缩,直接发送 BGRA,作为调试和回退链路。MfH264Encoder:使用 Media Foundation H.264 MFT 编码。
H.264 编码流程:
BGRA frame
-> MFVideoFormat_RGB32 输入 sample
-> H.264 encoder MFT
-> ProcessOutput
-> EncodedFrame(codec=VIDEO_CODEC_H264)
编码器选择策略:
- 控制端请求
VIDEO_CODEC_H264时优先创建CMfH264Encoder。 - H.264 初始化失败时自动切换
CRawBgraEncoder。 - 配置包回传实际 codec,控制端以实际 codec 处理帧。
5. 控制端实现
控制端主要文件位于:
主控/Quick/
关键文件:
LowLatencyScreenSpyDlg.h/.cpp:低延迟屏幕窗口、协议处理、状态统计和渲染。LowLatencyH264Decoder.h/.cpp:Media Foundation H.264 解码器。LowLatencyScreenProtocol.h:控制端协议定义,必须和插件端二进制布局保持一致。
5.1 配置协商
窗口创建后优先发送 H.264 配置:
OnInitDialog()
-> SendConfig(VIDEO_CODEC_H264)
这样可以避免能力包早于窗口创建到达导致协商丢失。如果 H.264 不可用,插件端或控制端会回退 BGRA。
5.2 解码流程
BGRA 帧:
VideoFrameHeader(codec=BGRA)
-> 校验 payload/stride/尺寸
-> 拷贝为紧凑 BGRA
-> 渲染
H.264 帧:
VideoFrameHeader(codec=H264)
-> CLowLatencyH264Decoder::Decode()
-> 输出 BGRA
-> 渲染
解码器直接创建系统 H.264 Decoder MFT,避免全局修改 Quick 工程较老的 _WIN32_WINNT 目标版本。
5.3 渲染策略
当前渲染为 GDI 双缓冲:
OnPaint()
-> 内存 DC
-> 黑底清屏
-> 按远端画面比例计算居中目标矩形
-> HALFTONE StretchDIBits
-> BitBlt 到窗口
这样解决三类问题:
- 避免默认背景擦除造成白闪/黑闪。
- 避免窗口比例和远端桌面比例不一致时拉伸变形。
- 保持现有 MFC/GDI 窗口兼容性。
6. 协议设计
低延迟屏幕使用独立高位 token,避免和主协议冲突:
TOKEN_VIDEO_CAPS = 220
TOKEN_VIDEO_CONFIG = 221
TOKEN_VIDEO_FRAME = 222
TOKEN_VIDEO_KEYFRAME_REQ = 223
TOKEN_VIDEO_CONTROL = 224
TOKEN_VIDEO_CLOSE = 225
TOKEN_VIDEO_ERROR = 226
codec 定义为位掩码:
VIDEO_CODEC_BGRA = 1
VIDEO_CODEC_H264 = 2
VIDEO_CODEC_H265 = 4
包结构:
VideoCapsPacket:能力声明,包括支持 codec 和最大 fps。VideoConfigPacket:配置请求或实际配置回传,包括 codec、宽高、fps、码率。VideoFrameHeader:帧头,包括 codec、flags、displayId、宽高、stride、pts、payloadSize。
所有协议结构体使用 #pragma pack(push, 1),控制端和插件端必须保持字段顺序、字段大小和 LOW_LATENCY_MAGIC 一致。
7. 异常恢复与回退
7.1 采集回退
DXGI 初始化失败
-> GDI 采集
-> 仍失败则发送 TOKEN_VIDEO_ERROR
7.2 编码回退
H.264 编码器初始化失败
-> Raw BGRA
-> 配置包回传 codec=BGRA
7.3 解码恢复
控制端 H.264 解码失败时:
- 累计连续失败次数。
- 每隔约 1 秒发送
TOKEN_VIDEO_KEYFRAME_REQ。 - 连续失败达到阈值后发送
SendConfig(VIDEO_CODEC_BGRA),主动回退。
7.4 渲染保护
控制端会丢弃异常帧:
- 宽高为 0。
- 宽高超过上限。
payloadSize大于实际包长度。- BGRA
stride * height溢出。 - 单帧 BGRA 缓冲超过合理上限。
8. 运行状态与日志
控制端窗口标题显示:
低延迟屏幕 - 1536x864 H.264 30 fps 4000 kbps 失败:0
统计项包括:
- 当前 codec。
- 远端分辨率。
- 本地渲染 fps。
- 输入码流 kbps。
- 连续解码失败次数。
关键日志路径:
- Manager 启动/停止。
- DXGI/GDI 选择和失败。
- 配置协商。
- 编码器初始化和回退。
- 帧发送失败。
- H.264 解码失败。
- 关键帧请求。
- BGRA 回退。
9. 构建与验证
插件建议验证:
msbuild "主插件\低延迟屏幕\低延迟屏幕.sln" /p:Configuration=Debug /p:Platform=Win32
msbuild "主插件\低延迟屏幕\低延迟屏幕.sln" /p:Configuration=Release /p:Platform=Win32
msbuild "主插件\低延迟屏幕\低延迟屏幕.sln" /p:Configuration=Debug /p:Platform=x64
msbuild "主插件\低延迟屏幕\低延迟屏幕.sln" /p:Configuration=Release /p:Platform=x64
控制端 Quick.vcxproj 当前只要求 x86:
msbuild "主控\Quick\Quick.vcxproj" /p:Configuration=Debug /p:Platform=Win32
msbuild "主控\Quick\Quick.vcxproj" /p:Configuration=Release /p:Platform=Win32
如果 output/Quick.exe 正在运行,Debug 链接可能无法覆盖输出文件。验证时可使用临时 TargetName:
msbuild "主控\Quick\Quick.vcxproj" /p:Configuration=Release /p:Platform=Win32 /p:TargetName=Quick_lowlatency_verify
10. 已知限制
- 当前渲染仍是 GDI 双缓冲,非 GPU texture 渲染。
- H.264 编码输入仍有 BGRA 拷贝,尚未做到 DXGI texture 到编码器的零拷贝。
- 控制端窗口如果显示在被采集桌面内,会出现递归画中画,这是远程屏幕类功能的正常现象。
- H.264 MFT 在不同 Windows 版本和显卡驱动下行为可能不同,需要实机验证 SPS/PPS、关键帧和输出格式兼容性。
- x64 版
Quick.vcxproj存在旧模块字符集、SDL 和 ToolkitPro 依赖问题,当前不作为低延迟屏幕交付目标。
11. 后续优化计划
由于工作比较忙,闲暇时间做点优化,接下来计划如下
- D3D11 渲染:将 BGRA 上传为 texture,替换 GDI
StretchDIBits。 - GPU 编码:探索 D3D11-aware Media Foundation 编码器,减少 CPU 拷贝。
- 动态 QoS:根据帧率、码率、发送失败和解码失败动态调整 fps/bitrate。
- 帧丢弃策略:控制端渲染落后时丢弃旧帧,只保留最新帧。
- 多显示器支持:扩展
displayId和采集器选择逻辑。 - 输入控制:在授权场景下补充鼠标、键盘事件映射。
- 诊断面板:显示采集耗时、编码耗时、网络吞吐、解码耗时和渲染耗时。
源码获取
如果对银狐(winos)有兴趣,可以通过下面的方式获取全套源码:
关注后回复【winos】即可获取源码
推荐阅读
银狐远控问题排查与修复——Viusal Studio集成Google Address Sanitizer排查内存问题
银狐远控代码中差异屏幕bug修复
银狐远程屏幕内存优化方法探究
银狐远程软件bug修复记录 第03篇
银狐远程软件 UDP 断线无法重连的bug排查和修复
银狐远程软件代理映射功能优化思路分享
银狐远程软件去后门方法
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:CppGuide 安全研究员 安全研究员《winos低延迟屏幕优化方案》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。







评论