winos低延迟屏幕优化方案

admin 2026-06-18 05:20:35 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细介绍了银狐远控低延迟屏幕优化方案的技术实现,对比分析了高速、差异和娱乐三种现有屏幕模式的特点,提出采用DXGI/GDI采集、H.264编码与GDI双缓冲渲染的混合架构,并阐述了协议设计、异常恢复机制及后续优化计划。 综合评分: 85 文章分类: 解决方案,应用安全,技术标准,安全工具


cover_image

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. 累计连续失败次数。
  2. 每隔约 1 秒发送 TOKEN_VIDEO_KEYFRAME_REQ
  3. 连续失败达到阈值后发送 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. 后续优化计划

由于工作比较忙,闲暇时间做点优化,接下来计划如下

  1. D3D11 渲染:将 BGRA 上传为 texture,替换 GDI StretchDIBits
  2. GPU 编码:探索 D3D11-aware Media Foundation 编码器,减少 CPU 拷贝。
  3. 动态 QoS:根据帧率、码率、发送失败和解码失败动态调整 fps/bitrate。
  4. 帧丢弃策略:控制端渲染落后时丢弃旧帧,只保留最新帧。
  5. 多显示器支持:扩展 displayId 和采集器选择逻辑。
  6. 输入控制:在授权场景下补充鼠标、键盘事件映射。
  7. 诊断面板:显示采集耗时、编码耗时、网络吞吐、解码耗时和渲染耗时。

源码获取

如果对银狐(winos)有兴趣,可以通过下面的方式获取全套源码:

关注后回复【winos】即可获取源码

推荐阅读

银狐远控问题排查与修复——Viusal Studio集成Google Address Sanitizer排查内存问题

银狐远控代码中差异屏幕bug修复

银狐远程屏幕内存优化方法探究

银狐远程软件bug修复记录 第03篇

银狐远程软件 UDP 断线无法重连的bug排查和修复

银狐远程软件代理映射功能优化思路分享

银狐远程软件去后门方法


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:CppGuide 安全研究员 安全研究员《winos低延迟屏幕优化方案》

评论:0   参与:  0