Beispiel #1
0
 def parseSecondaryDrawingOrder(self, orderData):
     stream = BytesIO(orderData)
     controlFlags = Uint8.unpack(stream.read(1))
     orderLength = Uint16LE.unpack(stream.read(2))
     extraFlags = Uint16LE.unpack(stream.read(2))
     orderType = Uint8.unpack(stream.read(1))
     return SecondaryDrawingOrder(controlFlags, orderLength, extraFlags, orderType)
Beispiel #2
0
    def parse(self, data: bytes) -> NegotiationRequestPDU:
        """
        Parse a negotiation request.
        :param data: the request data.
        """

        cookie = None

        if b"\r\n" in data:
            cookie = data[: data.index(b"\r\n")]
            data = data[data.index(b"\r\n") + 2 :]

        stream = BytesIO(data)

        if len(data) >= 8:
            type = Uint8.unpack(stream)
            requestFlags = Uint8.unpack(stream)
            requestLength = Uint16LE.unpack(stream)
            requestedProtocols = Uint32LE.unpack(stream)

            correlationFlags = None
            correlationID = None

            if requestFlags & NegotiationRequestFlags.CORRELATION_INFO_PRESENT != 0 and len(data) >= 36:
                type = Uint8.unpack(stream)
                correlationFlags = Uint8.unpack(stream)
                correlationLength = Uint16LE.unpack(stream)
                correlationID = stream.read(16)
                stream.read(16)

            return NegotiationRequestPDU(cookie, requestFlags, requestedProtocols, correlationFlags, correlationID)
        else:
            return NegotiationRequestPDU(cookie, None, None, None, None)
Beispiel #3
0
    def parse(self, data: bytes) -> X224PDU:
        """
        Read the byte stream and return a corresponding X224PDU
        """
        length = Uint8.unpack(data[0])
        header = Uint8.unpack(data[1]) >> 4

        if header in list(X224PDUType):
            header = X224PDUType(header)

        if length < 2:
            raise ParsingError(
                "Invalid X224 length indicator: indicator = %d, expected at least 2 bytes"
                % length)
        if len(data) < length:
            raise ParsingError(
                "Invalid X224 length indicator: indicator = %d, length = %d" %
                (length, len(data)))

        if header not in self.parsers:
            raise UnknownPDUTypeError(
                "Trying to parse unknown X224 PDU type: %s" %
                (header if header in X224PDUType else hex(header)), header)

        return self.parsers[header](data, length)
Beispiel #4
0
    def parseBitmapCapability(self, data: bytes) -> BitmapCapability:
        """
        https://msdn.microsoft.com/en-us/library/cc240554.aspx
        :param data: Raw data starting after lengthCapability
        """
        stream = BytesIO(data)
        preferredBitsPerPixel = Uint16LE.unpack(stream.read(2))
        receive1bitPerPixel = Uint16LE.unpack(stream.read(2))
        receive4bitPerPixel = Uint16LE.unpack(stream.read(2))
        receive8bitPerPixel = Uint16LE.unpack(stream.read(2))
        desktopWidth = Uint16LE.unpack(stream.read(2))
        desktopHeight = Uint16LE.unpack(stream.read(2))
        stream.read(2)  # pad2octets
        desktopResizeFlag = Uint16LE.unpack(stream.read(2))
        bitmapCompressionFlag = Uint16LE.unpack(stream.read(2))
        highColorFlags = Uint8.unpack(stream.read(1))
        drawingFlags = Uint8.unpack(stream.read(1))
        multipleRectangleSupport = Uint16LE.unpack(stream.read(2))
        # ignoring pad2octetsB

        capability = BitmapCapability(preferredBitsPerPixel,
                                      receive1bitPerPixel, receive4bitPerPixel,
                                      receive8bitPerPixel, desktopWidth,
                                      desktopHeight, desktopResizeFlag,
                                      bitmapCompressionFlag, highColorFlags,
                                      drawingFlags, multipleRectangleSupport)
        capability.rawData = data
        return capability
