def parseClientCoreData(self, stream): stream = StrictStream(stream) # 128 bytes minimum (excluding header) version = RDPVersion(Uint32LE.unpack(stream)) desktopWidth = Uint16LE.unpack(stream) desktopHeight = Uint16LE.unpack(stream) colorDepth = ColorDepth(Uint16LE.unpack(stream)) sasSequence = Uint16LE.unpack(stream) keyboardLayout = Uint32LE.unpack(stream) clientBuild = Uint32LE.unpack(stream) clientName = decodeUTF16LE(stream.read(32)) keyboardType = Uint32LE.unpack(stream) keyboardSubType = Uint32LE.unpack(stream) keyboardFunctionKey = Uint32LE.unpack(stream) imeFileName = stream.read(64) core = ClientCoreData(version, desktopWidth, desktopHeight, colorDepth, sasSequence, keyboardLayout, clientBuild, clientName, keyboardType, keyboardSubType, keyboardFunctionKey, imeFileName) # Optional data # The optional fields are read in order. If one of them is not present, then all subsequent fields are also not present. try: core.postBeta2ColorDepth = Uint16LE.unpack(stream) core.clientProductId = Uint16LE.unpack(stream) core.serialNumber = Uint32LE.unpack(stream) core.highColorDepth = HighColorDepth(Uint16LE.unpack(stream)) core.supportedColorDepths = Uint16LE.unpack(stream) core.earlyCapabilityFlags = Uint16LE.unpack(stream) core.clientDigProductId = decodeUTF16LE(stream.read(64)) core.connectionType = ConnectionType(Uint8.unpack(stream)) core.pad1octet = stream.read(1) core.serverSelectedProtocol = Uint32LE.unpack(stream) core.desktopPhysicalWidth = Uint32LE.unpack(stream) core.desktopPhysicalHeight = Uint32LE.unpack(stream) core.desktopOrientation = DesktopOrientation(Uint16LE.unpack(stream)) core.desktopScaleFactor = Uint32LE.unpack(stream) core.deviceScaleFactor = Uint32LE.unpack(stream) except EOFError: # The stream has reached the end, we don't have any more optional fields. This exception can be ignored. pass return core
def parseControl(self, stream: BytesIO, header): action = Uint16LE.unpack(stream) grantID = Uint16LE.unpack(stream) controlID = Uint32LE.unpack(stream) return ControlPDU(header, action, grantID, controlID)
def parsePlaySound(self, stream: BytesIO, header): duration = Uint32LE.unpack(stream) frequency = Uint32LE.unpack(stream) return PlaySoundPDU(header, duration, frequency)
def writeDeviceReadResponse(self, pdu: DeviceReadResponsePDU, stream: BytesIO): Uint32LE.pack(len(pdu.payload), stream) stream.write(pdu.payload)
def parseError(self, stream: BytesIO, header): errorInfo = Uint32LE.unpack(stream) return SetErrorInfoPDU(header, ErrorInfo(errorInfo))
def writeDeviceCreateResponse(self, pdu: DeviceCreateResponsePDU, stream: BytesIO): Uint32LE.pack(pdu.fileID, stream) Uint8.pack(pdu.information)
def writeDeviceReadRequest(self, pdu: DeviceReadRequestPDU, stream: BytesIO): Uint32LE.pack(pdu.length, stream) Uint64LE.pack(pdu.offset, stream) stream.write(b"\x00" * 20) # Padding
def parseSynchronizeEvent(self, stream, eventTime): stream.read(2) flags = Uint32LE.unpack(stream) return SynchronizeEvent(eventTime, flags)
def writeSynchronizeEvent(self, stream, event): stream.write(b"\x00" * 2) Uint32LE.pack(event.flags, stream)
def parse(s: BytesIO) -> 'FrameMarker': self = FrameMarker() self.action = Uint32LE.unpack(s) return self
def writeHeader(self, stream, pdu): # Make sure the header contains the flags for encryption and salted signatures. header = pdu.header | SecurityFlags.SEC_ENCRYPT | SecurityFlags.SEC_SECURE_CHECKSUM Uint32LE.pack(header, stream)
def parseFileDescription(self, stream: BytesIO) -> PlayerFileDescription: length = Uint32LE.unpack(stream) path = stream.read(length).decode() isDirectory = bool(Uint8.unpack(stream)) return PlayerFileDescription(path, isDirectory)
def writeBitmap(self, pdu: PlayerBitmapPDU, stream: BytesIO): Uint32LE.pack(pdu.width, stream) Uint32LE.pack(pdu.height, stream) stream.write(pdu.pixels)
def parseBitmap(self, stream: BytesIO, timestamp: int) -> PlayerBitmapPDU: width = Uint32LE.unpack(stream) height = Uint32LE.unpack(stream) pixels = stream.read(width * height * 4) return PlayerBitmapPDU(timestamp, width, height, pixels)
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 or 0, stream)
def parseFileContentsResponse(self, payload, msgFlags): stream = BytesIO(payload) streamId = Uint32LE.unpack(stream) # FIXME: Need to grab the actual file size from the reply. data = stream.read() return FileContentsResponsePDU(payload, msgFlags, streamId, data)
def writeDeviceCreateRequest(self, pdu: DeviceCreateRequestPDU, stream: BytesIO): path = (pdu.path + "\x00").encode("utf-16le") Uint32LE.pack(pdu.desiredAccess, stream) Uint64LE.pack(pdu.allocationSize, stream) Uint32LE.pack(pdu.fileAttributes, stream) Uint32LE.pack(pdu.sharedAccess, stream) Uint32LE.pack(pdu.createDisposition, stream) Uint32LE.pack(pdu.createOptions, stream) Uint32LE.pack(len(path), stream) stream.write(path)
def parseFormatDataRequest(self, payload, msgFlags): s = BytesIO(payload) out = FormatDataRequestPDU(Uint32LE.unpack(s)) self.req = out return out
def parseDeviceReadRequest(self, deviceID: int, fileID: int, completionID: int, minorFunction: int, stream: BytesIO) -> DeviceReadRequestPDU: length = Uint32LE.unpack(stream) offset = Uint64LE.unpack(stream) stream.read(20) # Padding return DeviceReadRequestPDU(deviceID, fileID, completionID, minorFunction, length, offset)
def writeSingleDeviceAnnounce(self, pdu: DeviceAnnounce, stream: BytesIO): Uint32LE.pack(pdu.deviceType, stream) Uint32LE.pack(pdu.deviceId, stream) stream.write(pdu.preferredDosName) Uint32LE.pack(len(pdu.deviceData), stream) stream.write(pdu.deviceData)
def parseDeviceReadResponse(self, deviceID: int, completionID: int, ioStatus: int, stream: BytesIO) -> DeviceReadResponsePDU: length = Uint32LE.unpack(stream) payload = stream.read(length) return DeviceReadResponsePDU(deviceID, completionID, ioStatus, payload)
def parseDeviceListAnnounce(self, stream: BytesIO) -> DeviceListAnnounceRequest: deviceCount = Uint32LE.unpack(stream) deviceList = [] for i in range(deviceCount): deviceList.append(self.parseSingleDeviceAnnounce(stream)) return DeviceListAnnounceRequest(deviceList)
def doParse(self, data: bytes) -> VirtualChannelPDU: stream = BytesIO(data) length = Uint32LE.unpack(stream) flags = Uint32LE.unpack(stream) payload = stream.read(length) return VirtualChannelPDU(flags, payload)
def parseDeviceListAnnounce(self, stream: BytesIO) -> DeviceListAnnounceRequest: deviceCount = Uint32LE.unpack(stream) deviceList = [self.parseDeviceAnnounce(stream) for _ in range(deviceCount)] return DeviceListAnnounceRequest(deviceList)
def writeError(self, stream: BytesIO, pdu): Uint32LE.pack(pdu.errorInfo, stream)
def writeDeviceListAnnounce(self, pdu: DeviceListAnnounceRequest, stream: BytesIO): Uint32LE.pack(len(pdu.deviceList), stream) for device in pdu.deviceList: self.writeDeviceAnnounce(device, stream)
def writeControl(self, stream: BytesIO, pdu): Uint16LE.pack(pdu.action, stream) Uint16LE.pack(pdu.grantID, stream) Uint32LE.pack(pdu.grantID, stream)
def writeDeviceAnnounce(self, pdu: DeviceAnnounce, stream: BytesIO): Uint32LE.pack(pdu.deviceType, stream) Uint32LE.pack(pdu.deviceID, stream) stream.write(pdu.preferredDOSName.encode().ljust(7, b"\x00")[: 7] + b"\x00") Uint32LE.pack(len(pdu.deviceData), stream) stream.write(pdu.deviceData)
def writePlaySound(self, stream: BytesIO, pdu): Uint32LE.pack(pdu.duration, stream) Uint32LE.pack(pdu.frequency, stream)
def writeClientClusterData(self, stream, cluster): stream.write(Uint32LE.pack(cluster.flags)) stream.write(Uint32LE.pack(cluster.redirectedSessionID))