Esempio n. 1
0
    def __init__(self, output_path: str, format: str = None):
        def sendBytesStub(_: bytes):
            pass

        output_path = Path(output_path)
        output_directory = output_path.absolute().parent
        logger = logging.getLogger(LOGGER_NAMES.MITM_CONNECTIONS)
        log = SessionLogger(logger, "replay")

        config = RDPReplayerConfig()
        config.outDir = output_directory
        # We'll set up the recorder ourselves
        config.recordReplays = False

        state = RDPMITMState(config, log.sessionID)

        sink, outfile = getSink(format, output_path)
        transport = ConversionLayer(sink) if sink else FileLayer(outfile)
        rec = CustomMITMRecorder([transport], state)

        super().__init__(log, log, config, state, rec)

        self.client.tcp.sendBytes = sendBytesStub
        self.server.tcp.sendBytes = sendBytesStub
        self.state.useTLS = True
Esempio n. 2
0
    def __init__(self, output_path: str, mp4: bool = False):
        def sendBytesStub(_: bytes):
            pass

        output_path = Path(output_path)
        output_directory = output_path.absolute().parent
        logger = logging.getLogger(LOGGER_NAMES.MITM_CONNECTIONS)
        log = SessionLogger(logger, "replay")

        config = RDPReplayerConfig()
        config.outDir = output_directory
        # We'll set up the recorder ourselves
        config.recordReplays = False

        transport = FileLayer(output_path)
        state = RDPMITMState(config)

        sink = None
        if mp4:
            sink = Mp4EventHandler(output_path)
            transport = Mp4Layer(sink)

        super().__init__(log, log, config, state, CustomMITMRecorder([transport], state))

        self.client.tcp.sendBytes = sendBytesStub
        self.server.tcp.sendBytes = sendBytesStub
        self.state.useTLS = True
Esempio n. 3
0
    def __init__(self, handler, outputPath: str, sessionID: str):
        def sendBytesStub(_: bytes):
            pass

        output_directory = Path(outputPath)
        logger = logging.getLogger(LOGGER_NAMES.MITM_CONNECTIONS)
        log = SessionLogger(logger, "replay")

        config = RDPReplayerConfig()
        config.outDir = output_directory
        config.outDir.mkdir(exist_ok=True)

        # We'll set up the recorder ourselves
        config.recordReplays = False

        state = RDPMITMState(config, sessionID)

        transport = ConversionLayer(handler) if handler else FileLayer(
            output_directory / (sessionID + '.' + HANDLERS['replay'][1]))
        rec = OfflineRecorder([transport], state)

        super().__init__(log, log, config, state, rec)

        self.client.tcp.sendBytes = sendBytesStub
        self.server.tcp.sendBytes = sendBytesStub
        self.state.useTLS = True
Esempio n. 4
0
    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)
