def writeInput(self, stream: BytesIO, pdu): Uint16LE.pack(len(pdu.events), stream) stream.write(b"\x00" * 2) parser = SlowPathInputParser() for event in pdu.events: stream.write(parser.write(event))
def writeCapabilitySets(self, capabilitySets: List[Capability], substream): for capability in capabilitySets: # Since the general capability is fully parsed, write it back..... if isinstance(capability, GeneralCapability): self.writeGeneralCapability(capability, substream) elif isinstance(capability, OrderCapability): self.writeOrderCapability(capability, substream) elif isinstance(capability, BitmapCapability): self.writeBitmapCapability(capability, substream) elif isinstance(capability, SurfaceCommandsCapability): self.writeSurfaceCommandsCapability(capability, substream) elif isinstance(capability, OffscreenBitmapCacheCapability): self.writeOffscreenCacheCapability(capability, substream) elif isinstance(capability, VirtualChannelCapability): self.writeVirtualChannelCapability(capability, substream) elif isinstance(capability, PointerCapability): self.writePointerCapability(capability, substream) elif capability.capabilityType == CapabilityType.CAPSETTYPE_MULTIFRAGMENTUPDATE \ and isinstance(capability, MultifragmentUpdateCapability): self.writeMultiFragmentUpdateCapability(capability, substream) # Every other capability is parsed minimally. else: Uint16LE.pack(capability.capabilityType, substream) Uint16LE.pack(len(capability.rawData) + 4, substream) substream.write(capability.rawData)
def writeClientCoreData(self, stream: BytesIO, core: ClientCoreData): stream.write(Uint32LE.pack(core.version)) stream.write(Uint16LE.pack(core.desktopWidth)) stream.write(Uint16LE.pack(core.desktopHeight)) stream.write(Uint16LE.pack(core.colorDepth)) stream.write(Uint16LE.pack(core.sasSequence)) stream.write(Uint32LE.pack(core.keyboardLayout)) stream.write(Uint32LE.pack(core.clientBuild)) stream.write(encodeUTF16LE(core.clientName).ljust(32, b"\x00")[: 32]) stream.write(Uint32LE.pack(core.keyboardType)) stream.write(Uint32LE.pack(core.keyboardSubType)) stream.write(Uint32LE.pack(core.keyboardFunctionKey)) stream.write(core.imeFileName) try: stream.write(Uint16LE.pack(core.postBeta2ColorDepth)) stream.write(Uint16LE.pack(core.clientProductId)) stream.write(Uint32LE.pack(core.serialNumber)) stream.write(Uint16LE.pack(core.highColorDepth)) stream.write(Uint16LE.pack(core.supportedColorDepths)) stream.write(Uint16LE.pack(core.earlyCapabilityFlags)) stream.write(encodeUTF16LE(core.clientDigProductId).ljust(64, b"\x00")[: 64]) stream.write(Uint8.pack(core.connectionType)) stream.write(b"\x00") stream.write(Uint32LE.pack(core.serverSelectedProtocol)) stream.write(Uint32LE.pack(core.desktopPhysicalWidth)) stream.write(Uint32LE.pack(core.desktopPhysicalHeight)) stream.write(Uint16LE.pack(core.desktopOrientation)) stream.write(Uint32LE.pack(core.desktopScaleFactor)) stream.write(Uint32LE.pack(core.deviceScaleFactor)) except struct.error: # We tried to write an optional field which was not present. Stop writing beyond this point. pass
def writeCapabilities(self, pdu: DeviceRedirectionCapabilitiesPDU, stream: BytesIO): Uint16LE.pack(len(pdu.capabilities), stream) stream.write(b"\x00" * 2) # Padding for capability in pdu.capabilities.values(): self.writeSingleCapability(capability, stream)
def write(self, pdu): """ Write a negotiation request. :param pdu: the request PDU. :type pdu: NegotiationRequestPDU :return: str """ stream = BytesIO() if pdu.cookie is not None: stream.write(pdu.cookie + b"\r\n") if pdu.flags is not None and pdu.requestedProtocols is not None: Uint8.pack(NegotiationType.TYPE_RDP_NEG_REQ, stream) Uint8.pack(pdu.flags, stream) Uint16LE.pack(8, stream) Uint32LE.pack(pdu.requestedProtocols, stream) if pdu.correlationFlags is not None and pdu.correlationID is not None: Uint8.pack(NegotiationType.TYPE_RDP_CORRELATION_INFO, stream) Uint8.pack(pdu.correlationFlags, stream) Uint16LE.pack(36, stream) stream.write(pdu.correlationID) stream.write(b"\x00" * 16) return stream.getvalue()
def writeMultiFragmentUpdateCapability(self, capability: MultifragmentUpdateCapability, stream: BytesIO): substream = BytesIO() Uint16LE.pack(capability.capabilityType, stream) Uint32LE.pack(capability.maxRequestSize, substream) Uint16LE.pack(len(substream.getvalue()) + 4, stream) stream.write(substream.getvalue())
def write(self, pdu): """ Encode a Client Info PDU to bytes. :param pdu: the Client Info PDU. :type pdu: ClientInfoPDU :return: str """ stream = BytesIO() stream.write(Uint32LE.pack(pdu.codePage)) stream.write(Uint32LE.pack(pdu.flags)) isUnicode = pdu.flags & ClientInfoFlags.INFO_UNICODE != 0 hasNullBytes = pdu.codePage == 1252 or isUnicode nullByteCount = 1 if hasNullBytes else 0 unicodeMultiplier = 2 if isUnicode else 0 domain = pdu.domain + "\x00" * nullByteCount username = pdu.username + "\x00" * nullByteCount password = pdu.password + "\x00" * nullByteCount alternateShell = pdu.alternateShell + "\x00" * nullByteCount workingDir = pdu.workingDir + "\x00" * nullByteCount if isUnicode: domain = encodeUTF16LE(domain) username = encodeUTF16LE(username) password = encodeUTF16LE(password) alternateShell = encodeUTF16LE(alternateShell) workingDir = encodeUTF16LE(workingDir) else: domain = domain.encode() username = username.encode() password = password.encode() alternateShell = alternateShell.encode() workingDir = workingDir.encode() domainLength = len(domain) - nullByteCount * unicodeMultiplier usernameLength = len(username) - nullByteCount * unicodeMultiplier passwordLength = len(password) - nullByteCount * unicodeMultiplier alternateShellLength = len( alternateShell) - nullByteCount * unicodeMultiplier workingDirLength = len(workingDir) - nullByteCount * unicodeMultiplier stream.write(Uint16LE.pack(domainLength)) stream.write(Uint16LE.pack(usernameLength)) stream.write(Uint16LE.pack(passwordLength)) stream.write(Uint16LE.pack(alternateShellLength)) stream.write(Uint16LE.pack(workingDirLength)) stream.write(domain) stream.write(username) stream.write(password) stream.write(alternateShell) stream.write(workingDir) if pdu.extraInfo is not None: extraInfoBytes = self.writeExtraInfo(pdu.extraInfo) stream.write(extraInfoBytes) return stream.getvalue()
def writeSurfaceCommandsCapability(self, capability: SurfaceCommandsCapability, stream: BytesIO): substream = BytesIO() Uint16LE.pack(capability.capabilityType, stream) Uint32LE.pack(capability.cmdFlags, substream) Uint32LE.pack(capability.reserved, substream) Uint16LE.pack(len(substream.getvalue()) + 4, stream) stream.write(substream.getvalue())
def write(self, pdu: DeviceRedirectionPDU) -> bytes: stream = BytesIO() Uint16LE.pack(pdu.component, stream) Uint16LE.pack(pdu.packetId, stream) if pdu.packetId in self.writers.keys(): self.writers[pdu.packetId](pdu, stream) else: stream.write(pdu.payload) return stream.getvalue()
def writeBody(self, stream: BytesIO, pdu: FastPathPDU): bodyStream = BytesIO() SignedFastPathParser.writeBody(self, bodyStream, pdu) body = bodyStream.getvalue() Uint16LE.pack(0x10, stream) Uint8.pack(FIPSVersion.TSFIPS_VERSION1, stream) Uint8.pack(self.crypter.getPadLength(self.eventData), stream) stream.write(body)
def writeChannelId(self, stream: BytesIO, cbid: int, channelId: int): if cbid == CbId.ONE_BYTE: return Uint8.pack(channelId, stream) elif cbid == CbId.TWO_BYTE: return Uint16LE.pack(channelId, stream) elif cbid == CbId.FOUR_BYTES: return Uint16LE.pack(channelId, stream) else: raise ValueError(f"Invalid channel id length: {cbid}")
def write(self, input): stream = BytesIO() Uint32LE.pack(input.eventTime, stream) Uint16LE.pack(input.messageType, stream) if input.messageType not in self.writers: raise WritingError("Invalid input message type") self.writers[input.messageType](stream, input) return stream.getvalue()
def writePointerCapability(self, capability: PointerCapability, stream: BytesIO): substream = BytesIO() Uint16LE.pack(capability.capabilityType, stream) Uint16LE.pack(capability.colorPointerFlag, substream) Uint16LE.pack(capability.colorPointerCacheSize, substream) Uint16LE.pack(capability.pointerCacheSize, substream) Uint16LE.pack(len(substream.getvalue()) + 4, stream) stream.write(substream.getvalue())
def writeSingleCapability(self, capability: DeviceRedirectionCapability, stream: BytesIO): Uint16LE.pack(capability.capabilityType, stream) substream = BytesIO() if isinstance(capability, DeviceRedirectionGeneralCapability): self.writeGeneralCapability(capability, substream) else: substream.write(capability.payload) Uint16LE.pack(len(substream.getvalue()) + 8, stream) Uint32LE.pack(capability.version, stream) stream.write(substream.getvalue())
def writeServerNetworkData(self, stream: BytesIO, data: ServerNetworkData): """ https://msdn.microsoft.com/en-us/library/cc240522.aspx """ stream.write(Uint16LE.pack(data.mcsChannelID)) stream.write(Uint16LE.pack(len(data.channels))) for channel in data.channels: stream.write(Uint16LE.pack(channel)) if len(data.channels) % 2 != 0: stream.write(Uint16LE.pack(0)) # Write 2 empty bytes so we keep a multiple of 4.
def write(self, pdu: PlayerMessagePDU) -> bytes: stream = BytesIO() # 18 bytes of header + the payload Uint64LE.pack(len(pdu.payload) + 18, stream) Uint16LE.pack(pdu.header, stream) Uint64LE.pack(pdu.timestamp, stream) stream.write(pdu.payload) return stream.getvalue()
def writeColorEvent(self, stream, event): Uint16LE.pack(event.cacheIndex, stream) Uint32LE.pack(event.hotSpot, stream) Uint16LE.pack(event.width, stream) Uint16LE.pack(event.height, stream) Uint16LE.pack(len(event.andMask), stream) Uint16LE.pack(len(event.xorMask), stream) stream.write(event.xorMask) stream.write(event.andMask) stream.write(b"\x00")
def writeErrorAlert(self, stream, pdu): """ Writes LicenceErrorAlertPDU-specific fields to stream :type stream: BytesIO :type pdu: LicenseErrorAlertPDU """ stream.write(Uint32LE.pack(pdu.errorCode)) stream.write(Uint32LE.pack(pdu.stateTransition)) stream.write(Uint16LE.pack(pdu.blob.type)) stream.write(Uint16LE.pack(0))
def write(self, event): stream = BytesIO() Uint16LE.pack(event.messageType, stream) stream.write(b"\x00" * 2) if event.messageType not in self.writers: raise ParsingError("Trying to write invalid pointer event type") self.writers[event.messageType](stream, event) return stream.getvalue()
def writeVirtualChannelCapability(self, capability: VirtualChannelCapability, stream: BytesIO): substream = BytesIO() Uint16LE.pack(capability.capabilityType, stream) Uint32LE.pack(capability.flags, substream) if capability.vcChunkSize is not None: Uint32LE.pack(capability.vcChunkSize, substream) Uint16LE.pack(len(substream.getvalue()) + 4, stream) stream.write(substream.getvalue())
def write(self, pdu: DeviceRedirectionPDU) -> bytes: stream = BytesIO() Uint16LE.pack(pdu.component, stream) Uint16LE.pack(pdu.packetID, stream) if pdu.component == DeviceRedirectionComponent.RDPDR_CTYP_CORE and pdu.packetID in self.writers.keys(): self.writers[pdu.packetID](pdu, stream) else: stream.write(pdu.payload) return stream.getvalue()
def writeCapability(self, capability: DeviceRedirectionCapability, stream: BytesIO): Uint16LE.pack(capability.capabilityType, stream) substream = BytesIO() if capability.capabilityType in self.capabilityWriters: self.capabilityWriters[capability.capabilityType](capability, substream) else: substream.write(capability.payload) Uint16LE.pack(len(substream.getvalue()) + 8, stream) Uint32LE.pack(capability.version, stream) stream.write(substream.getvalue())
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 writeGeneralCapability(self, capability: DeviceRedirectionGeneralCapability, stream: BytesIO): Uint32LE.pack(capability.osType, stream) Uint32LE.pack(capability.osVersion, stream) Uint16LE.pack(capability.protocolMajorVersion, stream) Uint16LE.pack(capability.protocolMinorVersion, stream) Uint32LE.pack(capability.ioCode1, stream) Uint32LE.pack(capability.ioCode2, stream) Uint32LE.pack(capability.extendedPDU, stream) Uint32LE.pack(capability.extraFlags1, stream) Uint32LE.pack(capability.extraFlags2, stream) if capability.version == GeneralCapabilityVersion.GENERAL_CAPABILITY_VERSION_02: Uint32LE.pack(capability.specialTypeDeviceCap, stream)
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 writeShareDataHeader(self, stream: BytesIO, header, dataLength): substream = BytesIO() substream.write(Uint32LE.pack(header.shareID)) substream.write(b"\x00") substream.write(Uint8.pack(header.streamID)) substream.write(Uint16LE.pack(header.uncompressedLength)) substream.write(Uint8.pack(header.subtype)) substream.write(Uint8.pack(header.compressedType)) substream.write(Uint16LE.pack(header.compressedLength)) substream = substream.getvalue() self.writeShareControlHeader(stream, header, dataLength + len(substream)) stream.write(substream)
def writeSuppressOutput(self, stream: BytesIO, pdu): Uint8.pack(int(pdu.allowDisplayUpdates), stream) stream.write(b"\x00" * 3) Uint16LE.pack(pdu.left, stream) Uint16LE.pack(pdu.top, stream) Uint16LE.pack(pdu.right, stream) Uint16LE.pack(pdu.bottom, stream)
def write(self, pdu): """ Write a negotiation response. :param pdu: the response PDU. :type pdu: NegotiationResponsePDU :return: str """ stream = BytesIO() if pdu.flags is not None and pdu.selectedProtocols is not None: Uint8.pack(NegotiationType.TYPE_RDP_NEG_RSP, stream) Uint8.pack(pdu.flags, stream) Uint16LE.pack(8, stream) Uint32LE.pack(pdu.selectedProtocols, stream) return stream.getvalue()
def writeError(self, stream: BytesIO, pdu: X224ErrorPDU): """ Write an error PDU onto the provided stream """ stream.write(Uint8.pack(pdu.header)) stream.write(Uint16LE.pack(pdu.destination)) stream.write(Uint8.pack(pdu.cause))
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)