Exemplo n.º 1
0
def prepare_loggers(logLevel):
    """
    Sets up the "liveplayer" and "liveplayer.ui" loggers to print messages and send notifications on connect.
    """
    log.prepare_pyrdp_logger(logLevel)
    log.prepare_ssl_session_logger()

    if not os.path.exists("log"):
        os.makedirs("log")

    liveplayer_logger = getLoggerPassFilters(LOGGER_NAMES.LIVEPLAYER)
    liveplayer_logger.setLevel(logLevel)

    liveplayer_ui_logger = getLoggerPassFilters(
        f"{LOGGER_NAMES.LIVEPLAYER}.ui")
    liveplayer_ui_logger.setLevel(logLevel)

    formatter = log.get_formatter()

    stream_handler = logging.StreamHandler()
    file_handler = logging.FileHandler("log/liveplayer.log")
    stream_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)
    liveplayer_logger.addHandler(stream_handler)
    liveplayer_logger.addHandler(file_handler)

    notify_handler = NotifyHandler()
    notify_handler.setFormatter(
        logging.Formatter("[%(asctime)s] - %(message)s"))
    liveplayer_ui_logger.addHandler(notify_handler)
Exemplo n.º 2
0
    def __init__(self, layer: Layer, recorder: Recorder, logger: Logger, **kwargs):
        Observer.__init__(self, **kwargs)

        self.clipboardParser = ClipboardParser()
        self.peer = None
        self.layer = layer
        self.recorder = recorder
        self.forwardNextDataResponse = True
        self.mitm_log = getLoggerPassFilters(f"{logger.name}.clipboard")
        self.clipboard_log = getLoggerPassFilters(f"{self.mitm_log.name}.data")
Exemplo n.º 3
0
 def __init__(self, maxTabCount=250):
     QTabWidget.__init__(self)
     self.closeTabShortcut = QShortcut(QKeySequence("Ctrl+W"), self,
                                       self.closeCurrentTab)
     self.maxTabCount = maxTabCount
     self.setTabsClosable(True)
     self.tabCloseRequested.connect(self.onTabClosed)
     self.log = getLoggerPassFilters(LOGGER_NAMES.LIVEPLAYER)
Exemplo n.º 4
0
    def dataReceived(self, data):
        """
        When a PSH TCP packet is received, call the next layer to receive the data.
        :param data: The byte stream (without the TCP header)
        :type data: bytes
        """
        try:
            if self.logSSLRequired:
                self.logSSLParameters()
                self.logSSLRequired = False

            self.next.recv(data)
        except KeyboardInterrupt:
            raise
        except Exception as e:
            getLoggerPassFilters(LOGGER_NAMES.PYRDP_EXCEPTIONS).exception(e)
            raise
Exemplo n.º 5
0
def prepare_loggers(logLevel, sensorID):
    """
        Sets up the "mitm" and the "mitm.connections" loggers.
    """
    log.prepare_pyrdp_logger(logLevel)
    log.prepare_ssl_session_logger()

    if not os.path.exists("log"):
        os.makedirs("log")

    mitm_logger = getLoggerPassFilters(LOGGER_NAMES.MITM)
    mitm_logger.setLevel(logLevel)

    mitm_connections_logger = getLoggerPassFilters(
        LOGGER_NAMES.MITM_CONNECTIONS)
    mitm_connections_logger.setLevel(logLevel)

    formatter = log.get_formatter()

    stream_handler = logging.StreamHandler()
    file_handler = logging.handlers.TimedRotatingFileHandler("log/mitm.log",
                                                             when="D")
    stream_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)
    mitm_logger.addHandler(stream_handler)
    mitm_logger.addHandler(file_handler)

    # Make sure that the library writes to the file as well
    pyrdp_logger = log.get_logger()
    pyrdp_logger.addHandler(file_handler)

    exceptions_logger = getLoggerPassFilters(LOGGER_NAMES.PYRDP_EXCEPTIONS)
    exceptions_logger.propagate = False
    exceptions_logger.addHandler(file_handler)

    jsonFormatter = JSONFormatter()
    jsonFileHandler = logging.FileHandler("log/mitm.json")
    sensorFilter = SensorFilter(sensorID)

    jsonFileHandler.setFormatter(jsonFormatter)
    jsonFileHandler.setLevel(logging.INFO)
    jsonFileHandler.addFilter(sensorFilter)

    getLoggerPassFilters(
        LOGGER_NAMES.MITM_CONNECTIONS).addHandler(jsonFileHandler)
