def onConnectResponse(self, pdu: MCSConnectResponsePDU): """ Parse server connection information. Initialize security settings and map channel IDs to channel names. :param pdu: the connect response PDU """ if pdu.result != 0: self.client.sendPDU(pdu) else: # Parse response PDUs gccParser = GCCParser() rdpParser = ServerConnectionParser() gccPDU: GCCConferenceCreateResponsePDU = gccParser.parse(pdu.payload) serverData = rdpParser.parse(gccPDU.payload) # Save security settings self.state.securitySettings.setEncryptionMethod(serverData.securityData.encryptionMethod) self.state.securitySettings.setServerRandom(serverData.securityData.serverRandom) if serverData.securityData.serverCertificate: self.state.securitySettings.setServerPublicKey(serverData.securityData.serverCertificate.publicKey) # Map channel names to IDs self.state.channelMap[serverData.networkData.mcsChannelID] = MCSChannelName.IO for index in range(len(serverData.networkData.channels)): channelID = serverData.networkData.channels[index] name = self.state.channelDefinitions[index].name self.log.info("%(channelName)s <---> Channel #%(channelId)d", {"channelName": name, "channelId": channelID}) self.state.channelMap[channelID] = name # Replace the server's public key with our own key so we can decrypt the incoming client random cert = serverData.securityData.serverCertificate if cert: cert = ProprietaryCertificate( cert.signatureAlgorithmID, cert.keyAlgorithmID, cert.publicKeyType, self.state.rc4RSAKey, cert.signatureType, cert.signature, cert.padding ) # FIPS is not implemented so avoid using that security = ServerSecurityData( serverData.securityData.encryptionMethod if serverData.securityData.encryptionMethod != EncryptionMethod.ENCRYPTION_FIPS else EncryptionMethod.ENCRYPTION_128BIT, serverData.securityData.encryptionLevel if serverData.securityData.encryptionLevel != EncryptionLevel.ENCRYPTION_LEVEL_FIPS else EncryptionLevel.ENCRYPTION_LEVEL_HIGH, serverData.securityData.serverRandom, cert ) # The clientRequestedProtocols field MUST be the same as the one received in the X224 Connection Request serverData.coreData.clientRequestedProtocols = self.state.requestedProtocols modifiedServerData = ServerDataPDU(serverData.coreData, security, serverData.networkData) modifiedGCCPDU = GCCConferenceCreateResponsePDU(gccPDU.nodeID, gccPDU.tag, gccPDU.result, rdpParser.write(modifiedServerData)) modifiedMCSPDU = MCSConnectResponsePDU(pdu.result, pdu.calledConnectID, pdu.domainParams, gccParser.write(modifiedGCCPDU)) self.client.sendPDU(modifiedMCSPDU)
def onConnectResponse(self, pdu, serverData): # MCS Connect Response """ :type pdu: MCSConnectResponsePDU :type serverData: ServerDataPDU """ if pdu.result != 0: self.mcs.send(pdu) return # Replace the server's public key with our own key so we can decrypt the incoming client random cert = serverData.security.serverCertificate if cert: cert = ProprietaryCertificate(cert.signatureAlgorithmID, cert.keyAlgorithmID, cert.publicKeyType, self.rc4RSAKey, cert.signatureType, cert.signature, cert.padding) security = ServerSecurityData( # FIPS is not implemented so avoid using that serverData.security.encryptionMethod if serverData.security.encryptionMethod != EncryptionMethod.ENCRYPTION_FIPS else EncryptionMethod.ENCRYPTION_128BIT, serverData.security.encryptionLevel if serverData.security.encryptionLevel != EncryptionLevel.ENCRYPTION_LEVEL_FIPS else EncryptionLevel.ENCRYPTION_LEVEL_HIGH, serverData.security.serverRandom, cert) serverData.core.clientRequestedProtocols = self.originalNegotiationPDU.requestedProtocols self.securitySettings.serverSecurityReceived(security) self.serverData = ServerDataPDU(serverData.core, security, serverData.network) rdpParser = ServerConnectionParser() gccParser = GCCParser() gcc = self.client.conferenceCreateResponse gcc = GCCConferenceCreateResponsePDU(gcc.nodeID, gcc.tag, gcc.result, rdpParser.write(self.serverData)) pdu = MCSConnectResponsePDU(pdu.result, pdu.calledConnectID, pdu.domainParams, gccParser.write(gcc)) self.mcs.send(pdu)
def __init__(self, sendParser = ClientConnectionParser(), recvParser = ServerConnectionParser()): """ :param sendParser: parser to use when sending client PDUs. :param recvParser: parser to use when receiving server PDUs. """ Layer.__init__(self, None, hasNext=True) self.sendParser = sendParser self.recvParser = recvParser
def __init__(self, friendlyName: str, targetHost: str, targetPort: int, certificateFileName: str, privateKeyFileName: str, recordHost: str, recordPort: int, replacementUsername: str, replacementPassword: str): MCSUserObserver.__init__(self) self.sessionId = f"{friendlyName}{random.randrange(100000,999999)}" self.log = getLoggerPassFilters( f"{LOGGER_NAMES.MITM_CONNECTIONS}.{self.sessionId}.server") self.metadataFilter = ConnectionMetadataFilter(self, self.sessionId) self.log.addFilter(self.metadataFilter) self.replacementPassword = replacementPassword self.replacementUsername = replacementUsername self.targetHost = targetHost self.targetPort = targetPort self.certificateFileName = certificateFileName self.privateKeyFileName = privateKeyFileName self.clipboardObserver = None self.useTLS = False self.client: MITMClient = None self.clientConnector = None self.originalNegotiationPDU = None self.targetNegotiationPDU = None self.serverData = None self.rc4RSAKey = RSA.generate(2048) self.crypter = RC4CrypterProxy() self.socket = None self.fileHandle = open( "out/rdp_replay_{}_{}.pyrdp".format( datetime.datetime.now().strftime('%Y%m%d_%H-%M-%S'), random.randint(0, 1000)), "wb") rc4Log = getLoggerPassFilters(f"{self.log.name}.rc4") self.securitySettings = SecuritySettings(SecuritySettings.Mode.SERVER) self.securitySettings.addObserver(self.crypter) self.securitySettings.addObserver(RC4LoggingObserver(rc4Log)) self.tcp = TwistedTCPLayer() self.tcp.createObserver(onConnection=self.onConnection, onDisconnection=self.onDisconnection) self.segmentation = SegmentationLayer() self.segmentation.createObserver( onUnknownHeader=self.onUnknownTPKTHeader) self.tpkt = TPKTLayer() self.x224 = X224Layer() self.x224.createObserver(onConnectionRequest=self.onConnectionRequest, onDisconnectRequest=self.onDisconnectRequest) self.mcs = MCSLayer() self.router = MITMServerRouter(self.mcs, self) self.mcs.addObserver(self.router) self.router.createObserver( onConnectionReceived=self.onConnectInitial, onDisconnectProviderUltimatum=self.onDisconnectProviderUltimatum, onAttachUserRequest=self.onAttachUserRequest, onChannelJoinRequest=self.onChannelJoinRequest) self.gcc = GCCParser() self.rdpClientInfoParser = ClientInfoParser() self.rdpClientConnectionParser = ClientConnectionParser() self.rdpServerConnectionParser = ServerConnectionParser() self.securityLayer = None self.slowPathLayer = SlowPathLayer() self.fastPathLayer = None self.tcp.setNext(self.segmentation) self.segmentation.attachLayer(SegmentationPDUType.TPKT, self.tpkt) Layer.chain(self.tpkt, self.x224, self.mcs) if recordHost is not None and recordPort is not None: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.socket.connect((recordHost, recordPort)) except socket.error as e: logging.getLogger(LOGGER_NAMES.MITM).error( "Could not connect to liveplayer: %(error)s", {"error": e}) self.socket.close() self.socket = None recordingLayers = [FileLayer(self.fileHandle)] if self.socket is not None: recordingLayers.append(SocketLayer(self.socket)) # Since we're intercepting communications from the original client (so we're a server), # We need to write back the packets as if they came from the client. self.recorder = Recorder(recordingLayers)