Beispiel #5
0
    def parse(self, data: bytes) -> FastPathOutputEvent:
        stream = BytesIO(data)
        header = Uint8.unpack(stream)

        compressionFlags = None

        if self.isCompressed(header):
            compressionFlags = Uint8.unpack(stream)

        size = Uint16LE.unpack(stream)

        eventType = header & 0xf
        fragmentation = header & 0b00110000 != 0

        if fragmentation:
            log.debug(
                "Fragmentation is present in output fastpath event packets."
                " Not parsing it and saving to FastPathOutputUpdateEvent.")
            return FastPathOutputEvent(header,
                                       compressionFlags,
                                       payload=stream.read(size))

        if eventType == FastPathOutputType.FASTPATH_UPDATETYPE_BITMAP:
            return self.parseBitmapEventRaw(stream, header, compressionFlags,
                                            size)
        elif eventType == FastPathOutputType.FASTPATH_UPDATETYPE_ORDERS:
            return self.parseOrdersEvent(stream, header, compressionFlags,
                                         size)

        read = stream.read(size)
        return FastPathOutputEvent(header, compressionFlags, read)
Beispiel #6
0
    def parse(self, data: bytes) -> FastPathOutputEvent:
        """
        Parse TS_FP_UPDATE.

        https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/a1c4caa8-00ed-45bb-a06e-5177473766d3
        """
        stream = BytesIO(data)
        header = Uint8.unpack(stream)

        # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/a1c4caa8-00ed-45bb-a06e-5177473766d3
        updateCode = header & 0xf
        # fragmentation = (header & 0b00110000) >> 4
        compressionFlags = Uint8.unpack(stream) if self.isCompressed(
            header) else None
        size = Uint16LE.unpack(stream)

        # Dispatch to the appropriate sub-parser.
        if updateCode == FastPathOutputType.FASTPATH_UPDATETYPE_BITMAP:
            return self.parseBitmapEventRaw(stream, header, compressionFlags,
                                            size)
        elif updateCode == FastPathOutputType.FASTPATH_UPDATETYPE_ORDERS:
            return self.parseOrdersEvent(stream, header, compressionFlags,
                                         size)

        read = stream.read(size)
        return FastPathOutputEvent(header, compressionFlags, read)
Beispiel #7
0
    def parseLength(self, stream: BytesIO) -> int:
        length = Uint8.unpack(stream)

        if length & 0x80 != 0:
            length = ((length & 0x7f) << 8) | Uint8.unpack(stream)

        return length
Beispiel #8
0
 def parseShareDataHeader(self, stream: BytesIO, controlHeader: ShareControlHeader):
     shareID = Uint32LE.unpack(stream)
     stream.read(1)
     streamID = Uint8.unpack(stream)
     uncompressedLength = Uint16LE.unpack(stream)
     pduSubtype = Uint8.unpack(stream)
     compressedType = Uint8.unpack(stream)
     compressedLength = Uint16LE.unpack(stream)
     return ShareDataHeader(controlHeader.pduType, controlHeader.version, controlHeader.source, shareID, streamID, uncompressedLength, SlowPathDataType(pduSubtype), compressedType, compressedLength)
Beispiel #9
0
    def parse(self, data: bytes) -> FastPathPDU:
        stream = BytesIO(data)
        header = Uint8.unpack(stream)
        eventCount = self.parseEventCount(header)
        pduLength = self.parseLength(stream)

        if eventCount == 0:
            eventCount = Uint8.unpack(stream)

        data = stream.read(pduLength - stream.tell())
        events = self.parseEvents(data)
        return FastPathPDU(header, events)
