Windows RDP协议 Fuzzing 漏洞挖掘研究

本文详细介绍了作者在Fuzzing Windows RDP客户端和服务端时的尝试和挑战,包括对RDP协议的理解、Fuzzing过程中遇到的问题及解决方法,以及在Fuzzing过程中发现的漏洞分析。作者分享了Fuzzing技术细节,如客户端-服务端架构、Fuzzing的挑战以及多输入Fuzzing,并展示了如何克服这些问题以实现有效的Fuzzing设置。通过对RDP服务端和客户端的Fuzzing,作者揭示了协议的脆弱性,尽管尚未发现RCE漏洞,但确实找到了一些bug,进一步加深了对RDP协议的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本介绍

本文描述了我在Fuzzing Windows RDP 客户端和服务端方面所做的一些尝试和挑战,以及Crsahs分析。

Microsoft 的远程桌面协议 (RDP) 持续受到安全社区的关注。从 2019 年发现的几个可能危及数百万面向互联网的服务端的关键漏洞,到RDP 被攻击者用作主要的初始访问向量之一。

我对这个目标最初的兴趣是与 VM 相关的。因为连接到 Azure Windows 机器或 Hyper-V 虚拟机的默认方式是 RDP,所以我认为 RDP 是比较重要的目标。

我很快就发现了 Park、Jang、Kim 和 Lee在 BlackHat Europe 2019 上发表的关于 RDP Fuzzing的精彩分享。演讲者在短短几个小时内使用一个并不高效的 fuzzer 发现了几个漏洞,因此我决定在他们的工作基础上进行构建新的挖掘工具,将 fuzzing 能力扩展到其他方面,改进其性能并挖掘到我自己的 RDP 远程代码执行 (RCE)漏洞。

不幸的是,并不是所有的Fuzzing工具都能挖到严重的漏洞。我目前还没有挖到 RDP 的RCE漏洞,但我确实设法找到了一些bugs,并更好地了解了协议、其组件以及Fuzzing过程和工具。我开发的Fuzzing框架足够通用,有助于对其他目标进行Fuzzing。

在这篇文章中,我将分享我执行上述所有操作的过程。首先,我将概述 RDP 和开发的Fuzzing设置,然后将分享我临的挑战以及如何处理的方法,最后,我将回顾在此过程中发现的几个漏洞。

1.RDP 协议

远程桌面协议是用于远程访问 Windows 计算机的通用协议,Malwaretech 最近将其述为“协议的协议”。RDP 允许在每个连接中运行多个通道,并且每个通道都有不同的用途。这意味着每个通道都有自己的代码来处理其数据、自己的结构定义和数据流。这实质上意味着 RDP 中确实存在多种协议。
在这里插入图片描述
RDP 连接中的通道

RDP 通道可以是静态的,也可以是动态的,但对于我们的目的而言,两者之间的区别并不重要。如果你想了解更多关于RDP连接的内部运作原理,我建议你阅读下文。

2.RDP Fuzz的挑战

在“标准”Fuzzing场景中,有一个程序读取由Fuzzer控制的输入,输入可以是文件或任何类型的数据流。然后程序处理数据,同时Fuzzer监视生成的数据的代码覆盖率。基于该覆盖范围,Fuzzer对输入进行变异,再次将变异的输入发送到程序,然后重复该过程。

RDP Fuzzing是不同的,因为我必须始终有一个 RDP 连接处于活动状态。Fuzzer可以输入到程序中的数据需要作为协议数据单元 (PDU) 发送到特定通道(在Fuzzing期间也应处于活动状态)的顶部,并在开放连接中进行。如前所述,每个通道都有自己的协议,因此需要逐个通道进行Fuzzing。这给Fuzzing过程带来了以下挑战(这也可能适用于其他协议/网络相关的Fuzzing):

客户端-服务端架构——在传统的Fuzzing中,Fuzzer可以简单地运行目标应用程序并提供其输入。在客户端-服务端场景中,目标应用程序在连接的一侧运行,而输入从另一侧发送。在RDP的情况下,双方通常在不同的机器上。

状态性- RDP 是一种有状态协议,这意味着你必须在对测试用例进行Fuzzing时考虑连接的状态。这会严重影响Fuzzing的稳定性。

多输入Fuzzing——当对接受文件作为输入的目标进行Fuzzing(文件格式Fuzzing)时,Fuzzer对目标的所有输入都包含在单个文件中。相反,当你对协议进行Fuzzing时,你可能需要发送一些连续的消息才能到达有效的代码路径。

寻找目标代码——当你使用覆盖率引导的Fuzzing时,你通常需要向Fuzzer表明它需要在什么时候开始监控代码覆盖率(即,处理你输入的目标函数是什么?)。RDP 有许多负责其操作的组件,在某些情况下,找到正确的位置可能是一项艰巨的任务。

这四个挑战是我预计Fuzzing RDP的主要挑战。在文中,我将讨论如何克服这些挑战,以及在工作后期出现的其他挑战。

Fuzzing技术细节

在本节中,我将介绍技术细节,以及在工作过程中遇到的挑战。还将解释如何解决它们以实现有效的Fuzzing设置。我在 GitHub 上创建了一个工作存储库,其中包含我在此工作中编写的所有代码。

1.客户端-服务端架构

在这个工作中,我想要Fuzzing Windows 的 RDP 服务端及其 RDP 客户端。对 RDP 服务端进行Fuzzing的动机很明显:攻击者可以使用它来远程入侵 Windows 服务端并获得对其的访问权限。对 RDP 客户端进行Fuzzing的动机是不同的,如果攻击者已经获取了 RDP 服务端权限的场景,然后等待受害 RDP 客户端连接过来。一旦受害者连接上,攻击者也可以通过 RDP 客户端获取受害者的机器权限。当管理员连接到他们管理的服务端时可能会发生这种情况,由于 Hyper-V 利用 RDP 访问其虚拟机,甚至可以用作 VM 逃逸。

