Пример #1
0
        private void ReadIndexUpdated(BinaryReader reader, FPakInfo info, byte[] aesKey)
        {
            MountPoint = reader.ReadFString();
            if (MountPoint.StartsWith("../../.."))
            {
                MountPoint = MountPoint.Substring(8);
            }
            else
            {
                MountPoint = "/";
            }

            var filesNum = reader.ReadInt32();

            reader.ReadUInt64();

            if (reader.ReadInt32() == 0)
            {
                throw new FileLoadException("No path hash index");
            }

            //reader.ReadInt64();
            //reader.ReadInt64();
            reader.BaseStream.Position += 20L + 8L + 8L;

            if (reader.ReadInt32() == 0)
            {
                throw new FileLoadException("No directory index");
            }

            var position           = reader.ReadInt64();
            var directoryIndexSize = reader.ReadInt64();

            reader.BaseStream.Position += 20L;
            var encodedPakEntries = reader.ReadTArray(reader.ReadByte);
            var files             = reader.ReadInt32();

            if (files < 0)
            {
                throw new FileLoadException("Corrupt pak PrimaryIndex detected!");
            }

            Reader.BaseStream.Position = position;
            var directoryIndexData = Reader.ReadBytes((int)directoryIndexSize);

            if (info.bEncryptedIndex != 0)
            {
                directoryIndexData = AESDecryptor.DecryptAES(directoryIndexData, aesKey);
            }

            var directoryIndexReader = new BinaryReader(new MemoryStream(directoryIndexData));
            var directoryEntries     = directoryIndexReader.ReadTArray(() => new FPakDirectoryEntry(directoryIndexReader));

            var entries = new List <FPakEntry>(filesNum);

            foreach (var directoryEntry in directoryEntries)
            {
                foreach (var hashIndexEntry in directoryEntry.Entries)
                {
                    string path = MountPoint + directoryEntry.Directory + hashIndexEntry.Filename;
                    entries.Add(GetEntry(path, hashIndexEntry.Location, encodedPakEntries));
                }
            }
            this.FileInfos = entries.ToArray();
        }
Пример #2
0
        public PakReader(Stream stream, string name, byte[] aes = null, bool ParseFiles = true)
        {
            Aes    = aes;
            Stream = stream;
            Name   = name;
            Reader = new BinaryReader(Stream);

            Stream.Seek(-FPakInfo.Size, SeekOrigin.End);

            FPakInfo info = new FPakInfo(Reader);

            if (info.Magic != FPakInfo.PAK_FILE_MAGIC)
            {
                DebugHelper.WriteLine(".PAKs: The file magic is invalid");
                throw new FileLoadException("The file magic is invalid");
            }

            if (info.Version > (int)PAK_VERSION.PAK_LATEST)
            {
                DebugHelper.WriteLine($".PAKs: WARNING: Pak file \"{Name}\" has unsupported version {info.Version}");
            }

            if (info.bEncryptedIndex != 0)
            {
                if (Aes == null)
                {
                    DebugHelper.WriteLine(".PAKs: The file has an encrypted index");
                    throw new FileLoadException("The file has an encrypted index");
                }
            }

            // Read pak index

            Stream.Seek(info.IndexOffset, SeekOrigin.Begin);

            // Manage pak files with encrypted index
            BinaryReader infoReader = Reader;

            if (info.bEncryptedIndex != 0)
            {
                var InfoBlock = Reader.ReadBytes((int)info.IndexSize);
                InfoBlock = AESDecryptor.DecryptAES(InfoBlock, Aes);

                infoReader = new BinaryReader(new MemoryStream(InfoBlock));
                int stringLen = infoReader.ReadInt32();
                if (stringLen > 512 || stringLen < -512)
                {
                    DebugHelper.WriteLine(".PAKs: The AES key is invalid");
                    throw new FileLoadException("The AES key is invalid");
                }
                if (stringLen < 0)
                {
                    infoReader.BaseStream.Seek((stringLen - 1) * 2, SeekOrigin.Current);
                    ushort c = infoReader.ReadUInt16();
                    if (c != 0)
                    {
                        DebugHelper.WriteLine(".PAKs: The AES key is invalid");
                        throw new FileLoadException("The AES key is invalid");
                    }
                }
                else
                {
                    infoReader.BaseStream.Seek(stringLen - 1, SeekOrigin.Current);
                    byte c = infoReader.ReadByte();
                    if (c != 0)
                    {
                        DebugHelper.WriteLine(".PAKs: The AES key is invalid");
                        throw new FileLoadException("The AES key is invalid");
                    }
                }

                infoReader.BaseStream.Seek(0, SeekOrigin.Begin);
            }

            if (!ParseFiles)
            {
                return;
            }

            if (info.Version >= (int)PAK_VERSION.PAK_PATH_HASH_INDEX)
            {
                ReadIndexUpdated(infoReader, info, Aes);
            }
            else
            {
                MountPoint = infoReader.ReadFString();
                if (MountPoint.StartsWith("../../.."))
                {
                    MountPoint = MountPoint.Substring(8);
                }
                else
                {
                    MountPoint = "/";
                }

                FileInfos = new FPakEntry[infoReader.ReadInt32()];
                for (int i = 0; i < FileInfos.Length; i++)
                {
                    FileInfos[i] = new FPakEntry(infoReader, MountPoint, (PAK_VERSION)info.Version);
                }
            }
        }