Beispiel #10
0
    def parse(self, data: bytes) -> TPKTPDU:
        """
        Read the byte stream and return a TPKTPDU
        """

        _version = Uint8.unpack(data[0:1])
        _padding = Uint8.unpack(data[1:2])
        length = Uint16BE.unpack(data[2:4])
        payload = data[4:length]

        if len(payload) != length - 4:
            raise ParsingError("Payload is too short for TPKT length field")

        return TPKTPDU(payload)
Beispiel #11
0
    def parseLengthWithSocket(self, socket):
        """
        Same as parseLength, but with a network socket.
        :type socket: socket.socket
        """
        data = socket.recv(1)
        length = Uint8.unpack(data)

        if length & 0x80 != 0:
            data2 = socket.recv(1)
            data += data2
            length = ((length & 0x7f) << 8) | Uint8.unpack(data2)

        return data, length
Beispiel #12
0
    def parse(self, data: bytes) -> NegotiationResponsePDU:
        """
        Parse a negotiation response.
        :param data: the response data.
        """
        stream = BytesIO(data)

        if len(data) == 8:
            type = Uint8.unpack(stream)
            flags = Uint8.unpack(stream)
            length = Uint16LE.unpack(stream)
            selectedProtocols = Uint32LE.unpack(stream)
            return NegotiationResponsePDU(type, flags, selectedProtocols)
        else:
            return NegotiationResponsePDU(None, None, None)
Beispiel #13
0
    def parseConnectionPDU(self, data: bytes, length: int,
                           name: str) -> Tuple[int, int, int, bytes]:
        """
        Parse the provided data to extract common information contained in Connection Request, Connection Confirm and Disconnect Request PDUs.
        :param data: bytes to parse.
        :param length: Length of the Connection PDU.
        :param name: For debugging purposes: the name of the connection PDU (like "Connection Request").
        :return: A tuple of the information we find in both connection PDUs: (source, destination, options, payload)
        """

        if length < 6:
            raise ParsingError(
                "Invalid X244 %s length indicator: indicator = %d, expected at least 6 bytes"
                % (name, 6))

        destination = Uint16BE.unpack(data[2:4])
        source = Uint16BE.unpack(data[4:6])
        options = Uint8.unpack(data[6])
        payload = data[7:]

        if len(payload) != length - 6:
            raise ParsingError(
                "Invalid X224 %s payload length: expected = %d, length = %d" %
                (name, length - 6, len(payload)))

        return source, destination, options, payload
Beispiel #14
0
    def getEventLength(self, event: FastPathOutputUpdateEvent):

        if isinstance(event, bytes):
            header = Uint8.unpack(event[0])
            if self.isCompressed(header):
                return Uint16LE.unpack(event[2: 4]) + 4
            else:
                return Uint16LE.unpack(event[1: 3]) + 3

        size = 3

        if self.isCompressed(event.header):
            size += 1

        if isinstance(event, FastPathOrdersEvent):
            size += 2 + len(event.orderData)
        elif isinstance(event, FastPathBitmapEvent):
            size += len(event.payload)
        elif isinstance(event, FastPathOutputUpdateEvent):
            length = len(event.payload) + 3
            if event.compressionFlags is not None:
                length += 1
            return length

        return size
Beispiel #15
0
    def parseDirectoryControlRequest(self, deviceID: int, fileID: int,
                                     completionID: int, minorFunction: int,
                                     stream: BytesIO) -> DeviceIORequestPDU:
        self.minorFunctionsForParsingResponse[completionID] = MinorFunction(
            minorFunction)

        if minorFunction == MinorFunction.IRP_MN_NOTIFY_CHANGE_DIRECTORY:
            return DeviceIORequestPDU(deviceID, fileID, completionID,
                                      MajorFunction.IRP_MJ_DIRECTORY_CONTROL,
                                      minorFunction, stream.read())
        else:
            informationClass = FileSystemInformationClass(
                Uint32LE.unpack(stream))
            initialQuery = Uint8.unpack(stream)
            pathLength = Uint32LE.unpack(stream)
            stream.read(23)

            path = stream.read(pathLength)
            path = decodeUTF16LE(path)[:-1]

            self.informationClassForParsingResponse[
                completionID] = informationClass
            return DeviceQueryDirectoryRequestPDU(deviceID, fileID,
                                                  completionID,
                                                  informationClass,
                                                  initialQuery, path)
