Пример #1
0
    def _decompress(self, stream: BinaryStream, key, compressionMethods: list):
        compressionMethod = compressionMethods[self.CompressionMethodIndex - 1]

        result = bytearray()
        if self.Encrypted:
            if key is None:
                raise InvalidEncryptionKey(
                    "File is Encrypted and Key was not provided.")
            from Crypto.Cipher import AES
            decryptor = AES.new(bytearray().fromhex(key), AES.MODE_ECB)

        block: FPakCompressedBlock
        for block in self.CompressionBlocks:
            stream.seek(self.Offset + block.CompressedStart)
            uncompressed_size = min(self.CompressionBlockSize,
                                    self.UncompressedSize - len(result))

            if self.Encrypted:
                buffer = stream.read(
                    Align(self.CompressionBlockSize, AES.block_size))
                buffer = decryptor.decrypt(buffer)
            else:
                buffer = stream.read(Align(self.CompressionBlockSize,
                                           16))  # AES.block_size

            result += Decompress.Decompress(buffer, compressionMethod,
                                            uncompressed_size)
        return result
Пример #2
0
 def __init__(self, reader: BinaryStream, ubulk: BinaryStream,
              bulkOffset: int) -> None:
     self.bCooked = reader.readInt32() != 0
     self.BulkData = FByteBulkData(reader, ubulk, bulkOffset)
     self.SizeX = reader.readInt32()
     self.SizeY = reader.readInt32()
     self.SizeZ = reader.readInt32()
Пример #3
0
    def serializeBuffer(self, reader: BinaryStream):
        stripFlags = FStripDataFlags(reader)

        self.positionVertexBuffer = FPositionVertexBuffer(reader)
        self.vertexBuffer = FStaticMeshVertexBuffer(reader)
        self.colorVertexBuffer = FColorVertexBuffer(reader)
        self.indexBuffer = FRawStaticIndexBuffer(reader)

        if not stripFlags.isClassDataStripped(CDSF_ReversedIndexBuffer):
            self.reversedIndexBuffer = FRawStaticIndexBuffer(reader)

        self.depthOnlyIndexBuffer = FRawStaticIndexBuffer(reader)

        if not stripFlags.isClassDataStripped(CDSF_ReversedIndexBuffer):
            self.reversedDepthOnlyIndexBuffer = FRawStaticIndexBuffer(reader)

        if not stripFlags.isEditorDataStripped():
            self.wireframeIndexBuffer = FRawStaticIndexBuffer(reader)

        if not stripFlags.isClassDataStripped(CDSF_AdjancencyData):
            self.adjacencyIndexBuffer = FRawStaticIndexBuffer(reader)

        # UE 4.25+
        if reader.game >= GAME_UE4(25) and not stripFlags.isClassDataStripped(
                CDSF_RaytracingResources):
            reader.readBulkTArray(reader.readByte)  # Raw data

        # 25178
        for i in range(len(self.sections)):
            FWeightedRandomSampler(
                reader)  # FStaticMeshSectionAreaWeightedTriangleSampler
        FWeightedRandomSampler(reader)  # FStaticMeshAreaWeightedSectionSampler
Пример #4
0
    def __init__(self, reader: BinaryStream):
        self.MaterialInterface = reader.readObject()
        self.MaterialSlotName = reader.readFName()

        if FRenderingObjectVersion().get(
                reader
        ) >= FRenderingObjectVersion.TextureStreamingMeshUVChannelData:
            self.UVChannelData = FMeshUVChannelInfo(reader)
Пример #5
0
 def __init__(self, reader: BinaryStream):
     self.stripFlags = FStripDataFlags(reader, Versions.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX)
     self.stride = reader.readInt32()
     self.numVertices = reader.readInt32()
     if not self.stripFlags.isDataStrippedForServer() and self.numVertices > 0:
         self.data = reader.readBulkTArray(FColor, reader)
     else:
         self.data = []
Пример #6
0
 def __init__(self,
              reader: BinaryStream,
              min_version=Versions.VER_UE4_REMOVED_STRIP_DATA):
     if reader.version >= min_version:
         self.globalStripFlags = reader.readByteToInt()
         self.classStripFlags = reader.readByteToInt()
     else:
         self.globalStripFlags = 0
         self.classStripFlags = 0
Пример #7
0
        def yeet(anything):
            if isinstance(anything, str):
                if not os.path.exists(anything):
                    logger.error(f"{anything} not found")
                with open(anything, "rb") as f:
                    data = f.read()
                    return BinaryStream(io.BytesIO(data), size=len(data))

            elif isinstance(anything, (bytes, bytearray)):
                return BinaryStream(io.BytesIO(anything), size=len(anything))
