示例#1
0
        public static HashSet <string> GetAllStringsFromAllXmls(string gameDirectoryName)
        {
            var xmlStrings = new HashSet <string>();

            ArchiveUtilities.ForEachBinaryFile(gameDirectoryName, (fullFileName, file, encryption) =>
            {
                if (file.Name.EndsWith(".meta", StringComparison.OrdinalIgnoreCase) ||
                    file.Name.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
                {
                    var fileStream = new MemoryStream();
                    file.Export(fileStream);

                    var buf             = new byte[fileStream.Length];
                    fileStream.Position = 0;
                    fileStream.Read(buf, 0, buf.Length);

                    if (file.IsEncrypted)
                    {
                        if (encryption == RageArchiveEncryption7.AES)
                        {
                            buf = AesEncryption.DecryptData(buf, GTA5Constants.PC_AES_KEY);
                        }
                        else
                        {
                            var qq = GTA5Hash.CalculateHash(file.Name);
                            var gg = (qq + (uint)file.UncompressedSize + (101 - 40)) % 0x65;
                            buf    = GTA5Crypto.Decrypt(buf, GTA5Constants.PC_NG_KEYS[gg]);
                        }
                    }

                    if (file.IsCompressed)
                    {
                        var def    = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress);
                        var bufnew = new byte[file.UncompressedSize];
                        def.Read(bufnew, 0, (int)file.UncompressedSize);
                        buf = bufnew;
                    }

                    var cleanedStream = new MemoryStream(buf);
                    foreach (string xmlString in GetAllStringsFromXml(cleanedStream))
                    {
                        xmlStrings.Add(xmlString);
                    }

                    Console.WriteLine(file.Name);
                }
            });

            return(xmlStrings);
        }
示例#2
0
        /// <summary>
        /// Exports a file.
        /// </summary>
        public void Export(IArchiveFile file, string fileName)
        {
            if (file is IArchiveBinaryFile)
            {
                var binFile = (IArchiveBinaryFile)file;

                // export
                var ms = new MemoryStream();
                file.Export(ms);
                ms.Position = 0;

                var buf = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(buf, 0, buf.Length);

                // decrypt...
                if (binFile.IsEncrypted)
                {
                    var qq = GTA5Hash.CalculateHash(binFile.Name);
                    var gg = (qq + (uint)binFile.UncompressedSize + (101 - 40)) % 0x65;

                    // TODO: if archive encrypted with AES, use AES key...

                    buf = GTA5Crypto.Decrypt(buf, GTA5Constants.PC_NG_KEYS[gg]);
                }

                // decompress...
                if (binFile.IsCompressed)
                {
                    var def    = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress);
                    var bufnew = new byte[binFile.UncompressedSize];
                    def.Read(bufnew, 0, (int)binFile.UncompressedSize);
                    buf = bufnew;
                }

                File.WriteAllBytes(fileName, buf);
            }
            else
            {
                file.Export(fileName);
            }
        }