Beispiel #16
0
    def parseData(self, data, length):
        """
        Parse a Data PDU from the raw bytes
        :type data: bytes
        :param length: The length in bytes of the Data PDU.
        :return: X224DataPDU
        """

        if length != 2:
            raise ParsingError("Invalid X224 Data PDU length indicator: expected = 2, indicator = %d" % length)

        code = Uint8.unpack(data[1]) & 0xf
        sequence = Uint8.unpack(data[2])
        payload = data[3 :]

        return X224DataPDU(code & 1 == 1, sequence & 0x80 == 0x80, payload)
Beispiel #17
0
    def parse(self, data: bytes) -> MCSPDU:
        """
        Parse raw data bytes into a MCSPDU
        :param data: raw bytes to parse
        """

        stream = BytesIO(data)
        header = Uint8.unpack(stream.read(1))
        if header == ber.Class.BER_CLASS_APPL | ber.PC.BER_CONSTRUCT | ber.Tag.BER_TAG_MASK:
            header = Uint8.unpack(stream.read(1))
        else:
            header = header >> 2

        if header not in self.parsers:
            raise UnknownPDUTypeError("Trying to parse unknown MCS PDU type %s" % header, header)

        return self.parsers[header](stream)
Beispiel #18
0
    def parse(self, data):
        """
        Read the provided byte stream and return the corresponding RDPLicensingPDU.
        :type data: bytes
        :return: RDPLicensingPDU
        """

        stream = BytesIO(data)
        header = Uint8.unpack(stream)
        flags = Uint8.unpack(stream)
        size = Uint16LE.unpack(stream)

        if header not in self.parsers:
            raise UnknownPDUTypeError("Trying to parse unknown license PDU",
                                      header)

        return self.parsers[header](stream, flags)
Beispiel #19
0
 def parseSuppressOutput(self, stream: BytesIO, header):
     allowDisplayUpdates = Uint8.unpack(stream)
     stream.read(3)
     left = Uint16LE.unpack(stream)
     top = Uint16LE.unpack(stream)
     right = Uint16LE.unpack(stream)
     bottom = Uint16LE.unpack(stream)
     return SuppressOutputPDU(header, allowDisplayUpdates, left, top, right, bottom)
Beispiel #20
0
    def isCompletePDU(self, data: bytes) -> bool:
        if len(data) == 1:
            return False

        if Uint8.unpack(data[1]) & 0x80 != 0 and len(data) == 2:
            return False

        return len(data) >= self.getPDULength(data)
Beispiel #21
0
 def isTPKTPDU(self, data):
     """
     Check if the PDU in data is a TPKT PDU.
     :param data: the data.
     :type data: bytes
     :return: bool
     """
     return Uint8.unpack(data[0]) == 3
Beispiel #22
0
    def parse(self, data):
        stream = BytesIO(data)
        header = Uint32LE.unpack(stream)

        if header & SecurityFlags.SEC_EXCHANGE_PKT != 0:
            return self.parseSecurityExchange(stream, header)

        length = Uint16LE.unpack(stream)
        version = Uint8.unpack(stream)
        padLength = Uint8.unpack(stream)
        signature = stream.read(8)
        payload = stream.read()

        if header & SecurityFlags.SEC_ENCRYPT != 0:
            payload = self.crypter.decrypt(payload)
            self.crypter.addDecryption()

        return SecurityPDU(header, payload)
Beispiel #23
0
 def readChannelId(self, stream: BytesIO, cbid: int):
     if cbid == CbId.ONE_BYTE:
         return Uint8.unpack(stream)
     elif cbid == CbId.TWO_BYTE:
         return Uint16LE.unpack(stream)
     elif cbid == CbId.FOUR_BYTES:
         return Uint16LE.unpack(stream)
     else:
         raise ValueError(f"Invalid channel id length: {cbid}")