Exemplo n.º 6
0
 def __init__(self, layer: Layer, recorder: Recorder, logger: logging.Logger, **kwargs):
     super().__init__(**kwargs)
     self.peer: PassiveFileStealer = None
     self.layer = layer
     self.recorder = recorder
     self.mitm_log = getLoggerPassFilters(f"{logger.name}.deviceRedirection")
     self.deviceRedirectionParser = DeviceRedirectionParser()
     self.completionIdInProgress: Dict[MajorFunction, DeviceIORequestPDU] = {}
     self.reconstructedFilesTemp: Dict[int, BytesIO] = {}
     self.openedFiles: Dict[int, bytes] = {}
     self.finalFiles: Dict[str, BytesIO] = {}
     self.pduToSend = None  # Needed since the PDU changes if it's a response.
Exemplo n.º 7
0
def prepare_ssl_session_logger():
    """
    Prepares the SSL master secret logger. Used to log TLS session secrets to decrypt traffic later.
    """
    ssl_logger = getLoggerPassFilters("ssl")
    ssl_logger.setLevel(logging.INFO)
    os.makedirs("log", exist_ok=True)
    handler = logging.FileHandler("log/ssl_master_secret.log")
    formatter = SSLSecretFormatter()
    handler.setFormatter(formatter)
    ssl_logger.addHandler(handler)
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    ssl_logger.addHandler(stream_handler)
Exemplo n.º 8
0
def prepare_pyrdp_logger(logLevel=logging.INFO):
    """
    Prepare the PyRDP logger to be used by the library.
    """
    logger = getLoggerPassFilters(LOGGER_NAMES.PYRDP)
    logger.setLevel(logLevel)

    stream_handler = logging.StreamHandler()

    formatter = get_formatter()

    stream_handler.setFormatter(formatter)
    stream_handler.setLevel(logLevel)

    logger.addHandler(stream_handler)
Exemplo n.º 9
0
    def __init__(self, viewer):
        """
        :type viewer: QWidget
        """
        QWidget.__init__(self, None, Qt.WindowFlags())
        self.widget = viewer

        self.writeInCaps = False
        self.text = QTextEdit()
        self.text.setReadOnly(True)
        self.text.setMinimumHeight(150)
        self.log = getLoggerPassFilters(LOGGER_NAMES.LIVEPLAYER)

        scrollViewer = QScrollArea()
        scrollViewer.setWidget(self.widget)
        layout = QVBoxLayout()
        layout.addWidget(scrollViewer, 8)
        layout.addWidget(self.text, 2)

        self.setLayout(layout)
Exemplo n.º 10
0
    def __init__(self, duration: float, parent: QWidget = None):
        QWidget.__init__(self, parent)

        self.log = getLoggerPassFilters(LOGGER_NAMES.LIVEPLAYER)

        self.button = PlayPauseButton()
        self.button.setMaximumWidth(100)
        self.button.clicked.connect(self.onButtonClicked)

        self.timeSlider = ClickableProgressBar()
        self.timeSlider.setMinimum(0)
        self.timeSlider.setMaximum(int(duration * 1000))
        self.timeSlider.valueChanged.connect(self.onSeek)

        self.speedLabel = QLabel("Speed: 1x")

        self.speedSlider = QSlider(Qt.Horizontal)
        self.speedSlider.setMaximumWidth(300)
        self.speedSlider.setMinimum(1)
        self.speedSlider.setMaximum(10)
        self.speedSlider.valueChanged.connect(self.onSpeedChanged)

        vertical = QVBoxLayout()

        horizontal = QHBoxLayout()
        horizontal.addWidget(self.speedLabel)
        horizontal.addWidget(self.speedSlider)
        horizontal.addItem(
            QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Expanding))
        vertical.addLayout(horizontal)

        horizontal = QHBoxLayout()
        horizontal.addWidget(self.button)
        horizontal.addWidget(self.timeSlider)
        vertical.addLayout(horizontal)

        self.setLayout(vertical)
        self.setGeometry(0, 0, 80, 60)