Пример #3
0
        public PakReader(Stream stream, string name, byte[] aes = null, bool ParseFiles = true)
        {
            Aes    = aes;
            Stream = stream;
            Name   = name;
            Reader = new BinaryReader(Stream);

            Stream.Seek(-FPakInfo.Size, SeekOrigin.End);

            FPakInfo info = new FPakInfo(Reader);

            if (info.Magic != FPakInfo.PAK_FILE_MAGIC)
            {
                throw new FileLoadException("The file magic is invalid");
            }

            if (info.Version > (int)PAK_VERSION.PAK_LATEST)
            {
                Console.Error.WriteLine($"WARNING: Pak file \"{Name}\" has unsupported version {info.Version}");
            }

            if (info.bEncryptedIndex != 0)
            {
                if (Aes == null)
                {
                    throw new FileLoadException("The file has an encrypted index");
                }
            }

            // Read pak index

            Stream.Seek(info.IndexOffset, SeekOrigin.Begin);

            // Manage pak files with encrypted index
            BinaryReader infoReader = Reader;

            if (info.bEncryptedIndex != 0)
            {
                var InfoBlock = Reader.ReadBytes((int)info.IndexSize);
                InfoBlock = AESDecryptor.DecryptAES(InfoBlock, (int)info.IndexSize, Aes, Aes.Length);

                infoReader = new BinaryReader(new MemoryStream(InfoBlock));
                int stringLen = infoReader.ReadInt32();
                if (stringLen > 512 || stringLen < -512)
                {
                    throw new FileLoadException("The AES key is invalid");
                }
                if (stringLen < 0)
                {
                    infoReader.BaseStream.Seek((stringLen - 1) * 2, SeekOrigin.Current);
                    ushort c = infoReader.ReadUInt16();
                    if (c != 0)
                    {
                        throw new FileLoadException("The AES key is invalid");
                    }
                }
                else
                {
                    infoReader.BaseStream.Seek(stringLen - 1, SeekOrigin.Current);
                    byte c = infoReader.ReadByte();
                    if (c != 0)
                    {
                        throw new FileLoadException("The AES key is invalid");
                    }
                }
            }

            if (!ParseFiles)
            {
                return;
            }

            // Pak index reading time :)
            infoReader.BaseStream.Seek(0, SeekOrigin.Begin);
            MountPoint = infoReader.ReadString(FPakInfo.MAX_PACKAGE_PATH);

            bool badMountPoint = false;

            if (!MountPoint.StartsWith("../../.."))
            {
                badMountPoint = true;
            }
            else
            {
                MountPoint = MountPoint.Substring(8);
            }
            if (MountPoint[0] != '/' || ((MountPoint.Length > 1) && (MountPoint[1] == '.')))
            {
                badMountPoint = true;
            }

            if (badMountPoint)
            {
                Console.Error.WriteLine($"WARNING: Pak \"{Name}\" has strange mount point \"{MountPoint}\", mounting to root");
                MountPoint = "/";
            }

            FileInfos = new FPakEntry[infoReader.ReadInt32()];
            for (int i = 0; i < FileInfos.Length; i++)
            {
                FileInfos[i] = new FPakEntry(infoReader, MountPoint, info.Version);
            }
        }