def __init__(self, reader: BinaryStream, ubulk: BinaryStream, bulkOffset: int) -> None: self.Header = FByteBulkDataHeader(reader, bulkOffset) bulkDataFlags = self.Header.BulkDataFlags if self.Header.ElementCount == 0: self.Data = None elif (bulkDataFlags & EBulkDataFlags.BULKDATA_Unused) != 0: self.Data = None elif (bulkDataFlags & EBulkDataFlags.BULKDATA_OptionalPayload) != 0: self.Data = None elif (bulkDataFlags & EBulkDataFlags.BULKDATA_ForceInlinePayload) != 0: self.Data = reader.readBytes(self.Header.ElementCount) elif (bulkDataFlags & EBulkDataFlags.BULKDATA_PayloadInSeperateFile) != 0: # ubulk ubulk.seek(self.Header.OffsetInFile, 0) self.Data = ubulk.readBytes(self.Header.ElementCount) elif (bulkDataFlags & EBulkDataFlags.BULKDATA_PayloadAtEndOfFile) != 0: pos = reader.base_stream.tell() if self.Header.OffsetInFile + self.Header.ElementCount <= reader.size: reader.seek(self.Header.OffsetInFile, 0) self.Data = reader.readBytes(self.Header.ElementCount) else: self.Data = None reader.seek(pos, 0)
def __init__(self, reader: BinaryStream): self.ContainerId = FIoContainerId(reader) self.PackageCount = reader.readUInt32() self.Names = reader.readBytes(reader.readInt32()) self.NameHashes = reader.readBytes(reader.readInt32()) self.PackageIds = reader.readTArray(FPackageId, reader) self.StoreEntries = reader.readTArray(reader.readByteToInt)
def __init__(self, reader: BinaryStream): magic = reader.readBytes(16) if magic != bytes(self._TocMagic, "utf-8"): raise Exceptions.InvalidMagic("invalid utoc magic") self.Version = EIoStoreTocVersion(reader.readByteToInt()) self.Reserved0 = reader.readByte() self.Reserved1 = reader.readUInt16() self.TocHeaderSize = reader.readUInt32() self.TocEntryCount = reader.readUInt32() self.TocCompressedBlockEntryCount = reader.readUInt32() self.TocCompressedBlockEntrySize = reader.readUInt32() self.CompressionMethodNameCount = reader.readUInt32() self.CompressionMethodNameLength = reader.readUInt32() self.CompressionBlockSize = reader.readUInt32() self.DirectoryIndexSize = reader.readUInt32() self.PartitionCount = reader.readUInt32() self.ContainerId = FIoContainerId(reader) self.EncryptionKeyGuid = FGuid(reader) self.ContainerFlags = reader.readByteToInt() try: self.ContainerFlags = EIoContainerFlags(self.ContainerFlags).value except: pass self.Reserved3 = reader.readByteToInt() self.Reserved4 = reader.readUInt16() self.Reserved5 = reader.readUInt32() self.PartitionSize = reader.readUInt64()
def get_data(self, stream: BinaryStream, key, compression_method): if self.CompressionMethodIndex == 0: stream.seek(self.Offset + self.StructSize, 0) if self.Encrypted: raise NotImplementedError("Encryption is not implemented") else: data: bytes = stream.readBytes(self.UncompressedSize) return BinaryStream(data) else: return BinaryStream( self._decompress(stream, key, compression_method))
def Info(self, reader: BinaryStream, offset): self.EncryptionKeyGuid = FGuid(reader).read() self.bEncryptedIndex = reader.readByte() != b'\x00' magic = reader.readUInt32() if magic != self.PAK_FILE_MAGIC: self.Version = EPakVersion.INVALID self.SubVersion = 0 self.IndexOffset = 0 self.IndexSize = 0 self.IndexHash = None self.CompressionMethods = None return self self.Version = EPakVersion(reader.readInt32()) # FGame.Version = self.Version # FGame.SubVersion = self.SubVersion self.SubVersion = 1 if offset == self._SIZE8A and self.Version == EPakVersion.FNAME_BASED_COMPRESSION_METHOD else 0 self.IndexOffset = reader.readInt64() self.IndexSize = reader.readInt64() self.IndexHash = FSHAHash(reader) if self.Version == EPakVersion.FROZEN_INDEX: reader.readByte() # bIndexIsFrozen if self.Version.value < EPakVersion.FNAME_BASED_COMPRESSION_METHOD.value: self.CompressionMethods = ["Zlib", "Gzip", "Oodle", "LZ4"] else: BufferSize: int = self.COMPRESSION_METHOD_NAME_LEN * 4 Methods: bytes = reader.readBytes(BufferSize) MethodList = [] for i in range(4): if int(Methods[i * self.COMPRESSION_METHOD_NAME_LEN]) != 0: methods = Methods byteIndex = i * self.COMPRESSION_METHOD_NAME_LEN byteCount = self.COMPRESSION_METHOD_NAME_LEN decoded = methods[byteIndex:byteCount].decode("utf-8") MethodList.append(decoded) self.CompressionMethods = MethodList if self.Version.value < EPakVersion.INDEX_ENCRYPTION.value: self.bEncryptedIndex = False if self.Version.value < EPakVersion.ENCRYPTION_KEY_GUID.value: self.EncryptionKeyGuid = FGuid().construct(0, 0, 0, 0) return self
def __init__(self, reader: BinaryStream): self.offset = reader.readBytes(5) self.size = reader.readBytes(3) self.uncompressed_size = reader.readBytes(3) self.compression_method = reader.readBytes(1)
def __init__(self, reader: BinaryStream): self.Hash = reader.readBytes(32)
def __init__(self, reader: BinaryStream) -> None: self.Hash = reader.readBytes(20)
def __init__(self, reader: BinaryStream = None): if reader is not None: self.raw = bytearray(reader.readBytes(12)) self._Id = convert_each_byte_to_int(self.raw)
def ReadUpdatedIndex(self, IndexReader: BinaryStream, key, Case_insensitive: bool) -> dict: self.MountPoint = IndexReader.readFString() or "" if self.MountPoint.startswith("../../.."): self.MountPoint = self.MountPoint[8::] if Case_insensitive: self.MountPoint = self.MountPoint.lower() self.NumEntries = IndexReader.readInt32() PathHashSeed = IndexReader.readUInt64() if IndexReader.readInt32() == 0: raise Exception("No path hash index") IndexReader.seek( 8 + 8 + 20 ) # PathHashIndexOffset(long) + PathHashIndexSize(long) + PathHashIndexHash(20bytes) if IndexReader.readInt32() == 0: raise Exception("No directory index") FullDirectoryIndexOffset = IndexReader.readInt64() FullDirectoryIndexSize = IndexReader.readInt64() FullDirectoryIndexHash = FSHAHash(IndexReader) PakEntry_Size = IndexReader.readInt32() EncodedPakEntries = IndexReader.readBytes(PakEntry_Size) # TArray file_num = IndexReader.readInt32() if file_num < 0: raise Exception("Corrupt PrimaryIndex") self.reader.seek(FullDirectoryIndexOffset, 0) PathHashIndexData: bytes = self.reader.base_stream.read( FullDirectoryIndexSize) if self.Info.bEncryptedIndex: bytekey = bytearray.fromhex(key) decryptor = AES.new(bytekey, AES.MODE_ECB) PathHash_Reader = BinaryStream( io.BytesIO(decryptor.decrypt(PathHashIndexData))) else: PathHash_Reader = BinaryStream(io.BytesIO(PathHashIndexData)) PathHashIndex = PathHash_Reader.readTArray_W_Arg( FPakDirectoryEntry, PathHash_Reader) PathHash_Reader.base_stream.close() encodedEntryReader = BinaryStream(io.BytesIO(EncodedPakEntries)) tempentries = {} for directoryEntry in PathHashIndex: for hasIndexEntry in directoryEntry.Entries: path = directoryEntry.Directory + hasIndexEntry.FileName if Case_insensitive: path = path.lower() encodedEntryReader.seek(hasIndexEntry.Location, 0) entry = self.BitEntry(path, encodedEntryReader) tempentries[self.MountPoint + path] = entry index = UpdateIndex(self.FileName, self, tempentries) del tempentries encodedEntryReader.base_stream.close() return index