def sendMessage(self, data: bytes, messageType: PlayerMessageType, timeStamp: int): stream = BytesIO() Uint8.pack(messageType, stream) Uint64LE.pack(timeStamp, stream) stream.write(data) self.previous.send(stream.getvalue())
def parse(self, data: bytes) -> PlayerMessagePDU: stream = BytesIO(data) length = Uint64LE.unpack(stream) type = PlayerMessageType(Uint16LE.unpack(stream)) timestamp = Uint64LE.unpack(stream) payload = stream.read(length - 18) return PlayerMessagePDU(type, timestamp, payload)
def writeCreateRequest(self, pdu: DeviceCreateRequestPDU, stream: BytesIO): 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(pdu.path), stream) stream.write(pdu.path)
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 writeFileDownloadResponse(self, pdu: PlayerFileDownloadResponsePDU, stream: BytesIO): path = pdu.path.encode() Uint32LE.pack(pdu.deviceID, stream) Uint32LE.pack(len(path), stream) stream.write(path) Uint64LE.pack(pdu.offset, stream) Uint32LE.pack(len(pdu.payload), stream) stream.write(pdu.payload)
def parse(self, data: bytes) -> PlayerPDU: stream = BytesIO(data) length = Uint64LE.unpack(stream) pduType = PlayerPDUType(Uint16LE.unpack(stream)) timestamp = Uint64LE.unpack(stream) if pduType in self.parsers: return self.parsers[pduType](stream, timestamp) payload = stream.read(length - 18) return PlayerPDU(pduType, timestamp, payload)
def parseDeviceCreateRequest(self, deviceID: int, fileID: int, completionID: int, minorFunction: int, stream: BytesIO) -> DeviceCreateRequestPDU: desiredAccess = Uint32LE.unpack(stream) allocationSize = Uint64LE.unpack(stream) fileAttributes = FileAttributes(Uint32LE.unpack(stream)) sharedAccess = FileShareAccess(Uint32LE.unpack(stream)) createDisposition = FileCreateDisposition(Uint32LE.unpack(stream)) createOptions = FileCreateOptions(Uint32LE.unpack(stream)) pathLength = Uint32LE.unpack(stream) path = stream.read(pathLength) path = decodeUTF16LE(path)[: -1] return DeviceCreateRequestPDU( deviceID, fileID, completionID, minorFunction, desiredAccess, allocationSize, fileAttributes, sharedAccess, createDisposition, createOptions, path )
def write(self, pdu: PlayerPDU) -> bytes: substream = BytesIO() Uint16LE.pack(pdu.header, substream) Uint64LE.pack(pdu.timestamp, substream) if pdu.header in self.writers: self.writers[pdu.header](pdu, substream) substream.write(pdu.payload) substreamValue = substream.getvalue() stream = BytesIO() Uint64LE.pack(len(substreamValue) + 8, stream) stream.write(substreamValue) return stream.getvalue()
def parseDeviceReadRequest(self, deviceId: int, fileId: int, completionId: int, minorFunction: int, stream: BytesIO) -> DeviceReadRequestPDU: """ Starting at length, just before offset """ length = Uint32LE.unpack(stream) offset = Uint64LE.unpack(stream) return DeviceReadRequestPDU(deviceId, fileId, completionId, minorFunction, length, offset)
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 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)
def parseFileDownloadResponse( self, stream: BytesIO, timestamp: int) -> PlayerFileDownloadResponsePDU: deviceID = Uint32LE.unpack(stream) pathLength = Uint32LE.unpack(stream) path = stream.read(pathLength).decode() offset = Uint64LE.unpack(stream) payloadLength = Uint32LE.unpack(stream) payload = stream.read(payloadLength) return PlayerFileDownloadResponsePDU(timestamp, deviceID, path, offset, payload)
def parseFileFullDirectoryInformation( self, data: bytes) -> List[FileFullDirectoryInformation]: stream = BytesIO(data) information: [FileFullDirectoryInformation] = [] while stream.tell() < len(data): nextEntryOffset = Uint32LE.unpack(stream) fileIndex = Uint32LE.unpack(stream) creationTime = Uint64LE.unpack(stream) lastAccessTime = Uint64LE.unpack(stream) lastWriteTime = Uint64LE.unpack(stream) lastChangeTime = Uint64LE.unpack(stream) endOfFilePosition = Uint64LE.unpack(stream) allocationSize = Uint64LE.unpack(stream) fileAttributes = FileAttributes(Uint32LE.unpack(stream)) fileNameLength = Uint32LE.unpack(stream) eaSize = Uint32LE.unpack(stream) fileName = stream.read(fileNameLength) if nextEntryOffset != 0: stream.read(8 - stream.tell() % 8) # alignment break fileName = decodeUTF16LE(fileName) info = FileFullDirectoryInformation(fileIndex, creationTime, lastAccessTime, lastWriteTime, lastChangeTime, endOfFilePosition, allocationSize, fileAttributes, eaSize, fileName) information.append(info) return information
def parseDeviceCreateRequest(self, deviceId: int, fileId: int, completionId: int, minorFunction: int, stream: BytesIO) -> DeviceCreateRequestPDU: """ Starting at desiredAccess. """ desiredAccess = Uint32LE.unpack(stream) allocationSize = Uint64LE.unpack(stream) fileAttributes = Uint32LE.unpack(stream) sharedAccess = Uint32LE.unpack(stream) createDisposition = Uint32LE.unpack(stream) createOptions = Uint32LE.unpack(stream) pathLength = Uint32LE.unpack(stream) path = stream.read(pathLength) return DeviceCreateRequestPDU(deviceId, fileId, completionId, minorFunction, desiredAccess, allocationSize, fileAttributes, sharedAccess, createDisposition, createOptions, path)
def parse(stream: BytesIO) -> 'FileDescriptor': fd = FileDescriptor() fd.flags = Uint32LE.unpack(stream) stream.read(32) # reserved1 fd.attribs = Uint32LE.unpack(stream) stream.read(16) # reserved2 fd.lastWrite = Uint64LE.unpack(stream) sizeHi = Uint32LE.unpack(stream) sizeLo = Uint32LE.unpack(stream) fd.size = (sizeHi << 32) | sizeLo filename = stream.read(520) fd.filename = filename.decode('utf-16le').strip('\x00') return fd
def onResponse(self, pdu: FileContentsResponsePDU) -> bool: """ Handle file data. @Returns True if file transfer is complete. """ if not self.prev: # First response always contains file size. self.size = Uint64LE.unpack(BytesIO(pdu.data)) return False received = len(pdu.data) self.handle.write(pdu.data) self.transferred += received if self.transferred == self.size: self.handle.close() return True return False
def parseFileBothDirectoryInformation(self, data: bytes) -> List[FileBothDirectoryInformation]: stream = BytesIO(data) information: [FileBothDirectoryInformation] = [] while stream.tell() < len(data): nextEntryOffset = Uint32LE.unpack(stream) fileIndex = Uint32LE.unpack(stream) creationTime = Uint64LE.unpack(stream) lastAccessTime = Uint64LE.unpack(stream) lastWriteTime = Uint64LE.unpack(stream) lastChangeTime = Uint64LE.unpack(stream) endOfFilePosition = Uint64LE.unpack(stream) allocationSize = Uint64LE.unpack(stream) fileAttributes = FileAttributes(Uint32LE.unpack(stream)) fileNameLength = Uint32LE.unpack(stream) eaSize = Uint32LE.unpack(stream) shortNameLength = Uint8.unpack(stream) # stream.read(1) # reserved (not actually used, WTF Microsoft ????) shortName = stream.read(24)[: min(24, shortNameLength)] fileName = stream.read(fileNameLength) if nextEntryOffset != 0: stream.read(8 - stream.tell() % 8) # alignment break shortName = decodeUTF16LE(shortName) fileName = decodeUTF16LE(fileName) info = FileBothDirectoryInformation( fileIndex, creationTime, lastAccessTime, lastWriteTime, lastChangeTime, endOfFilePosition, allocationSize, fileAttributes, eaSize, shortName, fileName ) information.append(info) return information
def writeFileBothDirectoryInformation(self, information: List[FileBothDirectoryInformation], stream: BytesIO): dataList: [bytes] = [] for info in information: substream = BytesIO() fileName = info.fileName.encode("utf-16le") shortName = info.shortName.encode("utf-16le") Uint32LE.pack(info.fileIndex, substream) Uint64LE.pack(info.creationTime, substream) Uint64LE.pack(info.lastAccessTime, substream) Uint64LE.pack(info.lastWriteTime, substream) Uint64LE.pack(info.lastChangeTime, substream) Uint64LE.pack(info.endOfFilePosition, substream) Uint64LE.pack(info.allocationSize, substream) Uint32LE.pack(info.fileAttributes, substream) Uint32LE.pack(len(fileName), substream) Uint32LE.pack(info.eaSize, substream) Uint8.pack(len(shortName), substream) # stream.write(b"\x00") # reserved substream.write(shortName.ljust(24, b"\x00")[: 24]) substream.write(fileName) dataList.append(substream.getvalue()) self.writeFileInformationList(dataList, stream)
def writeDeviceReadRequest(self, pdu: DeviceReadRequestPDU, stream: BytesIO): Uint32LE.pack(pdu.length, stream) Uint64LE.pack(pdu.offset, stream) stream.write(b"\x00" * 20) # Padding
def getPDULength(self, data): return Uint64LE.unpack(data[: 8])
def getPDULength(self, data: bytes) -> int: return Uint64LE.unpack(data[:8])