winserver2019/2016 RDS基于自定义协议Dpi同步研究

背景

做完了winserver 2022的RDS,让我们的远程协议也能像RDP一样对winserver进行连接了,对于新版的windows server来说,RDS采用的显卡驱动变成了Indirect display driver,这让开发工作量简化了很多,但windowsserver 2022毕竟是比较新的系统,市场上的普及还不是很到位,客户现在用的大部分都是windows server 2016和windows server 2019,可惜的是windows server 2019不支持Indirect display driver模型的远程桌面显卡驱动,而是使用老旧的xddm驱动的显卡框架,本文在基于这种xddm框架的显卡驱动基础上,解决在实现过程中遇到的一个问题。

前期工作量

前面已经完成了对RDP xddm模型的remote display driver的初步逆向,实现了基本的显示功能,如画面显示和采集、分辨率设置(包含自定义分辨率)、双屏等功能,这些功能暂时不做介绍,后续有机会再详细介绍这些功能的实现。

DPI同步

随着现在2K、4K分辨率的普及,现在DPI的需求还是很普遍的,所以我们的RDS远程桌面也需要实现对DPI的同步,即虚机内的DPI要与客户端的一致。

普通DPI同步方式

对物理机而言,DPI设置其实有很多种方式,例如github上的这个项目就介绍了DPI的获取和设置。
https://github.com/lihas/windows-DPI-scaling-sample
将该项目编译放到远程桌面(remote session),发现无法有效的获取和设置。
(https://note.youdao.com/yws/res/17441/WEBRESOURCEc96552b4e5f7ce9a2a5dc7d304b559db)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0z3JEDvj-1669345365488)(https://note.youdao.com/yws/res/17442/WEBRESOURCE145605efe32fc35f277d9cafcdb504a3)]

看来远程Session的桌面通过常见的一些DPI设置函数是行不通的,所以需要研究其他方式。

远程session dpi同步研究——动态和静态分析RDP

静态IDA分析

将RDP的RDPUDD.dll用IDA工具来分析,其实关于显示配置,我们只需要重点关注两个接口就好了:DrvEnablePDEV、DrvGetModes。我们先来看下DrvGetModes函数,经过一系列的结构体调整,可以看到:

其实最终是填充显示器的分辨率信息,我们通过上图可以看到dmFields是0x7C00A0,其实就是DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS。通过前面的逆向代码可知,并没有包含任何关于DPI的信息。

我们接着来看下DrvEnablePDEV函数,该函数主要做一些初始化操作,重点在于GDIINFO的结构体填充,其中有包括色彩之类的,我们需要看下里面有没有DPI的一些信息。
在这里插入图片描述
该函数的GDIINFO填充在DDInitializeModeFields里面,我们再来看下:
在这里插入图片描述
我仔细的对照了下文档,有可能的地方在于我标的几个地方:
pGdiInfo->ulHorzSize
pGdiInfo->ulVertSize
pGdiInfo->ulLogPixelsX
pGdiInfo->ulLogPixelsY
根据跟踪分析除了ulLogPixelsX,其他几个变量都是其他程序传进来的数赋值上去,具体表示什么不得而知,是否与DPI有关,这下要动态调试了。
我们先设置vmware的双机调试环境,我使用的虚机系统是win10 1809 32位。
我们先挂断点:bp RDPUDD!DrvEnablePDEV
在这里插入图片描述
主要是想看下DrvEnablePDEV执行完后参数pGdiInfo填了什么数据,该参数是函数的第6个参数,所以是esp+0x18。
我们使用mstsc进行远程连接,此时函数断下来了。
在这里插入图片描述
我们接着执行:dd esp+0x18;gu
目的是打出pGdiInfo的地址,并继续执行直到函数返回,然后又会断下来:
在这里插入图片描述
这时候我们可以看下pGdiInfo里面的数据了:
在这里插入图片描述
我们关注的几个数据:
pGdiInfo->ulHorzSize = 0x20f
pGdiInfo->ulVertSize = 0x128
pGdiInfo->ulLogPixelsX = 0x60
pGdiInfo->ulLogPixelsY = 0x640064

我们再把客户端DPI调整到125%,再来看下这几个值:
在这里插入图片描述
pGdiInfo->ulHorzSize = 0x20f
pGdiInfo->ulVertSize = 0x128
pGdiInfo->ulLogPixelsX = 0x60
pGdiInfo->ulLogPixelsY = 0x7d0064
我们发现除了pGdiInfo->ulLogPixelsY,其他的都没变,pGdiInfo->ulLogPixelsY的高位发生了变化,我们来看下高位的10进制:0x64=100,0x7d=125,正好是我们两次的缩放比,我们再来设置成150%来看下。
在这里插入图片描述
pGdiInfo->ulHorzSize = 0x20f
pGdiInfo->ulVertSize = 0x128
pGdiInfo->ulLogPixelsX = 0x60
pGdiInfo->ulLogPixelsY = 0x96008C
0x96=150
所以到这里基本可以确定了,通过传递dpi的值到pGdiInfo->ulLogPixelsY的高16位,低16位其实也有变化,但是是什么意义还是不得而知,先不管,统一设置成0x64再做测试。
通过修改代码,发现使用我们的协议也能正常设置DPI了,pGdiInfo->ulLogPixelsY的低16位一直设置0x60,其实也没什么影响。
再来看下GDIINFO的官方文档说明,其实什么都没说。
在这里插入图片描述

如果按照文档来,我估计我几个月都没法做出DPI同步功能了。

总结

windows做到一定程度,光靠msdn那点文档其实是远远不够的,需要通过各种手段去深入剖析,最终才能达到我们的目的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宸汐软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值