Esempio n. 5
0
    def __init__(self, log: SessionLogger, config: MITMConfig):
        """
        :param log: base logger to use for the connection
        :param config: the MITM configuration
        """

        self.log = log
        """Base logger for the connection"""

        self.clientLog = log.createChild("client")
        """Base logger for the client side"""

        self.serverLog = log.createChild("server")
        """Base logger for the server side"""

        self.attackerLog = log.createChild("attacker")
        """Base logger for the attacker side"""

        self.rc4Log = log.createChild("rc4")
        """Logger for RC4 secrets"""

        self.config = config
        """The MITM configuration"""

        self.statCounter = StatCounter()
        """Class to keep track of connection-related statistics such as # of mouse events, # of output events, etc."""

        self.state = RDPMITMState()
        """The MITM state"""

        self.client = RDPLayerSet()
        """Layers on the client side"""

        self.server = RDPLayerSet()
        """Layers on the server side"""

        self.player = TwistedPlayerLayerSet()
        """Layers on the attacker side"""

        self.recorder = MITMRecorder([], self.state)
        """Recorder for this connection"""

        self.channelMITMs = {}
        """MITM components for virtual channels"""

        serverConnector = self.connectToServer()
        self.tcp = TCPMITM(self.client.tcp, self.server.tcp, self.player.tcp,
                           self.getLog("tcp"), self.state, self.recorder,
                           serverConnector, self.statCounter)
        """TCP MITM component"""

        self.x224 = X224MITM(self.client.x224, self.server.x224,
                             self.getLog("x224"), self.state, serverConnector,
                             self.startTLS)
        """X224 MITM component"""

        self.mcs = MCSMITM(self.client.mcs, self.server.mcs,
                           self.state, self.recorder, self.buildChannel,
                           self.getLog("mcs"), self.statCounter)
        """MCS MITM component"""

        self.security: SecurityMITM = None
        """Security MITM component"""

        self.slowPath = SlowPathMITM(self.client.slowPath,
                                     self.server.slowPath, self.state,
                                     self.statCounter)
        """Slow-path MITM component"""

        self.fastPath: FastPathMITM = None
        """Fast-path MITM component"""

        self.attacker: AttackerMITM = None

        self.client.x224.addObserver(X224Logger(self.getClientLog("x224")))
        self.client.mcs.addObserver(MCSLogger(self.getClientLog("mcs")))
        self.client.slowPath.addObserver(
            SlowPathLogger(self.getClientLog("slowpath")))
        self.client.slowPath.addObserver(
            RecordingSlowPathObserver(self.recorder))

        self.server.x224.addObserver(X224Logger(self.getServerLog("x224")))
        self.server.mcs.addObserver(MCSLogger(self.getServerLog("mcs")))
        self.server.slowPath.addObserver(
            SlowPathLogger(self.getServerLog("slowpath")))
        self.server.slowPath.addObserver(
            RecordingSlowPathObserver(self.recorder))

        self.player.player.addObserver(LayerLogger(self.attackerLog))

        self.config.outDir.mkdir(parents=True, exist_ok=True)
        self.config.replayDir.mkdir(exist_ok=True)
        self.config.fileDir.mkdir(exist_ok=True)

        self.state.securitySettings.addObserver(RC4LoggingObserver(
            self.rc4Log))

        if config.recordReplays:
            date = datetime.datetime.now()
            replayFileName = "rdp_replay_{}_{}.pyrdp".format(
                date.strftime('%Y%m%d_%H-%M-%S'), date.microsecond // 1000)
            self.recorder.addTransport(
                FileLayer(self.config.replayDir / replayFileName))
Esempio n. 6
0
    def __init__(self,
                 server,
                 fileHandle: BinaryIO,
                 livePlayerSocket: socket,
                 replacementUsername=None,
                 replacementPassword=None):
        MCSChannelFactory.__init__(self)
        self.log = getLoggerPassFilters(
            f"{LOGGER_NAMES.MITM_CONNECTIONS}.{server.getSessionId()}.client")
        self.log.addFilter(server.metadataFilter)

        self.replacementUsername = replacementUsername
        self.replacementPassword = replacementPassword

        self.server = server
        self.channelMap: Dict[int, str] = {}
        self.channelDefinitions = []
        self.channelObservers = {}
        self.deviceRedirectionObserver = None
        self.useTLS = False
        self.user = None
        self.fastPathObserver = None
        self.conferenceCreateResponse = None
        self.serverData = None
        self.crypter = RC4CrypterProxy()

        rc4Log = getLoggerPassFilters(f"{self.log.name}.rc4")
        self.securitySettings = SecuritySettings(SecuritySettings.Mode.CLIENT)
        self.securitySettings.addObserver(self.crypter)
        self.securitySettings.addObserver(RC4LoggingObserver(rc4Log))

        self.tcp = TwistedTCPLayer()
        self.tcp.createObserver(onConnection=self.startConnection,
                                onDisconnection=self.onDisconnection)

        self.segmentation = SegmentationLayer()
        self.segmentation.createObserver(
            onUnknownHeader=self.onUnknownTPKTHeader)

        self.tpkt = TPKTLayer()

        self.x224 = X224Layer()
        self.x224.createObserver(onConnectionConfirm=self.onConnectionConfirm,
                                 onDisconnectRequest=self.onDisconnectRequest)

        self.mcs = MCSLayer()
        self.router = MCSClientRouter(self.mcs, self)
        self.mcs.addObserver(self.router)
        self.router.createObserver(
            onConnectResponse=self.onConnectResponse,
            onDisconnectProviderUltimatum=self.onDisconnectProviderUltimatum)

        self.mcsConnect = MCSClientConnectionLayer(self.mcs)

        self.gccConnect = GCCClientConnectionLayer(b"1")
        self.gccConnect.createObserver(
            onPDUReceived=self.onConferenceCreateResponse)

        self.rdpConnect = ClientConnectionLayer()
        self.rdpConnect.createObserver(onPDUReceived=self.onServerData)

        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)
        Layer.chain(self.mcsConnect, self.gccConnect, self.rdpConnect)

        record_layers = [FileLayer(fileHandle)]

        if livePlayerSocket is not None:
            record_layers.append(SocketLayer(livePlayerSocket))

        self.recorder = Recorder(record_layers)