Beispiel #24
0
    def parse(self, data: bytes) -> FastPathPDU:
        stream = BytesIO(data)
        header = Uint8.unpack(stream)
        eventCount = self.parseEventCount(header)
        pduLength = self.parseLength(stream)
        _signature = stream.read(8)

        if eventCount == 0:
            eventCount = Uint8.unpack(stream)

        data = stream.read(pduLength - stream.tell())

        if header & FastPathSecurityFlags.FASTPATH_OUTPUT_ENCRYPTED != 0:
            data = self.crypter.decrypt(data)
            self.crypter.addDecryption()

        events = self.parseEvents(data)
        return FastPathPDU(header, events)
Beispiel #25
0
 def parseConnectionConfirm(self, data, length):
     """
     Parse a ConnectionConfirm PDU from the raw bytes
     :type data: bytes
     :param length: The length in bytes of the Connection Confirm PDU.
     :return: X224ConnectionConfirmPDU
     """
     credit = Uint8.unpack(data[1]) & 0xf
     destination, source, options, payload = self.parseConnectionPDU(data, length, "Connection Confirm")
     return X224ConnectionConfirmPDU(credit, destination, source, options, payload)
Beispiel #26
0
 def recv(self, data: bytes):
     """
     Parses data to make a RDPPlayerMessagePDU and calls the observer with it.
     """
     stream = BytesIO(data)
     type = PlayerMessageType(Uint8.unpack(stream))
     timestamp = Uint64LE.unpack(stream)
     payload = stream.read()
     pdu = PlayerMessagePDU(type, timestamp, payload)
     self.pduReceived(pdu, forward=False)
Beispiel #27
0
    def parse(s: BytesIO) -> 'StreamBitmapNext':
        self = StreamBitmapNext()

        self.flags = Uint8.unpack(s)
        self.bitmapType = Uint16LE.unpack(s)

        blockSize = Uint16LE.unpack(s)
        self.data = s.read(blockSize)

        return self
Beispiel #28
0
 def parse(self, data):
     stream = BytesIO(data)
     eventHeader = Uint8.unpack(stream.read(1))
     eventCode = (eventHeader & 0b11100000) >> 5
     eventFlags= eventHeader & 0b00011111
     if eventCode == FastPathInputType.FASTPATH_INPUT_EVENT_SCANCODE:
         return self.parseScanCode(eventFlags, eventHeader, stream)
     elif eventCode == FastPathInputType.FASTPATH_INPUT_EVENT_MOUSE:
         return self.parseMouseEvent(data, eventHeader)
     return FastPathEventRaw(data)
Beispiel #29
0
    def parse(s: BytesIO) -> 'StreamBitmapFirst':
        self = StreamBitmapFirst()

        self.flags = Uint8.unpack(s)
        self.bpp = Uint8.unpack(s)

        self.type = Uint16LE.unpack(s)
        self.width = Uint16LE.unpack(s)
        self.height = Uint16LE.unpack(s)

        self.totalSize = 0
        if self.flags & STREAM_BITMAP_V2:
            self.totalSize = Uint32LE.unpack(s)
        else:
            self.totalSize = Uint16LE.unpack(s)

        blockSize = Uint16LE.unpack(s)
        self.data = s.read(blockSize)

        return self
Beispiel #30
0
    def parse(s: BytesIO) -> 'GdiPlusCacheEnd':
        self = GdiPlusCacheEnd()

        self.flags = Uint8.unpack(s)
        self.cacheType = Uint16LE.unpack(s)
        self.cacheIndex = Uint16LE.unpack(s)
        cbSize = Uint16LE.unpack(s)
        self.totalSize = Uint32LE.unpack(s)
        self.data = s.read(cbSize)

        return self