Пример #8
0
    def __init__(self, reader: BinaryStream):
        self.TableNamespace = reader.readFString()

        self.KeysToMetadata = {}

        NumEntries = reader.readInt32()
        for i in range(NumEntries):
            key = reader.readFString()
            text = reader.readFString()
            self.KeysToMetadata[key] = text
Пример #9
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)
Пример #10
0
    def __init__(self, reader: BinaryStream):
        self.X = reader.readUInt16()
        self.Y = reader.readUInt16()
        self.Z = reader.readUInt16()
        self.W = reader.readUInt16()

        if reader.game >= GAME_UE4(20):
            self.X = self.X ^ 0x8000
            self.Y = self.Y ^ 0x8000
            self.Z = self.Z ^ 0x8000
            self.W = self.W ^ 0x8000
Пример #11
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))
Пример #12
0
    def __init__(self, reader: BinaryStream, readType,
                 tag):  #TODO: handle enums
        self.position = reader.base_stream.tell()

        if readType == PropertyTagData.BaseProperty.ReadType.NORMAL:
            self.Value = reader.readByteToInt()
        elif readType == PropertyTagData.BaseProperty.ReadType.MAP:
            self.Value = reader.readUInt32()
        elif readType == PropertyTagData.BaseProperty.ReadType.ARRAY:
            self.Value = reader.readByteToInt()
        else:
            raise Exception(f"hmm {readType.name}")
Пример #13
0
    def __init__(self, reader: BinaryStream, FileSize: int) -> None:
        reader = reader
        Offsets_to_Try = [self._SIZE, self._SIZE8, self._SIZE8A, self._SIZE9]

        for Offset in Offsets_to_Try:
            if FileSize - Offset > 0:
                reader.seek(FileSize - Offset, 0)
                info = self.Info(reader, Offset)
                if info.Version != EPakVersion.INVALID:
                    return

        raise ParserException(f"Unknown Pak Format")
Пример #14
0
 def __init__(self, reader: BinaryStream, Tag):
     NumKeystoRemove = reader.readInt32()
     for _ in range(NumKeystoRemove):
         PropertyTagData.BaseProperty.ReadAsObject(
             reader, Tag, Tag.Type,
             PropertyTagData.BaseProperty.ReadType.ARRAY)
     Entries = reader.readInt32()
     self.Value = []
     for _ in range(Entries):
         value = PropertyTagData.BaseProperty.ReadAsObject(
             reader, Tag, Tag.Type,
             PropertyTagData.BaseProperty.ReadType.ARRAY)
         self.Value.append(value)
Пример #15
0
    def __init__(self, reader: BinaryStream, Case_insensitive: bool):
        self.MountPoint = reader.readFString()

        if self.MountPoint.startswith("../../.."):
            self.MountPoint = self.MountPoint[8::]

        if Case_insensitive:
            self.MountPoint = self.MountPoint.lower()

        self.DirectoryEntries = reader.readTArray(FIoDirectoryIndexEntry,
                                                  reader)
        self.FileEntries = reader.readTArray(FIoFileIndexEntry, reader)
        self.StringTable = reader.readTArray(reader.readFString)
Пример #16
0
    def __init__(self, reader: BinaryStream) -> None:
        self.position = reader.base_stream.tell()
        length = reader.readInt32()

        for _ in range(length):
            self.Map[FGuid(
                reader).read()] = FLevelSequenceLegacyObjectReference(reader)
Пример #17
0
    def IndexToEnum(self, reader: BinaryStream, tag: FPropertyTag, index: int):
        name = tag.EnumName
        if name is None:
            return str(index)

        if reader.has_unversioned_properties:
            enumVals = reader.getmappings().get_enum(name.string)
            return tag.EnumName.string + "::" + enumVals[index]
Пример #18
0
 def __init__(self, reader: BinaryStream):
     self.MaterialIndex = reader.readInt32()
     self.FirstIndex = reader.readInt32()
     self.NumTriangles = reader.readInt32()
     self.MinVertexIndex = reader.readInt32()
     self.MaxVertexIndex = reader.readInt32()
     self.EnableCollision = reader.readBool()
     self.CastShadow = reader.readBool()
     self.ForceOpaque = reader.readBool() if FRenderingObjectVersion().get(reader) >= FRenderingObjectVersion.StaticMeshSectionForceOpaqueField else False
     self.VisibleInRayTracing = reader.readBool() if reader.game >= EUEVersion.GAME_UE4_26 else False