Esempio n. 7
0
    def __init__(self,
                 mainLogger: SessionLogger,
                 crawlerLogger: SessionLogger,
                 config: MITMConfig,
                 state: RDPMITMState = None,
                 recorder: Recorder = None):
        """
        :param log: base logger to use for the connection
        :param config: the MITM configuration
        """

        self.log = mainLogger
        """Base logger for the connection"""

        self.clientLog = mainLogger.createChild("client")
        """Base logger for the client side"""

        self.serverLog = mainLogger.createChild("server")
        """Base logger for the server side"""

        self.attackerLog = mainLogger.createChild("attacker")
        """Base logger for the attacker side"""

        self.rc4Log = mainLogger.createChild("rc4")
        """Logger for RC4 secrets"""

        self.config = config
        """The MITM configuration"""

        self.statCounter = StatCounter()
        """Class to keep track of connection-related statistics such as # of mouse events, # of output events, etc."""

        self.state = state if state is not None else RDPMITMState(self.config)
        """The MITM state"""

        self.client = RDPLayerSet()
        """Layers on the client side"""

        self.server = RDPLayerSet()
        """Layers on the server side"""

        self.player = TwistedPlayerLayerSet()
        """Layers on the attacker side"""

        self.recorder = recorder if recorder is not None else MITMRecorder(
            [], self.state)
        """Recorder for this connection"""

        self.channelMITMs = {}
        """MITM components for virtual channels"""

        serverConnector = self.connectToServer()
        self.tcp = TCPMITM(self.client.tcp, self.server.tcp, self.player.tcp,
                           self.getLog("tcp"), self.state, self.recorder,
                           serverConnector, self.statCounter)
        """TCP MITM component"""

        self.x224 = X224MITM(self.client.x224, self.server.x224,
                             self.getLog("x224"), self.state, serverConnector,
                             self.startTLS)
        """X224 MITM component"""

        self.mcs = MCSMITM(self.client.mcs, self.server.mcs,
                           self.state, self.recorder, self.buildChannel,
                           self.getLog("mcs"), self.statCounter)
        """MCS MITM component"""

        self.security: SecurityMITM = None
        """Security MITM component"""

        self.slowPath = SlowPathMITM(self.client.slowPath,
                                     self.server.slowPath, self.state,
                                     self.statCounter)
        """Slow-path MITM component"""

        self.fastPath: FastPathMITM = None
        """Fast-path MITM component"""

        self.attacker: AttackerMITM = None

        self.crawler: FileCrawlerMITM = None

        self.client.x224.addObserver(X224Logger(self.getClientLog("x224")))
        self.client.mcs.addObserver(MCSLogger(self.getClientLog("mcs")))
        self.client.slowPath.addObserver(
            SlowPathLogger(self.getClientLog("slowpath")))
        self.client.slowPath.addObserver(
            RecordingSlowPathObserver(self.recorder))

        self.server.x224.addObserver(X224Logger(self.getServerLog("x224")))
        self.server.mcs.addObserver(MCSLogger(self.getServerLog("mcs")))
        self.server.slowPath.addObserver(
            SlowPathLogger(self.getServerLog("slowpath")))
        self.server.slowPath.addObserver(
            RecordingSlowPathObserver(self.recorder))

        self.player.player.addObserver(LayerLogger(self.attackerLog))

        self.ensureOutDir()

        if config.certificateFileName is None:
            self.certs: CertificateCache = CertificateCache(
                self.config.certDir, mainLogger.createChild("cert"))
        else:
            self.certs = None

        self.state.securitySettings.addObserver(RC4LoggingObserver(
            self.rc4Log))

        if config.recordReplays:
            date = datetime.datetime.now()
            replayFileName = "rdp_replay_{}_{}_{}.pyrdp"\
                    .format(date.strftime('%Y%m%d_%H-%M-%S'),
                            date.microsecond // 1000,
                            self.log.sessionID)
            self.recorder.setRecordFilename(replayFileName)
            self.recorder.addTransport(
                FileLayer(self.config.replayDir / replayFileName))

        if config.enableCrawler:
            self.crawler: FileCrawlerMITM = FileCrawlerMITM(
                self.getClientLog(
                    MCSChannelName.DEVICE_REDIRECTION).createChild("crawler"),
                crawlerLogger, self.config, self.state)