示例#1
0
    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)
示例#2
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)
示例#3
0
    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()
示例#4
0
 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))
示例#5
0
    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
示例#6
0
 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)
示例#8
0
 def __init__(self, reader: BinaryStream) -> None:
     self.Hash = reader.readBytes(20)
示例#9
0
 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)
示例#10
0
    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