Пример #19
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)
Пример #20
0
 def __init__(self, reader: BinaryStream):  # probably crash
     self.position = reader.base_stream.tell()
     self.InterpMode = ERichCurveInterpMode(
         int.from_bytes(reader.readByte(), byteorder="little"))
     self.TangentMode = ERichCurveTangentMode(
         int.from_bytes(reader.readByte(), byteorder="little"))
     self.TangentWeightMode = ERichCurveTangentWeightMode(
         int.from_bytes(reader.readByte(), byteorder="little"))
     self.KeyTime = reader.readFloat()
     self.KeyValue = reader.readFloat()
     self.ArriveTangent = reader.readFloat()
     self.ArriveTangentWeight = reader.readFloat()
     self.LeaveTangent = reader.readFloat()
     self.LeaveTangentWeight = reader.readFloat()
Пример #21
0
    def __init__(self, reader: BinaryStream, tag: FPropertyTag, readType):
        self.position = reader.base_stream.tell()
        from .BaseProperty import ReadType

        if readType == ReadType.ZERO:  #ZERO
            self.Value = FName(self.IndexToEnum(reader, tag, 0))
        elif readType.value == 0:
            byteValue = 0
            innerType = getattr(tag, "InnerType", None)
            if innerType is not None:
                from .BaseProperty import ReadAsValue
                byteValue = ReadAsValue(reader, tag.InnerData, innerType, 0)
            else:
                byteValue = reader.readByteToInt()

            self.Value = FName(self.IndexToEnum(reader, tag, byteValue))
        else:
            self.Value = reader.readFName()
Пример #22
0
    def _register_file(self, con_file, path):
        pak_name = con_file

        if pak_name.endswith(".pak"):
            # self.Paks[os.path.basename(pak_name)] =
            reader = PakReader.PakReader(path, self.caseinsensitive)
            return reader, os.path.basename(pak_name)
            # logger.debug(f"Registering PakFile: {path}")
        if pak_name.endswith(".utoc"):
            ucas_path = path[:-5] + ".ucas"
            logger.debug(f"Registering IoStore: {path[:-5]}")
            reader = IoStoreReader.FFileIoStoreReader(ucas_path,
                                                      BinaryStream(path),
                                                      BinaryStream(ucas_path),
                                                      self.caseinsensitive)
            return reader, os.path.basename(pak_name)

        return None, None
Пример #23
0
    def __init__(self, reader: BinaryStream) -> None:
        FlagVal = reader.readUInt32()
        try:
            self.Flags = ETextFlag(FlagVal)
        except:
            self.Flags = FlagVal

        self.HistoryType = ETextHistoryBase(reader.readSByte())
        if self.HistoryType == ETextHistoryBase.Base:
            self.Text = Base(reader)
        elif self.HistoryType == ETextHistoryBase.NamedFormat:
            self.Text = NamedFormat(reader)
        elif self.HistoryType == ETextHistoryBase.StringTableEntry:
            self.Text = StringTableEntry(reader)
        elif self.HistoryType == ETextHistoryBase._None:
            self.Text = _None(reader)
        else:
            raise NotImplementedError(f"FText: Unsupported FText Type {self.HistoryType.name}")
Пример #24
0
    def ReadDirectoryIndex(self, key: Optional[str] = None):
        self._aeskey = key
        starttime = time.time()
        if self.HasDirectoryIndex:
            if not self.IsEncrypted:
                IndexReader = BinaryStream(io.BytesIO(self._directoryIndexBuffer), len(self._directoryIndexBuffer))
            else:
                if not CrytoAval:
                    raise ImportError(
                        "Failed to Import \"pycryptodome\", Index is Encrypted it is required for decryption.")
                if self._aeskey is None:
                    raise InvalidEncryptionKey("Index is Encrypted and Key was not provided.")

                bytekey = bytearray.fromhex(self._aeskey)
                decryptor = AES.new(bytekey, AES.MODE_ECB)
                IndexReader = BinaryStream(io.BytesIO(decryptor.decrypt(self._directoryIndexBuffer)),
                                           len(self._directoryIndexBuffer))

                stringLen = IndexReader.readInt32()
                if stringLen > 512 or stringLen < -512:
                    raise ValueError(f"Provided key didn't work with {self.FileName}")
                if stringLen < 0:
                    IndexReader.base_stream.seek((stringLen - 1) * 2, 1)
                    if IndexReader.readUInt16() != 0:
                        raise ValueError(f"Provided key didn't work with {self.FileName}")
                else:
                    IndexReader.base_stream.seek(stringLen - 1, 1)
                    if int.from_bytes(IndexReader.readByte(), "little") != 0:
                        raise ValueError(f"Provided key didn't work with {self.FileName}")
                IndexReader.seek(0, 0)
            del self.TocResource.DirectoryIndexBuffer
            del self._directoryIndexBuffer

            self._directory_index = FIoDirectoryIndexResource(IndexReader, self.caseinSensitive)
            self.ContainerFile.MountPoint = self._directory_index.MountPoint
            firstEntry = self.GetChildDirectory(FIoDirectoryIndexHandle(FIoDirectoryIndexHandle.Root))

            tempFiles: Dict[str, FIoStoreEntry]
            Chunks: Dict[str, str]
            tempFiles, Chunks = self.ReadIndex("", firstEntry)  # TODO use Chunks IDs

            files = UpdateIndex(self.FileName, self.ContainerFile, tempFiles)

            time_taken = round(time.time() - starttime, 2)
            logger.info("{} contains {} files, mount point: {}, version: {}, in: {}s".format
                        (self.FileName, len(tempFiles), self._directory_index.MountPoint, self.TocResource.Header.Version, time_taken))

            del self._directory_index
            return files, Chunks