示例#3
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            var reader = new DataReader(BaseStream);
            var posbak = reader.Position;

            reader.Position = 0;

            uint header_identifier = reader.ReadUInt32(); // 0x52504637

            if (header_identifier != IDENT)
            {
                throw new Exception("The identifier " + header_identifier.ToString("X8") + " did not match the expected value of 0x52504637");
            }

            uint header_entriesCount = reader.ReadUInt32();
            uint header_namesLength  = reader.ReadUInt32();
            uint header_encryption   = reader.ReadUInt32();

            byte[] entries_data_dec = null;
            byte[] names_data_dec   = null;

            if (header_encryption == 0x04E45504F) // for OpenIV compatibility
            {
                // no encryption...
                Encryption       = RageArchiveEncryption7.None;
                entries_data_dec = reader.ReadBytes(16 * (int)header_entriesCount);
                names_data_dec   = reader.ReadBytes((int)header_namesLength);
            }
            else if (header_encryption == 0x0ffffff9)
            {
                // AES enceyption...

                Encryption = RageArchiveEncryption7.AES;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = AesEncryption.DecryptData(entries_data, aesKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = AesEncryption.DecryptData(names_data, aesKey);
            }
            else
            {
                // NG encryption...

                Encryption = RageArchiveEncryption7.NG;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = GTA5Crypto.Decrypt(entries_data, ngKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = GTA5Crypto.Decrypt(names_data, ngKey);
            }

            var entries_reader = new DataReader(new MemoryStream(entries_data_dec));
            var names_reader   = new DataReader(new MemoryStream(names_data_dec));

            var entries = new List <IRageArchiveEntry7>();

            for (var index = 0; index < header_entriesCount; index++)
            {
                entries_reader.Position += 4;
                int x = entries_reader.ReadInt32();
                entries_reader.Position -= 8;

                if (x == 0x7fffff00)
                {
                    // directory
                    var e = new RageArchiveDirectory7();
                    e.Read(entries_reader);

                    names_reader.Position = e.NameOffset;
                    e.Name = names_reader.ReadString();

                    entries.Add(e);
                }
                else
                {
                    if ((x & 0x80000000) == 0)
                    {
                        // binary file
                        var e = new RageArchiveBinaryFile7();
                        e.Read(entries_reader);

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                    else
                    {
                        // resource file
                        var e = new RageArchiveResourceFile7();
                        e.Read(entries_reader);

                        // there are sometimes resources with length=0xffffff which actually
                        // means length>=0xffffff
                        if (e.FileSize == 0xFFFFFF)
                        {
                            reader.Position = 512 * e.FileOffset;
                            var buf = reader.ReadBytes(16);
                            e.FileSize = ((uint)buf[7] << 0) | ((uint)buf[14] << 8) | ((uint)buf[5] << 16) | ((uint)buf[2] << 24);
                        }

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                }
            }

            var stack = new Stack <RageArchiveDirectory7>();

            stack.Push((RageArchiveDirectory7)entries[0]);
            Root = (RageArchiveDirectory7)entries[0];
            while (stack.Count > 0)
            {
                var item = stack.Pop();

                for (int index = (int)item.EntriesIndex; index < (item.EntriesIndex + item.EntriesCount); index++)
                {
                    if (entries[index] is RageArchiveDirectory7)
                    {
                        item.Directories.Add(entries[index] as RageArchiveDirectory7);
                        stack.Push(entries[index] as RageArchiveDirectory7);
                    }
                    else
                    {
                        item.Files.Add(entries[index]);
                    }
                }
            }

            reader.Position = posbak;
        }
示例#4
0
        public static HashSet <int> GetAllHashesFromPsoMetas(string gameDirectoryName)
        {
            var hashes = new HashSet <int>();

            ArchiveUtilities.ForEachBinaryFile(gameDirectoryName, (fullFileName, file, encryption) =>
            {
                if (file.Name.EndsWith(".ymf") || file.Name.EndsWith(".ymt"))
                {
                    var stream = new MemoryStream();
                    file.Export(stream);

                    var buf         = new byte[stream.Length];
                    stream.Position = 0;
                    stream.Read(buf, 0, buf.Length);

                    if (file.IsEncrypted)
                    {
                        if (encryption == RageArchiveEncryption7.AES)
                        {
                            buf = AesEncryption.DecryptData(buf, GTA5Constants.PC_AES_KEY);
                        }
                        else
                        {
                            var qq = GTA5Hash.CalculateHash(file.Name);
                            var gg = (qq + (uint)file.UncompressedSize + (101 - 40)) % 0x65;
                            buf    = GTA5Crypto.Decrypt(buf, GTA5Constants.PC_NG_KEYS[gg]);
                        }
                    }

                    if (file.IsCompressed)
                    {
                        var def    = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress);
                        var bufnew = new byte[file.UncompressedSize];
                        def.Read(bufnew, 0, (int)file.UncompressedSize);
                        buf = bufnew;
                    }

                    var cleanStream = new MemoryStream(buf);
                    if (PsoFile.IsPSO(cleanStream))
                    {
                        PsoFile pso = new PsoFile();
                        pso.Load(cleanStream);

                        foreach (var info in pso.DefinitionSection.EntriesIdx)
                        {
                            hashes.Add(info.NameHash);
                        }
                        foreach (var info in pso.DefinitionSection.Entries)
                        {
                            if (info is PsoStructureInfo)
                            {
                                var structureInfo = (PsoStructureInfo)info;
                                foreach (var entryInfo in structureInfo.Entries)
                                {
                                    hashes.Add(entryInfo.EntryNameHash);
                                }
                            }

                            if (info is PsoEnumInfo)
                            {
                                var enumInfo = (PsoEnumInfo)info;
                                foreach (var entryInfo in enumInfo.Entries)
                                {
                                    hashes.Add(entryInfo.EntryNameHash);
                                }
                            }
                        }

                        Console.WriteLine(file.Name);
                    }
                }
            });
            return(hashes);
        }
示例#5
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            DataReader dataReader = new DataReader(this.BaseStream, Endianess.LittleEndian);
            long       position   = dataReader.Position;

            dataReader.Position = 0L;
            uint num = dataReader.ReadUInt32();

            if (num != 0x52504637)
            {
                throw new Exception("The identifier " + num.ToString("X8") + " did not match the expected value of 0x52504637");
            }
            uint num2  = dataReader.ReadUInt32();
            uint count = dataReader.ReadUInt32();
            uint num3  = dataReader.ReadUInt32();

            byte[] buffer;
            byte[] buffer2;
            if (num3 == 0x4E45504F)
            {
                this.Encryption = RageArchiveEncryption7.None;
                buffer          = dataReader.ReadBytes(16 * (int)num2);
                buffer2         = dataReader.ReadBytes((int)count);
            }
            else if (num3 == 0x0FFFFFF9)
            {
                this.Encryption = RageArchiveEncryption7.AES;
                byte[] data = dataReader.ReadBytes(16 * (int)num2);
                buffer = AesEncryption.DecryptData(data, aesKey, 1);
                byte[] data2 = dataReader.ReadBytes((int)count);
                buffer2 = AesEncryption.DecryptData(data2, aesKey, 1);
            }
            else
            {
                this.Encryption = RageArchiveEncryption7.NG;
                byte[] data3 = dataReader.ReadBytes(16 * (int)num2);
                buffer = GTA5Crypto.Decrypt(data3, ngKey);
                byte[] data4 = dataReader.ReadBytes((int)count);
                buffer2 = GTA5Crypto.Decrypt(data4, ngKey);
            }
            DataReader dataReader2         = new DataReader(new MemoryStream(buffer), Endianess.LittleEndian);
            DataReader dataReader3         = new DataReader(new MemoryStream(buffer2), Endianess.LittleEndian);
            List <IRageArchiveEntry7> list = new List <IRageArchiveEntry7>();
            int num4 = 0;

            while (num4 < num2)
            {
                dataReader2.Position += 4L;
                int num5 = dataReader2.ReadInt32();
                dataReader2.Position -= 8L;
                if (num5 == 0x7FFFFF00)
                {
                    RageArchiveDirectory7 rageArchiveDirectory = new RageArchiveDirectory7();
                    rageArchiveDirectory.Read(dataReader2);
                    dataReader3.Position      = (long)((ulong)rageArchiveDirectory.NameOffset);
                    rageArchiveDirectory.Name = dataReader3.ReadString();
                    list.Add(rageArchiveDirectory);
                }
                else if ((num5 & 0x80000000) == 0L)
                {
                    RageArchiveBinaryFile7 rageArchiveBinaryFile = new RageArchiveBinaryFile7();
                    rageArchiveBinaryFile.Read(dataReader2);
                    dataReader3.Position       = rageArchiveBinaryFile.NameOffset;
                    rageArchiveBinaryFile.Name = dataReader3.ReadString();
                    list.Add(rageArchiveBinaryFile);
                }
                else
                {
                    RageArchiveResourceFile7 rageArchiveResourceFile = new RageArchiveResourceFile7();
                    rageArchiveResourceFile.Read(dataReader2);
                    if (rageArchiveResourceFile.FileSize == 0x00FFFFFF)
                    {
                        dataReader.Position = 512 * rageArchiveResourceFile.FileOffset;
                        byte[] array = dataReader.ReadBytes(16);
                        rageArchiveResourceFile.FileSize = (uint)(array[7] | array[14] << 8 | array[5] << 16 | array[2] << 24);
                    }
                    dataReader3.Position         = rageArchiveResourceFile.NameOffset;
                    rageArchiveResourceFile.Name = dataReader3.ReadString();
                    list.Add(rageArchiveResourceFile);
                }
                num4++;
            }
            Stack <RageArchiveDirectory7> stack = new Stack <RageArchiveDirectory7>();

            stack.Push((RageArchiveDirectory7)list[0]);
            this.Root = (RageArchiveDirectory7)list[0];
            while (stack.Count > 0)
            {
                RageArchiveDirectory7 rageArchiveDirectory2 = stack.Pop();
                int num6 = (int)rageArchiveDirectory2.EntriesIndex;
                while ((long)num6 < (long)((ulong)(rageArchiveDirectory2.EntriesIndex + rageArchiveDirectory2.EntriesCount)))
                {
                    if (list[num6] is RageArchiveDirectory7)
                    {
                        rageArchiveDirectory2.Directories.Add(list[num6] as RageArchiveDirectory7);
                        stack.Push(list[num6] as RageArchiveDirectory7);
                    }
                    else
                    {
                        rageArchiveDirectory2.Files.Add(list[num6]);
                    }
                    num6++;
                }
            }
            dataReader.Position = position;
        }
示例#6
0
        public static Tuple <Dictionary <int, PsoStructureInfo>, Dictionary <int, PsoEnumInfo> > GetAllStructureInfoAndEnumInfoFromPsoMetas(string gameDirectoryName)
        {
            Dictionary <int, PsoStructureInfo> structureInfos = new Dictionary <int, PsoStructureInfo>();
            Dictionary <int, PsoEnumInfo>      enumInfos      = new Dictionary <int, PsoEnumInfo>();

            ArchiveUtilities.ForEachBinaryFile(gameDirectoryName, (fullFileName, file, encryption) =>
            {
                if (file.Name.EndsWith(".ymf") || file.Name.EndsWith(".ymt"))
                {
                    var stream = new MemoryStream();
                    file.Export(stream);

                    var buf         = new byte[stream.Length];
                    stream.Position = 0;
                    stream.Read(buf, 0, buf.Length);

                    if (file.IsEncrypted)
                    {
                        if (encryption == RageArchiveEncryption7.AES)
                        {
                            buf = AesEncryption.DecryptData(buf, GTA5Constants.PC_AES_KEY);
                        }
                        else
                        {
                            var indexKey = GTA5Crypto.GetKeyIndex(file.Name, (uint)file.UncompressedSize);
                            buf          = GTA5Crypto.Decrypt(buf, GTA5Constants.PC_NG_KEYS[indexKey]);
                        }
                    }

                    if (file.IsCompressed)
                    {
                        var def    = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress);
                        var bufnew = new byte[file.UncompressedSize];
                        def.Read(bufnew, 0, (int)file.UncompressedSize);
                        buf = bufnew;
                    }

                    var cleanStream = new MemoryStream(buf);
                    if (PsoFile.IsPSO(cleanStream))
                    {
                        PsoFile pso = new PsoFile();
                        pso.Load(cleanStream);

                        for (int i = 0; i < pso.DefinitionSection.Count; i++)
                        {
                            var id = pso.DefinitionSection.EntriesIdx[i];

                            var info = pso.DefinitionSection.Entries[i];

                            if (info is PsoStructureInfo structureInfo)
                            {
                                structureInfos.TryAdd(id.NameHash, structureInfo);
                            }

                            if (info is PsoEnumInfo enumInfo)
                            {
                                enumInfos.TryAdd(id.NameHash, enumInfo);
                            }
                        }

                        Console.WriteLine(file.Name);
                    }
                }
            });

            return(new Tuple <Dictionary <int, PsoStructureInfo>, Dictionary <int, PsoEnumInfo> >(structureInfos, enumInfos));
        }