Example #1
0
    def onClipboardData(self, pdu: PlayerPDU):
        parser = ClipboardParser()
        pdu = parser.parse(pdu.payload)

        if not isinstance(pdu, FormatDataResponsePDU):
            return

        clipboardData = decodeUTF16LE(pdu.requestedFormatData)

        self.writeSeparator()
        self.writeText(f"CLIPBOARD DATA: {clipboardData}")
        self.writeSeparator()
Example #2
0
    def onClipboardData(self, pdu: PlayerPDU):
        parser = ClipboardParser()
        pdu = parser.parse(pdu.payload)

        if not isinstance(pdu, FormatDataResponsePDU):
            # TODO: Handle file PDUs.
            return

        data = decodeUTF16LE(pdu.requestedFormatData)
        self.json[JSON_KEY_EVENTS].append({
            "timestamp": self.timestamp,
            "type": "clipboard",
            "data": {
                "mime": "text/plain",
                "content": data
            },
        })
Example #3
0
class PlayerMessageHandler(PlayerMessageObserver):
    """
    Class to manage the display of the RDP player when reading events.
    """
    def __init__(self, viewer, text):
        super().__init__()
        self.viewer = viewer
        self.text = text
        self.writeInCaps = False

        self.inputParser = BasicFastPathParser(ParserMode.SERVER)
        self.outputParser = BasicFastPathParser(ParserMode.CLIENT)
        self.clientInfoParser = ClientInfoParser()
        self.dataParser = SlowPathParser()
        self.clipboardParser = ClipboardParser()
        self.outputEventParser = FastPathOutputParser()
        self.clientConnectionParser = ClientConnectionParser()

        self.buffer = b""

    def onConnectionClose(self, pdu: PlayerMessagePDU):
        self.text.moveCursor(QTextCursor.End)
        self.text.insertPlainText("\n<Connection closed>")

    def onOutput(self, pdu: PlayerMessagePDU):
        pdu = self.outputParser.parse(pdu.payload)

        for event in pdu.events:
            reassembledEvent = self.reassembleEvent(event)
            if reassembledEvent is not None:
                if isinstance(reassembledEvent, FastPathOrdersEvent):
                    log.debug("Not handling orders event, not coded :)")
                elif isinstance(reassembledEvent, FastPathBitmapEvent):
                    log.debug("Handling bitmap event %(arg1)s",
                              {"arg1": type(reassembledEvent)})
                    self.onBitmap(reassembledEvent)
                else:
                    log.debug("Can't handle output event: %(arg1)s",
                              {"arg1": type(reassembledEvent)})
            else:
                log.debug("Reassembling output event...")

    def onInput(self, pdu: PlayerMessagePDU):
        pdu = self.inputParser.parse(pdu.payload)

        for event in pdu.events:
            if isinstance(event, FastPathScanCodeEvent):
                log.debug("handling %(arg1)s", {"arg1": event})
                self.onScanCode(event.scancode, not event.isReleased)
            elif isinstance(event, FastPathMouseEvent):
                self.onMousePosition(event.mouseX, event.mouseY)
            else:
                log.debug("Can't handle input event: %(arg1)s",
                          {"arg1": event})

    def onScanCode(self, code: int, isPressed: bool):
        """
        Handle scan code.
        """
        log.debug("Reading scancode %(arg1)s", {"arg1": code})

        if code in [0x2A, 0x36]:
            self.text.moveCursor(QTextCursor.End)
            self.text.insertPlainText(
                "\n<LSHIFT PRESSED>" if isPressed else "\n<LSHIFT RELEASED>")
            self.writeInCaps = not self.writeInCaps
        elif code == 0x3A and isPressed:
            self.text.moveCursor(QTextCursor.End)
            self.text.insertPlainText("\n<CAPSLOCK>")
            self.writeInCaps = not self.writeInCaps
        elif isPressed:
            char = scancodeToChar(code)
            self.text.moveCursor(QTextCursor.End)
            self.text.insertPlainText(
                char if self.writeInCaps else char.lower())

    def onMousePosition(self, x: int, y: int):
        self.viewer.setMousePosition(x, y)

    def onBitmap(self, event: FastPathBitmapEvent):
        parsedEvent = self.outputEventParser.parseBitmapEvent(event)
        for bitmapData in parsedEvent.bitmapUpdateData:
            self.handleBitmap(bitmapData)

    def handleBitmap(self, bitmapData: BitmapUpdateData):
        image = RDPBitmapToQtImage(
            bitmapData.width, bitmapData.heigth, bitmapData.bitsPerPixel,
            bitmapData.flags & BitmapFlags.BITMAP_COMPRESSION != 0,
            bitmapData.bitmapData)
        self.viewer.notifyImage(bitmapData.destLeft, bitmapData.destTop, image,
                                bitmapData.destRight - bitmapData.destLeft + 1,
                                bitmapData.destBottom - bitmapData.destTop + 1)

    def onClientInfo(self, pdu: PlayerMessagePDU):
        clientInfoPDU = self.clientInfoParser.parse(pdu.payload)
        self.text.insertPlainText(
            "USERNAME: {}\nPASSWORD: {}\nDOMAIN: {}\n".format(
                clientInfoPDU.username.replace("\0", ""),
                clientInfoPDU.password.replace("\0", ""),
                clientInfoPDU.domain.replace("\0", "")))
        self.text.insertPlainText("--------------------\n")

    def onSlowPathPDU(self, pdu: PlayerMessagePDU):
        pdu = self.dataParser.parse(pdu.payload)

        if isinstance(pdu, ConfirmActivePDU):
            self.viewer.resize(
                pdu.parsedCapabilitySets[
                    CapabilityType.CAPSTYPE_BITMAP].desktopWidth,
                pdu.parsedCapabilitySets[
                    CapabilityType.CAPSTYPE_BITMAP].desktopHeight)
        elif isinstance(
                pdu, UpdatePDU
        ) and pdu.updateType == SlowPathUpdateType.SLOWPATH_UPDATETYPE_BITMAP:
            updates = BitmapParser().parseBitmapUpdateData(pdu.updateData)
            for bitmap in updates:
                self.handleBitmap(bitmap)
        elif isinstance(pdu, InputPDU):
            for event in pdu.events:
                if isinstance(event, MouseEvent):
                    self.onMousePosition(event.x, event.y)
                elif isinstance(event, KeyboardEvent):
                    self.onScanCode(
                        event.keyCode,
                        event.flags & KeyboardFlag.KBDFLAGS_DOWN != 0)

    def onClipboardData(self, pdu: PlayerMessagePDU):
        formatDataResponsePDU: FormatDataResponsePDU = self.clipboardParser.parse(
            pdu.payload)
        self.text.moveCursor(QTextCursor.End)
        self.text.insertPlainText("\n=============\n")
        self.text.insertPlainText("CLIPBOARD DATA: {}".format(
            decodeUTF16LE(formatDataResponsePDU.requestedFormatData)))
        self.text.insertPlainText("\n=============\n")

    def onClientData(self, pdu: PlayerMessagePDU):
        """
        Prints the clientName on the screen
        """
        clientDataPDU = self.clientConnectionParser.parse(pdu.payload)
        self.text.moveCursor(QTextCursor.End)
        self.text.insertPlainText("--------------------\n")
        self.text.insertPlainText(
            f"HOST: {clientDataPDU.coreData.clientName.strip(chr(0))}\n")

    def reassembleEvent(
        self, event: FastPathOutputEvent
    ) -> Optional[Union[FastPathBitmapEvent, FastPathOutputEvent]]:
        """
        Handles FastPath event reassembly as described in
        https://msdn.microsoft.com/en-us/library/cc240622.aspx
        :param event: A potentially segmented fastpath output event
        :return: a FastPathBitmapEvent if a complete PDU has been reassembled, otherwise None. If the event is not
        fragmented, returns the original event.
        """
        fragmentationFlag = FastPathFragmentation((event.header
                                                   & 0b00110000) >> 4)
        if fragmentationFlag == FastPathFragmentation.FASTPATH_FRAGMENT_SINGLE:
            return event
        elif fragmentationFlag == FastPathFragmentation.FASTPATH_FRAGMENT_FIRST:
            self.buffer = event.payload
        elif fragmentationFlag == FastPathFragmentation.FASTPATH_FRAGMENT_NEXT:
            self.buffer += event.payload
        elif fragmentationFlag == FastPathFragmentation.FASTPATH_FRAGMENT_LAST:
            self.buffer += event.payload
            event.payload = self.buffer
            return self.outputEventParser.parseBitmapEvent(event)

        return None