Пример #25
0
 def __init__(self, reader: BinaryStream):
     self.Protocol = reader.readFString()
     self.Host = reader.readFString()
     self.Map = reader.readFString()
     self.Portal = reader.readFString()
     self.Op = reader.readTArray(reader.readFString)
     self.Port = reader.readInt32()
     self.Valid = reader.readInt32()
Пример #26
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
Пример #27
0
    def __init__(self, reader: BinaryStream, bulkOffset: int) -> None:
        self.BulkDataFlags = reader.readInt32()
        if (self.BulkDataFlags & EBulkDataFlags.BULKDATA_Size64Bit) != 0:
            self.ElementCount = reader.readInt64()
            self.SizeOnDisk = reader.readInt64()
        else:
            self.ElementCount = reader.readInt32()
            self.SizeOnDisk = reader.readInt32()

        self.OffsetInFile = reader.readInt64()
        if not (self.BulkDataFlags
                & EBulkDataFlags.BULKDATA_NoOffsetFixUp):  # UE4.26 flag
            self.OffsetInFile += bulkOffset

        if (self.BulkDataFlags & EBulkDataFlags.BULKDATA_BadDataVersion) != 0:
            reader.seek(2)
Пример #28
0
    def __init__(self, reader: BinaryStream, tag):
        # raise NotImplementedError("Map Prop")
        self.position = reader.base_stream.tell()
        NumKeysToRemove = reader.readInt32()

        if NumKeysToRemove != 0:
            for _ in range(NumKeysToRemove):
                PropertyTagData.BaseProperty.ReadAsValue(
                    reader, tag, tag.InnerType,
                    PropertyTagData.BaseProperty.ReadType.MAP)

        NumEntries = reader.readInt32()
        data = {}
        for _ in range(NumEntries):
            key = str(
                PropertyTagData.BaseProperty.ReadAsValue(
                    reader, tag, tag.InnerType,
                    PropertyTagData.BaseProperty.ReadType.MAP))
            value = PropertyTagData.BaseProperty.ReadAsObject(
                reader, tag, tag.ValueType,
                PropertyTagData.BaseProperty.ReadType.MAP)

            data[key] = value  # formatting tho
        self.Value = data
Пример #29
0
 def __init__(self,
              File: str = "",
              Case_insensitive: bool = False,
              reader: Optional[BinaryStream] = None) -> None:
     self.MountPoint: str = ""
     if reader is not None:
         self.reader = reader
         self.size: int = reader.size
     else:
         self.reader: BinaryStream = BinaryStream(File)
         self.size: int = os.path.getsize(File)
     self.FileName: str = os.path.basename(File)
     self.Info = PakInfo(self.reader, self.size)
     self.NumEntries = -1
     self.reader.seek(self.Info.IndexOffset, 0)
     self.MountArray = self.reader.readBytes(128)
     self.Case_insensitive: bool = Case_insensitive
Пример #30
0
    def deserialize(self, reader: BinaryStream, ubulk: BinaryStream,
                    ubulkOffset: int):
        self.SizeX = reader.readInt32()
        self.SizeY = reader.readInt32()
        self.NumSlices = reader.readInt32()  # 1 for normal textures
        self.PixelFormat = EPixelFormat[reader.readFString()]

        self.FirstMipToSerialize = reader.readInt32() - 1
        self.Mips = reader.readTArray_W_Arg(FTexture2DMipMap, reader, ubulk,
                                            ubulkOffset)
        if reader.game >= GAME_UE4(23):
            self.bIsVirtual = reader.readInt32() != 0
            if self.bIsVirtual:
                raise NotImplementedError(
                    "Virtual Textures ar not Not implemented")