winserver2019/2016 RDS之应用层同显示驱动通信研究

本文地址:https://blog.csdn.net/MagicFMan/article/details/128347179 严禁转载

背景

做完了基于自定义协议的RDS共享桌面,接下来基于该底座做远程应用,远程应用需要监控窗口的位置等信息,传统模式是通过HOOK窗口消息,但是现在我们基于RDS开发了自己的显示驱动,不用RDP的那一套了,所以可以通过RDS的显示驱动来进行监控,在做窗口监控中遇到了一些问题,本文就讲下其中第一步的坑,应用程序如何同显示驱动通信。

RDS显示驱动框架

RDS其实有两种显示驱动框架,在winserver2022以前,winserver2012、winserver2016、winserver2019都是采用xddm的过时框架来实现的,在winserver2022开始使用新框架Indirect display driver来替代xddm框架。本文由于是基于winserver2016和winserver2019,所以框架依然是xddm。

应用程序同xddm通信

有过spice协议开发经验的应该知道,在win7上我们采用的是xddm框架的QXL驱动,应用程序可以使用ExEscape函数同驱动进行通信,所以我一开始也采用win7的方式进行,我们当前的显示驱动叫xDeskUdd,目前阻塞在应用层无法同xDeskUdd驱动通信,所以开始进行排查。

排查方式

由于资料有限,官网上甚至很少有RDS的详细介绍,关于XDDM在Remote display场景也只有寥寥数语,官网地址如下:
https://learn.microsoft.com/en-us/windows-hardware/drivers/display/remote-display-drivers
所以很难通过官方文档去找到解决方案,唯一的方式还是要从RDP协议入手来找到解决方案,由于我们的XDDM显示驱动(xDeskUdd)也是部分逆向RDP的显示驱动开发出来的,所以可以用xDeskUdd替换RDPUDD(RDP显示驱动的Display层驱动),然后使用RDP来连接,就可以看出RDP哪个进程里有同显示驱动通信,由于xDeskUdd驱动并未完整实现RDP显示驱动的所有功能,RDP协议连接后一段时间就会断开,这里我们不需要RDP能完整运行,只需要能走到应用程序发通知给显示驱动就可以了,我在xDeskUDD驱动里的DrvEscape中打印发送者的进程号进行初步分析,发现只有iEsc是0x12600的时候进程不是DWM.exe进程,其他都是DWM.exe进程发的,属于系统行为,没有参考意义,由于DrvEscape进入次数太多,不能简单的打断点,为了提升效率,于是打条件断点,过滤iEsc为0x12600的消息,本次我采用双机调试方式。

bp RDPUDD!DrvEscape ".if(dwo(esp+8)==0x12600){} .else{gc;}"

很快就断下来了,我们可以用!process命令查看当前是哪个进程
在这里插入图片描述
确认是rdpClip进程,从字面意思看,一直以为该进程只是作为剪贴板用的,之前没有做深入分析,没想到分辨率、dpi等信息都是在里面,看来后续还要重点研究下rdpClip进程。
由于双机调试,基本上都是加载的内核态符号表,所以此时需要显示加载用户态符号表,执行如下命令:

.reload /user

加载完后就能查看堆栈了,从应用层到内核层都有,应有尽有!很明确了,rdpClip是微软的程序,所以微软也提供了符号表,所以通过动静结合的调试方式,微软程序的分析还是很容易的。
在这里插入图片描述
从上面的堆栈其实也可以看出来,它也是用ExtEscape函数,那为什么我用不行,他用就可以呢,是使用了什么奇淫技巧吗?所以接下来要逆向看下rdpClip是如何调用ExtEscape,先看下SendToRDPUDD函数的实现逆向。
在这里插入图片描述
再看下SendToDisplayDriverEx函数,这是我们需要重点研究的函数。
在这里插入图片描述
和我使用的方式差不多,懒得一步步再逆向了,直接点,接下来给SendToDisplayDriverEx加个断点,更直观的看下实际使用的参数,由于是用户态,在双击调试的时候打用户态程序断点还是要有些经验的,如下:

.process /p /r a89b9040
.process /i a89b9040
bp rdpclip!SendToDisplayDriverEx        

断下来后,一步步单步,我需要看CreateDCW的参数到底是什么,所以单步跟踪到CreateDCW里面,然后再看堆栈:
在这里插入图片描述
堆栈给出了前面两个参数,我们可以查看前面两个参数是什么
在这里插入图片描述
我们还可以通过查看堆栈信息,查看后面两个参数是什么,如下,我标出来了,都是NULL
在这里插入图片描述
所以与mirror驱动sample的调用还是有区别的,以下是mirror sample的调用
在这里插入图片描述
接下来就知道怎么改了。
后续继续介绍怎么在RDS的显卡驱动里进行窗口跟踪,感兴趣的,欢迎关注。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宸汐软件

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

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

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

打赏作者

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

抵扣说明:

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

余额充值