def doParse(self, data: bytes) -> GCCPDU: """ Parses the raw data bytes into a GCCPDU :param data: PDU data. """ stream = BytesIO(data) tag = per.readChoice(stream) if tag != 0: raise ParsingError("Expected object tag (0), got %d instead" % tag) oid = per.readObjectIdentifier(stream) if oid != GCCParser.T124_02_98_OID: raise ParsingError("Invalid object identifier: %r, expected %r" % (oid, GCCParser.T124_02_98_OID)) _length = per.readLength(stream) header = per.readChoice(stream) if header not in self.parsers: raise UnknownPDUTypeError( "Trying to parse unknown GCC PDU type %s" % header, header) pdu = self.parsers[header](stream) return pdu
def writeData(self, stream: BytesIO, pdu): if pdu.header.subtype not in self.dataWriters: raise UnknownPDUTypeError( "Trying to write unknown slow-path data type: %s" % pdu.header.subtype, pdu.header.subtype) self.dataWriters[pdu.header.subtype](stream, pdu)
def write(self, pdu: X224PDU) -> bytes: """ Encode the provided X224 pdu into a byte stream. :return: The bytes to send to the previous layer """ stream = BytesIO() if pdu.header == X224PDUType.X224_TPDU_DATA: length = 2 elif pdu.header in [ X224PDUType.X224_TPDU_CONNECTION_REQUEST, X224PDUType.X224_TPDU_CONNECTION_CONFIRM, X224PDUType.X224_TPDU_DISCONNECT_REQUEST ]: length = len(pdu.payload) + 6 elif pdu.header == X224PDUType.X224_TPDU_ERROR: length = len(pdu.payload) + 4 else: raise UnknownPDUTypeError( "Trying to write unknown X224 PDU type: %s" % (pdu.header if pdu.header in X224PDUType else hex(pdu.header)), pdu.header) stream.write(Uint8.pack(length)) self.writers[pdu.header](stream, pdu) stream.write(pdu.payload) return stream.getvalue()
def parseData(self, stream: BytesIO, header): header = self.parseShareDataHeader(stream, header) if header.subtype not in self.dataParsers: raise UnknownPDUTypeError("Trying to parse unknown slow-path data type: %s" % header.subtype, header.subtype) return self.dataParsers[header.subtype](stream, header)
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)
def write(self, pdu: SlowPathPDU) -> bytes: """ Encode an RDP Data PDU instance to bytes. """ stream = BytesIO() substream = BytesIO() if isinstance(pdu, DemandActivePDU): headerWriter = self.writeShareControlHeader self.writeDemandActive(substream, pdu) elif isinstance(pdu, ConfirmActivePDU): headerWriter = self.writeShareControlHeader self.writeConfirmActive(substream, pdu) elif pdu.header.pduType == SlowPathPDUType.DATA_PDU: headerWriter = self.writeShareDataHeader self.writeData(substream, pdu) else: raise UnknownPDUTypeError( "Trying to write unknown slow-path PDU type: %s" % pdu.header.pduType, pdu.header.pduType) substream = substream.getvalue() headerWriter(stream, pdu.header, len(substream)) stream.write(substream) return stream.getvalue()
def write(self, pdu: MCSPDU) -> bytes: """ Encode an MCS PDU into raw bytes :param pdu: the MCSPDU to encode :return: The raw bytes to send """ if pdu.header not in self.writers: raise UnknownPDUTypeError( "Trying to write unknown MCS PDU type %s" % pdu.header, pdu.header) stream = BytesIO() if pdu.header in [ MCSPDUType.CONNECT_INITIAL, MCSPDUType.CONNECT_RESPONSE ]: stream.write( Uint8.pack(ber.Class.BER_CLASS_APPL | ber.PC.BER_CONSTRUCT | ber.Tag.BER_TAG_MASK)) stream.write(Uint8.pack(pdu.header)) else: stream.write( Uint8.pack((pdu.header << 2) | self.headerOptions[pdu.header])) self.writers[pdu.header](stream, pdu) return stream.getvalue()
def writeStructure(self, stream: BytesIO, data: typing.Union[ClientCoreData, ClientNetworkData, ClientSecurityData, ClientClusterData]): if data.header not in self.writers: raise UnknownPDUTypeError("Trying to write unknown Client Data structure %s" % data.header, data.header) substream = BytesIO() self.writers[data.header](substream, data) substream = substream.getvalue() stream.write(Uint16LE.pack(data.header)) stream.write(Uint16LE.pack(len(substream) + 4)) stream.write(substream)
def parse(self, data: bytes) -> PDU: """ Decode a data PDU from bytes. :return: an instance of an RDP Data PDU class. """ stream = BytesIO(data) header = self.parseShareControlHeader(stream) if header.pduType not in self.parsers: raise UnknownPDUTypeError("Trying to parse unknown slow-path PDU type: %s" % header.pduType, header.pduType) return self.parsers[header.pduType](stream, header)
def writeStructure(self, stream, data): if data.header not in self.writers: raise UnknownPDUTypeError("Trying to write unknown Client Data structure %s" % data.header, data.header) substream = BytesIO() self.writers[data.header](substream, data) substream = substream.getvalue() stream.write(Uint16LE.pack(data.header)) stream.write(Uint16LE.pack(len(substream) + 4)) stream.write(substream)
def parseStructure(self, stream): header = Uint16LE.unpack(stream) length = Uint16LE.unpack(stream) - 4 data = stream.read(length) if len(data) != length: raise ParsingError("Client Data length field does not match actual size") substream = BytesIO(data) if header not in self.parsers: raise UnknownPDUTypeError("Trying to parse unknown client data structure %s" % header, header) return self.parsers[header](substream)
def parseStructure(self, stream: BytesIO) -> typing.Union[ClientCoreData, ClientNetworkData, ClientSecurityData, ClientClusterData]: header = Uint16LE.unpack(stream) length = Uint16LE.unpack(stream) - 4 data = stream.read(length) if len(data) != length: raise ParsingError("Client Data length field does not match actual size") substream = BytesIO(data) if header not in self.parsers: raise UnknownPDUTypeError("Trying to parse unknown client data structure %s" % header, header) return self.parsers[header](substream)
def write(self, pdu: X224PDU) -> bytes: """ Encode the provided X224 pdu into a byte stream. :return: The bytes to send to the previous layer """ stream = BytesIO() stream.write(Uint8.pack(pdu.length)) if pdu.header not in self.writers: raise UnknownPDUTypeError("Trying to write unknown X224 PDU type: %s" % (pdu.header if pdu.header in X224PDUType else hex(pdu.header)), pdu.header) self.writers[pdu.header](stream, pdu) stream.write(pdu.payload) return stream.getvalue()
def writeStructure(self, stream: BytesIO, data: typing.Union[ServerCoreData, ServerSecurityData, ServerNetworkData]): """ :param stream: BytesIO to write to :param data: The structure to write (ex: ServerCoreData) """ if data.header not in self.writers: raise UnknownPDUTypeError("Trying to write unknown Server Data structure %s" % data.header, data.header) substream = BytesIO() self.writers[data.header](substream, data) substream = substream.getvalue() stream.write(Uint16LE.pack(data.header)) stream.write(Uint16LE.pack(len(substream) + 4)) stream.write(substream)
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)
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)
def write(self, pdu: LicensingPDU) -> bytes: """ Encode a RDPLicensingPDU into a byte stream to send to the previous layer. """ stream = BytesIO() stream.write(Uint8.pack(pdu.header)) stream.write(Uint8.pack(pdu.flags)) substream = BytesIO() if isinstance(pdu, LicenseErrorAlertPDU): self.writeErrorAlert(substream, pdu) else: raise UnknownPDUTypeError( "Trying to write unknown RDP Licensing PDU: {}".format( pdu.header), pdu.header) stream.write(Uint16LE.pack(len(substream.getvalue()) + 4)) stream.write(substream.getvalue()) return stream.getvalue()
def write(self, pdu: GCCPDU) -> bytes: """ Encode a GCC PDU to bytes. :param pdu: gcc PDU. """ if pdu.header not in self.writers: raise UnknownPDUTypeError("Trying to write unknown GCC PDU type %s" % pdu.header, pdu.header) stream = BytesIO() stream.write(per.writeChoice(0)) stream.write(per.writeObjectIdentifier(GCCParser.T124_02_98_OID)) # Normally this should be len(pdu.payload) + 14, but Windows seems to always send 0x2a. This value is also # accepted by Wireshark. stream.write(per.writeLength(0x2a)) stream.write(per.writeChoice(pdu.header)) self.writers[pdu.header](stream, pdu) return stream.getvalue()
def write(self, pdu): """ Encode a GCC PDU to bytes. :param pdu: gcc PDU. :type pdu: GCCPDU :return: str """ if pdu.header not in self.writers: raise UnknownPDUTypeError( "Trying to write unknown GCC PDU type %s" % pdu.header, pdu.header) stream = BytesIO() stream.write(per.writeChoice(0)) stream.write(per.writeObjectIdentifier(GCCParser.T124_02_98_OID)) stream.write(per.writeLength(len(pdu.payload) + 14)) stream.write(per.writeChoice(pdu.header)) self.writers[pdu.header](stream, pdu) return stream.getvalue()
def onUnknownHeader(self, pdu): """ Method called when a PDU with an unknown header is received """ raise UnknownPDUTypeError( "Unknown PDU header received: 0x%2lx" % pdu.header, type(pdu))