Exemplo n.º 11
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)
Exemplo n.º 12
0
def get_ssl_logger():
    """
    Get the SSL logger.
    """
    return getLoggerPassFilters("ssl")
Exemplo n.º 13
0
def get_logger():
    """
    Get the main logger.
    """
    return getLoggerPassFilters(LOGGER_NAMES.PYRDP)
Exemplo n.º 14
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)
Exemplo n.º 15
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "target",
        help="IP:port of the target RDP machine (ex: 192.168.1.10:3390)")
    parser.add_argument("-l",
                        "--listen",
                        help="Port number to listen on (default: 3389)",
                        default=3389)
    parser.add_argument("-o",
                        "--output",
                        help="Output folder for replay files")
    parser.add_argument(
        "-i",
        "--destination-ip",
        help=
        "Destination IP address of the PyRDP player.If not specified, RDP events are not sent over the network."
    )
    parser.add_argument(
        "-d",
        "--destination-port",
        help="Listening port of the PyRDP player (default: 3000).",
        default=3000)
    parser.add_argument("-k",
                        "--private-key",
                        help="Path to private key (for SSL)")
    parser.add_argument("-c",
                        "--certificate",
                        help="Path to certificate (for SSL)")
    parser.add_argument(
        "-n",
        "--nla",
        help="For NLA client authentication (need to provide credentials)",
        action="store_true")
    parser.add_argument(
        "-u",
        "--username",
        help="Username that will replace the client's username",
        default=None)
    parser.add_argument(
        "-p",
        "--password",
        help="Password that will replace the client's password",
        default=None)
    parser.add_argument(
        "-L",
        "--log-level",
        help="Log level",
        default="INFO",
        choices=["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"])
    parser.add_argument(
        "-s",
        "--sensor-id",
        help=
        "Sensor ID (to differentiate multiple instances of the MITM where logs are aggregated at one place)",
        default="PyRDP")

    args = parser.parse_args()

    logLevel = getattr(logging, args.log_level)

    prepare_loggers(logLevel, args.sensor_id)
    os.makedirs("out", exist_ok=True)
    mitm_log = getLoggerPassFilters(LOGGER_NAMES.MITM)

    target = args.target
    if ":" in target:
        targetHost = target[:target.index(":")]
        targetPort = int(target[target.index(":") + 1:])
    else:
        targetHost = target
        targetPort = 3389
    if (args.private_key is None) != (args.certificate is None):
        mitm_log.error(
            "You must provide both the private key and the certificate")
        sys.exit(1)
    elif args.private_key is None:
        key, certificate = getSSLPaths()
        handleKeyAndCertificates(certificate, key, mitm_log)
    else:
        key, certificate = args.private_key, args.certificate
    listenPort = int(args.listen)
    reactor.listenTCP(
        listenPort,
        MITMServerFactory(targetHost, targetPort, key,
                          certificate, args.destination_ip,
                          int(args.destination_port), args.username,
                          args.password))
    mitm_log.info("MITM Server listening on port %(port)d",
                  {"port": listenPort})
    reactor.run()
Exemplo n.º 16
0
    parser.add_argument("-p",
                        "--port",
                        help="Bind port (default: 3000)",
                        default=3000)
    parser.add_argument(
        "-L",
        "--log-level",
        help="Log level",
        default="INFO",
        choices=["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"],
        nargs="?")

    arguments = parser.parse_args()

    logLevel = getattr(logging, arguments.log_level)
    prepare_loggers(logLevel)

    app = QApplication(sys.argv)

    mainWindow = player.MainWindow(arguments.bind, int(arguments.port),
                                   arguments.replay)
    mainWindow.show()

    return app.exec_()


if __name__ == '__main__':
    mlog = getLoggerPassFilters(LOGGER_NAMES.LIVEPLAYER)
    ulog = getLoggerPassFilters(f"{LOGGER_NAMES.LIVEPLAYER}.ui")
    sys.exit(main())