RDP 的 fuzzer 需要具有以下基本组件:

◼检测引擎跟踪代码覆盖并检测崩溃

◼变异引擎产生新输入

◼输入馈送器通过适当的目标通道发送fuzzer的测试用例

◼目标二进制文件状态由检测引擎跟踪

客户端和服务端的Fuzzing配置不同,但也有一些相似之处。
在这里插入图片描述
基本Fuzzing配置

在目标方面,有以下内容:

◼Fuzzer – 定制的 afl-fuzz.exe

◼检测引擎——定制的 winafl.dll,使用定制的 DynamoRIO 和in_app检测模式

◼输入 ——被写入目标和输入发送者共享目录中的中间文件的变异 PDU

在输入发送方,有一个组件:

◼代理——读取中间文件并在目标通道上发送输入

将输入的生成与向目标的传输分离,允许输入在被目标处理之前从 RDP 连接的一侧移动到另一侧。此外,我使用 WinAFL 的应用内检测模式来不中断正常的执行流程。

为了使覆盖引导的Fuzzing工作,输入和它们触发的代码路径之间必须存在一一对应的关系。为了实现这一点,我开发了“background fuzzing”,它将Fuzzer PDU 与常规 PDU 区分开来,并且只跟踪前者的代码路径。这是必不可少的,因为我只希望Fuzzer跟踪我自己测试用例的覆盖范围,而不是通过连接发送的随机 PDU。

为了说明这一点,让我看看在Fuzzing将音频从 RDP 服务端重定向到客户端的RDPSND虚拟通道时,类似的事情会是什么样子。根据官方文档,每个 PDU 的第一个字节表示发送的消息类型。
在这里插入图片描述
资料来源:[ MS-RDPEA ]

msgType字段支持的值为0x01到0x0D。在这种情况下,可以通过以下方式使用第一个字节的最高有效位作为fuzz标记:

◼在发送 PDU 之前,代理会转换第一个字节的最高有效位。

◼WinAFL 在处理消息之前检查第一个字节的最高有效位。如果该位打开,WinAFL 将关闭该位并跟踪此消息的代码覆盖率。如果该位关闭,WinAFL 将忽略该消息并且不跟踪任何覆盖范围。

在了解了客户端设置和服务端设置之间的相似之处之后,让我看看它们之间的区别,先从客户端开始。

2.客户端Fuzz配置

Windows RDP 客户端是mstsc.exe,但处理虚拟通道数据的大部分逻辑都在客户端加载的mstscax.dll中。

Hyper-V 虚拟机的远程访问客户端vmconnect.exe也使用mstscax.dll作为其核心功能。
在这里插入图片描述
Windows RDP 客户端

为了简单和高效,我在同一台机器上同时执行客户端和服务端(目标和代理)(使用客户端连接到 localhost/127.0.0)。为了允许并行Fuzzing,我还使用了mimikatz来修补服务端,使其允许并发 RDP 连接。
在这里插入图片描述

这些是对客户端进行Fuzzing时的设置组件:

◼目标 - mstsc.exe和mstscax.dll的目标模块

◼检测引擎 – 创建客户端进程的 DynamoRIO 和 winafl.dll,报告代码覆盖率的 DynamoRIO 客户端

◼变异引擎——在同一台机器上运行的 AFL-Fuzz 并将新的测试用例写入文件

◼输入馈送器——我的 RDPFuzzAgent,它打开服务端的句柄并在选定的虚拟通道上发送 PDU。代理从 AFL-Fuzz 创建的文件中获取每个测试用例,并将它们发送到目标通道上。

使用这些组件,我能够实现大约每秒 50-100 次执行的执行速度。

3.服务端Fuzz配置

为了找到包含 RDP 服务端主要逻辑的目标二进制文件,可以简单地查看远程桌面服务服务。

### 解决 PP-OCRv4 出现的错误 当遇到 `WARNING: The pretrained params backbone.blocks2.0.dw_conv.lab.scale not in model` 这样的警告时,这通常意味着预训练模型中的某些参数未能匹配到当前配置下的模型结构中[^2]。 对于此问题的一个有效解决方案是采用特定配置文件来适配预训练权重。具体操作方法如下: 通过指定配置文件 `ch_PP-OCRv4_det_student.yml` 并利用已有的最佳精度预训练模型 (`best_accuracy`) 来启动训练过程可以绕过上述不兼容的问题。执行命令如下所示: ```bash python3 tools/train.py -c configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml ``` 该方案不仅解决了参数缺失带来的警告,还能够继续基于高质量的预训练成果进行微调,从而提升最终检测效果。 关于蒸馏的概念,在机器学习领域内指的是将大型复杂网络(teacher 模型)的知识迁移到小型简单网络(student 模型)。这里 student 和 teacher 的关系是指两个不同规模或架构的神经网络之间的指导与被指导的关系;其中 teacher 已经经过充分训练并具有良好的性能,而 student 则试图模仿前者的行为模式以达到相似的效果但保持更高效的计算特性。 至于提到的 `Traceback` 错误信息部分,由于未提供具体的跟踪堆栈详情,难以给出针对性建议。不过一般而言,这报错往往涉及代码逻辑错误或是环境配置不当等问题。为了更好地帮助定位和解决问题,推荐记录完整的异常日志,并仔细检查最近修改过的代码片段以及确认依赖库版本的一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值