Ejemplo n.º 1
0
        /// <summary>
        /// Reads the PAK file metadata, including file list information and the file list
        /// </summary>
        /// <exception cref="NotSupportedException">Is thrown if the given PAK file does not have a valid signature</exception>
        private void ReadMetadata()
        {
            using (BinaryReader reader = new BinaryReader(new MemoryStream(File.ReadAllBytes(FilePath))))
            {
                reader.BaseStream.Seek(-9L, SeekOrigin.End);

                uint fileListOffset = reader.ReadUInt32();
                uint fileCount      = reader.ReadUInt32();

                if ((reader.ReadByte()) != 0x12)
                {
                    throw new NotSupportedException("The signature of this PAK file is invalid!");
                }

                reader.BaseStream.Seek(fileListOffset, SeekOrigin.Begin);

                for (uint i = 0; i < fileCount; i++)
                {
                    FileEntry fileEntry = new FileEntry();

                    fileEntry.FileNameLength = reader.ReadByte();
                    fileEntry.Compression    = reader.ReadByte();
                    fileEntry.Offset         = reader.ReadUInt32();
                    fileEntry.FileSize       = reader.ReadUInt32();
                    fileEntry.RealFileSize   = reader.ReadUInt32();

                    byte[] tempName = reader.ReadBytes(fileEntry.FileNameLength);

                    if (fileEntry.Compression < 4)
                    {
                        uint decryptionKey = (uint)Key;

                        reader.BaseStream.Seek(1L, SeekOrigin.Current);
                        fileEntry.FileName = Encoding.UTF8.GetString(XOR.Cipher(tempName, decryptionKey));
                    }
                    else
                    {
                        uint[] decryptionKey = (uint[])Key;

                        fileEntry.Compression ^= 0x20;

                        fileEntry.FileName = DecryptFileName(tempName, decryptionKey);

                        uint[] decryptionData =
                        {
                            fileEntry.Offset,
                            fileEntry.RealFileSize
                        };

                        uint[] resultData = XTEA.Decipher(16, decryptionData, decryptionKey);

                        fileEntry.Offset       = resultData[0];
                        fileEntry.RealFileSize = resultData[1];
                    }

                    Entries.Add(fileEntry);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Decrypts the name of a file using XTEA
        /// </summary>
        /// <param name="fileNameBuffer">Bytes of the file name</param>
        /// <param name="key">Key to decrypt the filename with</param>
        /// <returns>The decrypted filename</returns>
        private static string DecryptFileName(byte[] fileNameBuffer, uint[] key)
        {
            Span <byte> nameSpan = fileNameBuffer;

            for (int j = 0; j < nameSpan.Length; j = j + 8)
            {
                Span <byte> chunk     = nameSpan.Slice(j, 8);
                Span <uint> decrypted = XTEA.Decipher(16, MemoryMarshal.Cast <byte, uint>(chunk).ToArray(), key);
                Span <byte> resource  = MemoryMarshal.AsBytes(decrypted);
                resource.CopyTo(chunk);
            }

            return(Encoding.UTF8.GetString(nameSpan.ToArray().TakeWhile(x => x != 0x00).ToArray()));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Reads the file entries of the PAK file
        /// </summary>
        public void ReadFileEntries()
        {
            long Position = Reader.BaseStream.Position;

            Reader.BaseStream.Seek(FileListOffset, SeekOrigin.Begin);

            for (uint i = 0; i < FileCount; i++)
            {
                FileEntry fileEntry = new FileEntry();

                fileEntry.FileNameLength = Reader.ReadByte();
                fileEntry.Compression    = Reader.ReadByte();
                fileEntry.Offset         = Reader.ReadUInt32();
                fileEntry.FileSize       = Reader.ReadUInt32();
                fileEntry.RealFileSize   = Reader.ReadUInt32();

                byte[] tempName = Reader.ReadBytes(fileEntry.FileNameLength);

                if (fileEntry.Compression < 4 && fileEntry.Compression > -1)
                {
                    uint decryptionKey = (uint)Key;

                    fileEntry.Unknown1 = Reader.ReadByte();
                    fileEntry.FileName = Encoding.UTF8.GetString(XOR.Cipher(tempName, decryptionKey));
                }
                else
                {
                    uint[] decryptionKey = (uint[])Key;

                    fileEntry.Compression ^= 0x20;

                    fileEntry.FileName = DecryptFileName(tempName, decryptionKey);

                    uint[] decryptionData = new uint[]
                    {
                        fileEntry.Offset,
                        fileEntry.RealFileSize
                    };

                    uint[] resultData = XTEA.Decipher(16, decryptionData, decryptionKey);

                    fileEntry.Offset       = resultData[0];
                    fileEntry.RealFileSize = resultData[1];
                }

                Entries.Add(fileEntry);
            }

            Reader.BaseStream.Seek(Position, SeekOrigin.Begin);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Decrypts and parses the updatelist file
        ///
        /// Saves the parsed updatelist in the Document instance attribute
        /// </summary>
        public void Parse()
        {
            if (DecryptionKey == null)
            {
                throw new NullReferenceException("DecryptionKey needs to be set using the SetDecryptionKey instance method!");
            }

            Span <byte> updateList = File.ReadAllBytes(FilePath);

            for (int i = 0; i < updateList.Length; i += 8)
            {
                Span <byte> chunk     = updateList.Slice(i, 8);
                Span <uint> decrypted = XTEA.Decipher(16, MemoryMarshal.Cast <byte, uint>(chunk).ToArray(), DecryptionKey);
                Span <byte> resource  = MemoryMarshal.AsBytes(decrypted);
                resource.CopyTo(chunk);
            }

            Document = Encoding.UTF8.GetString(updateList.ToArray());
        }