예제 #1
0
        /// <summary>
        /// Clears all buffers for this archive and causes any buffered data to be
        /// written to the underlying device.
        /// </summary>
        public void Flush()
        {
            long headerSize = GetHeaderSize();

            do
            {
                var  blocks          = GetBlocks();
                long maxheaderlength = ArchiveHelpers.FindSpace(blocks, blocks[0]);
                if (maxheaderlength < headerSize)
                {
                    long newpos = ArchiveHelpers.FindOffset(blocks, blocks[1].Length, 512);
                    ArchiveHelpers.MoveBytes(archive_.BaseStream, blocks[1].Offset, newpos, blocks[1].Length);
                    ((IRageArchiveFileEntry7)blocks[1].Tag).FileOffset = (uint)(newpos / 512);

                    blocks          = GetBlocks();
                    maxheaderlength = ArchiveHelpers.FindSpace(blocks, blocks[0]);
                }
                else
                {
                    break;
                }
            } while (true);



            // calculate key...
            var indexKey = GTA5Crypto.GetKeyIndex(FileName, (uint)archive_.BaseStream.Length);

            //  archive_.key_ = GTA5Crypto.key_gta5;
            archive_.WriteHeader(GTA5Constants.PC_AES_KEY, GTA5Constants.PC_NG_KEYS[indexKey]);
            archive_.BaseStream.Flush();
        }
예제 #2
0
        public static byte[] GetBinaryFileData(IArchiveBinaryFile file, RageArchiveEncryption7 encryption)
        {
            using (var ms = new MemoryStream())
            {
                file.Export(ms);

                byte[] data = ms.ToArray();

                if (file.IsEncrypted)
                {
                    if (encryption == RageArchiveEncryption7.AES)
                    {
                        data = GTA5Crypto.DecryptAES(data);
                    }
                    else // if(encryption == RageArchiveEncryption7.NG)
                    {
                        data = GTA5Crypto.DecryptNG(data, file.Name, (uint)file.UncompressedSize);
                    }
                }

                if (file.IsCompressed)
                {
                    using (var dfls = new DeflateStream(new MemoryStream(data), CompressionMode.Decompress))
                    {
                        using (var outstr = new MemoryStream())
                        {
                            dfls.CopyTo(outstr);
                            data = outstr.ToArray();
                        }
                    }
                }

                return(data);
            }
        }
예제 #3
0
        public static RageArchiveWrapper7 Open(Stream stream, string fileName, bool leaveOpen = false)
        {
            var arch = new RageArchiveWrapper7(stream, fileName, leaveOpen);

            try
            {
                if (GTA5Constants.PC_LUT != null && GTA5Constants.PC_NG_KEYS != null)
                {
                    // calculate key...
                    var indexKey = GTA5Crypto.GetKeyIndex(arch.FileName, (uint)stream.Length);

                    arch.archive_.ReadHeader(GTA5Constants.PC_AES_KEY, GTA5Constants.PC_NG_KEYS[indexKey]); // read...
                }
                else
                {
                    arch.archive_.ReadHeader(GTA5Constants.PC_AES_KEY, null); // read...
                }

                return(arch);
            }
            catch
            {
                arch.Dispose();
                throw;
            }
        }
예제 #4
0
        public static RageArchiveWrapper7 Open(string fileName)
        {
            var finfo = new FileInfo(fileName);
            var fs    = new FileStream(fileName, FileMode.Open);
            var arch  = new RageArchiveWrapper7(fs, finfo.Name, false);

            try
            {
                if (GTA5Constants.PC_LUT != null && GTA5Constants.PC_NG_KEYS != null)
                {
                    // calculate key...
                    var indexKey = GTA5Crypto.GetKeyIndex(arch.FileName, (uint)finfo.Length);

                    arch.archive_.ReadHeader(GTA5Constants.PC_AES_KEY, GTA5Constants.PC_NG_KEYS[indexKey]); // read...
                }
                else
                {
                    arch.archive_.ReadHeader(GTA5Constants.PC_AES_KEY, null); // read...
                }


                return(arch);
            }
            catch
            {
                fs.Dispose();
                arch.Dispose();
                throw;
            }
        }
예제 #5
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);
        }
예제 #6
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);
            }
        }
예제 #7
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;
        }
예제 #8
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            // backup position
            var positionBackup = BaseStream.Position;

            var writer = new DataWriter(BaseStream);


            var entries    = new List <IRageArchiveEntry7>();
            var stack      = new Stack <RageArchiveDirectory7>();
            var nameOffset = 1;


            entries.Add(Root);
            stack.Push(Root);

            var nameDict = new Dictionary <string, uint>();

            nameDict.Add("", 0);

            while (stack.Count > 0)
            {
                var directory = stack.Pop();

                directory.EntriesIndex = (uint)entries.Count;
                directory.EntriesCount = (uint)directory.Directories.Count + (uint)directory.Files.Count;

                var theList = new List <IRageArchiveEntry7>();

                foreach (var xd in directory.Directories)
                {
                    if (!nameDict.ContainsKey(xd.Name))
                    {
                        nameDict.Add(xd.Name, (uint)nameOffset);
                        nameOffset += xd.Name.Length + 1;
                    }
                    xd.NameOffset = nameDict[xd.Name];

                    //xd.NameOffset = (ushort)nameOffset;
                    //nameOffset += xd.Name.Length + 1;
                    //entries.Add(xd);
                    //stack.Push(xd);
                    theList.Add(xd);
                }

                foreach (var xf in directory.Files)
                {
                    if (!nameDict.ContainsKey(xf.Name))
                    {
                        nameDict.Add(xf.Name, (uint)nameOffset);
                        nameOffset += xf.Name.Length + 1;
                    }
                    xf.NameOffset = nameDict[xf.Name];

                    //xf.NameOffset = (ushort)nameOffset;
                    //nameOffset += xf.Name.Length + 1;
                    //entries.Add(xf);
                    theList.Add(xf);
                }

                theList.Sort(
                    delegate(IRageArchiveEntry7 a, IRageArchiveEntry7 b)
                {
                    return(string.CompareOrdinal(a.Name, b.Name));
                }
                    );
                foreach (var xx in theList)
                {
                    entries.Add(xx);
                }
                theList.Reverse();
                foreach (var xx in theList)
                {
                    if (xx is RageArchiveDirectory7)
                    {
                        stack.Push((RageArchiveDirectory7)xx);
                    }
                }
            }


            // there are sometimes resources with length>=0xffffff which actually
            // means length=0xffffff
            // -> we therefore just cut the file size
            foreach (var entry in entries)
            {
                if (entry is RageArchiveResourceFile7)
                {
                    var resource = entry as RageArchiveResourceFile7;
                    if (resource.FileSize > 0xFFFFFF)
                    {
                        var buf = new byte[16];
                        buf[7]  = (byte)((resource.FileSize >> 0) & 0xFF);
                        buf[14] = (byte)((resource.FileSize >> 8) & 0xFF);
                        buf[5]  = (byte)((resource.FileSize >> 16) & 0xFF);
                        buf[2]  = (byte)((resource.FileSize >> 24) & 0xFF);

                        if (writer.Length > 512 * resource.FileOffset)
                        {
                            writer.Position = 512 * resource.FileOffset;
                            writer.Write(buf);
                        }

                        resource.FileSize = 0xFFFFFF;
                    }
                }
            }


            // entries...
            var ent_str = new MemoryStream();
            var ent_wr  = new DataWriter(ent_str);

            foreach (var entry in entries)
            {
                entry.Write(ent_wr);
            }
            ent_str.Flush();

            var ent_buf = new byte[ent_str.Length];

            ent_str.Position = 0;
            ent_str.Read(ent_buf, 0, ent_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
            {
                ent_buf = AesEncryption.EncryptData(ent_buf, aesKey);
            }
            else if (Encryption == RageArchiveEncryption7.NG)
            {
                ent_buf = GTA5Crypto.Encrypt(ent_buf, ngKey);
            }

            // names...
            var n_str = new MemoryStream();
            var n_wr  = new DataWriter(n_str);

            //foreach (var entry in entries)
            //    n_wr.Write(entry.Name);
            foreach (var entry in nameDict)
            {
                n_wr.Write(entry.Key);
            }
            var empty = new byte[16 - (n_wr.Length % 16)];

            n_wr.Write(empty);
            n_str.Flush();

            var n_buf = new byte[n_str.Length];

            n_str.Position = 0;
            n_str.Read(n_buf, 0, n_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
            {
                n_buf = AesEncryption.EncryptData(n_buf, aesKey);
            }
            else if (Encryption == RageArchiveEncryption7.NG)
            {
                n_buf = GTA5Crypto.Encrypt(n_buf, ngKey);
            }

            writer.Position = 0;
            writer.Write((uint)IDENT);
            writer.Write((uint)entries.Count);
            writer.Write((uint)n_buf.Length);

            switch (Encryption)
            {
            case RageArchiveEncryption7.None:
                writer.Write((uint)0x04E45504F);
                break;

            case RageArchiveEncryption7.AES:
                writer.Write((uint)0x0ffffff9);
                break;

            case RageArchiveEncryption7.NG:
                writer.Write((uint)0x0fefffff);
                break;
            }

            writer.Write(ent_buf);
            writer.Write(n_buf);



            // restore position
            BaseStream.Position = positionBackup;
        }
예제 #9
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);
        }
예제 #10
0
        public static bool[] Solve(uint[][] tables, int inByte0, int inByte1, int inByte2, int inByte3, int outByte, int outBit)
        {
            uint[] key    = new uint[4];
            Random random = new Random();
            List <RandomGaussRow> list           = new List <RandomGaussRow>();
            RandomGaussRow        randomGaussRow = new RandomGaussRow();

            randomGaussRow.SetA(0);
            randomGaussRow.SetB();
            list.Add(randomGaussRow);
            byte[] array = new byte[16];
            for (int i = 1; i < 1024; i++)
            {
                RandomGaussRow randomGaussRow2;
                do
                {
                    random.NextBytes(array);
                    byte[] array2 = GTA5Crypto.DecryptRoundA(array, key, tables);
                    randomGaussRow2 = new RandomGaussRow();
                    randomGaussRow2.SetA((int)array2[inByte0]);
                    randomGaussRow2.SetA(256 + (int)array2[inByte1]);
                    randomGaussRow2.SetA(512 + (int)array2[inByte2]);
                    randomGaussRow2.SetA(768 + (int)array2[inByte3]);
                    if (((int)array[outByte] & 1 << outBit) != 0)
                    {
                        randomGaussRow2.SetB();
                    }
                    if (i == 767)
                    {
                        randomGaussRow2 = new RandomGaussRow();
                        randomGaussRow2.SetA(767);
                        randomGaussRow2.SetB();
                    }
                    if (i == 1023)
                    {
                        randomGaussRow2 = new RandomGaussRow();
                        randomGaussRow2.SetA(1023);
                        randomGaussRow2.SetB();
                    }
                    for (int j = 0; j < i; j++)
                    {
                        if (randomGaussRow2.GetA(j))
                        {
                            randomGaussRow2 ^= list[j];
                        }
                    }
                }while (!randomGaussRow2.GetA(i));
                list.Add(randomGaussRow2);
            }
            bool[] array3 = new bool[1024];
            for (int k = 1023; k >= 0; k--)
            {
                bool b = list[k].GetB();
                array3[k] = b;
                for (int l = 0; l < k; l++)
                {
                    if (list[l].GetA(k))
                    {
                        list[l].B ^= b;
                    }
                }
            }
            return(array3);
        }
예제 #11
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;
        }
예제 #12
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            long       position   = this.BaseStream.Position;
            DataWriter dataWriter = new DataWriter(this.BaseStream, Endianess.LittleEndian);
            List <IRageArchiveEntry7>     list  = new List <IRageArchiveEntry7>();
            Stack <RageArchiveDirectory7> stack = new Stack <RageArchiveDirectory7>();
            int num = 1;

            list.Add(this.Root);
            stack.Push(this.Root);
            Dictionary <string, uint> dictionary = new Dictionary <string, uint>();

            dictionary.Add("", 0);
            while (stack.Count > 0)
            {
                RageArchiveDirectory7 rageArchiveDirectory = stack.Pop();
                rageArchiveDirectory.EntriesIndex = (uint)list.Count;
                rageArchiveDirectory.EntriesCount = (uint)(rageArchiveDirectory.Directories.Count + rageArchiveDirectory.Files.Count);
                List <IRageArchiveEntry7> list2 = new List <IRageArchiveEntry7>();
                foreach (RageArchiveDirectory7 rageArchiveDirectory2 in rageArchiveDirectory.Directories)
                {
                    if (!dictionary.ContainsKey(rageArchiveDirectory2.Name))
                    {
                        dictionary.Add(rageArchiveDirectory2.Name, (uint)num);
                        num += rageArchiveDirectory2.Name.Length + 1;
                    }
                    rageArchiveDirectory2.NameOffset = dictionary[rageArchiveDirectory2.Name];
                    list2.Add(rageArchiveDirectory2);
                }
                foreach (IRageArchiveEntry7 rageArchiveEntry in rageArchiveDirectory.Files)
                {
                    if (!dictionary.ContainsKey(rageArchiveEntry.Name))
                    {
                        dictionary.Add(rageArchiveEntry.Name, (uint)num);
                        num += rageArchiveEntry.Name.Length + 1;
                    }
                    rageArchiveEntry.NameOffset = dictionary[rageArchiveEntry.Name];
                    list2.Add(rageArchiveEntry);
                }
                list2.Sort((IRageArchiveEntry7 a, IRageArchiveEntry7 b) => string.CompareOrdinal(a.Name, b.Name));
                foreach (IRageArchiveEntry7 item in list2)
                {
                    list.Add(item);
                }
                list2.Reverse();
                foreach (IRageArchiveEntry7 rageArchiveEntry2 in list2)
                {
                    if (rageArchiveEntry2 is RageArchiveDirectory7)
                    {
                        stack.Push((RageArchiveDirectory7)rageArchiveEntry2);
                    }
                }
            }
            foreach (IRageArchiveEntry7 rageArchiveEntry3 in list)
            {
                if (rageArchiveEntry3 is RageArchiveResourceFile7)
                {
                    RageArchiveResourceFile7 rageArchiveResourceFile = rageArchiveEntry3 as RageArchiveResourceFile7;
                    if (rageArchiveResourceFile.FileSize > 0x00FFFFFF)
                    {
                        byte[] array = new byte[16];
                        array[7]  = (byte)(rageArchiveResourceFile.FileSize & 255);
                        array[14] = (byte)(rageArchiveResourceFile.FileSize >> 8 & 255);
                        array[5]  = (byte)(rageArchiveResourceFile.FileSize >> 16 & 255);
                        array[2]  = (byte)(rageArchiveResourceFile.FileSize >> 24 & 255);
                        if (dataWriter.Length > (512 * rageArchiveResourceFile.FileOffset))
                        {
                            dataWriter.Position = (512 * rageArchiveResourceFile.FileOffset);
                            dataWriter.Write(array);
                        }
                        rageArchiveResourceFile.FileSize = 0x00FFFFFF;
                    }
                }
            }
            MemoryStream memoryStream = new MemoryStream();
            DataWriter   writer       = new DataWriter(memoryStream, Endianess.LittleEndian);

            foreach (IRageArchiveEntry7 rageArchiveEntry4 in list)
            {
                rageArchiveEntry4.Write(writer);
            }
            memoryStream.Flush();
            byte[] array2 = new byte[memoryStream.Length];
            memoryStream.Position = 0L;
            memoryStream.Read(array2, 0, array2.Length);
            if (this.Encryption == RageArchiveEncryption7.AES)
            {
                array2 = AesEncryption.EncryptData(array2, aesKey, 1);
            }
            if (this.Encryption == RageArchiveEncryption7.NG)
            {
                array2 = GTA5Crypto.Encrypt(array2, ngKey);
            }
            MemoryStream memoryStream2 = new MemoryStream();
            DataWriter   dataWriter2   = new DataWriter(memoryStream2, Endianess.LittleEndian);

            foreach (KeyValuePair <string, uint> keyValuePair in dictionary)
            {
                dataWriter2.Write(keyValuePair.Key);
            }
            byte[] value = new byte[16L - dataWriter2.Length % 16L];
            dataWriter2.Write(value);
            memoryStream2.Flush();
            byte[] array3 = new byte[memoryStream2.Length];
            memoryStream2.Position = 0L;
            memoryStream2.Read(array3, 0, array3.Length);
            if (this.Encryption == RageArchiveEncryption7.AES)
            {
                array3 = AesEncryption.EncryptData(array3, aesKey, 1);
            }
            if (this.Encryption == RageArchiveEncryption7.NG)
            {
                array3 = GTA5Crypto.Encrypt(array3, ngKey);
            }
            dataWriter.Position = 0L;
            dataWriter.Write(0x52504637);
            dataWriter.Write((uint)list.Count);
            dataWriter.Write((uint)array3.Length);
            switch (this.Encryption)
            {
            case RageArchiveEncryption7.None:
                dataWriter.Write(0x4E45504F);
                break;

            case RageArchiveEncryption7.AES:
                dataWriter.Write(0x0FFFFFF9);
                break;

            case RageArchiveEncryption7.NG:
                dataWriter.Write(0x0FEFFFFF);
                break;
            }
            dataWriter.Write(array2);
            dataWriter.Write(array3);
            this.BaseStream.Position = position;
        }
예제 #13
0
        public static bool[] Solve(
            uint[][] tables,
            int inByte0, int inByte1, int inByte2, int inByte3,
            int outByte, int outBit)
        {
            var noKey  = new uint[] { 0, 0, 0, 0 };
            var random = new Random();

            var pivots = new List <RandomGaussRow>();

            var firstPivot = new RandomGaussRow();

            firstPivot.SetA(0);
            firstPivot.SetB();
            pivots.Add(firstPivot);

            var buf_encrypted = new byte[16];

            for (int pivotIdx = 1; pivotIdx < 1024; pivotIdx++)
            {
                while (true)
                {
                    random.NextBytes(buf_encrypted);

                    // decrypt
                    var buf_decrypted = GTA5Crypto.DecryptRoundA(
                        buf_encrypted,
                        noKey,
                        tables);

                    // make row
                    var row = new RandomGaussRow();
                    //row.A[0 + buf_decrypted[inByte0]] = true;
                    //row.A[256 + buf_decrypted[inByte1]] = true;
                    //row.A[512 + buf_decrypted[inByte2]] = true;
                    //row.A[768 + buf_decrypted[inByte3]] = true;
                    //row.B = (buf_encrypted[outByte] & (1 << outBit)) != 0;
                    row.SetA(0 + buf_decrypted[inByte0]);
                    row.SetA(256 + buf_decrypted[inByte1]);
                    row.SetA(512 + buf_decrypted[inByte2]);
                    row.SetA(768 + buf_decrypted[inByte3]);
                    if ((buf_encrypted[outByte] & (1 << outBit)) != 0)
                    {
                        row.SetB();
                    }

                    if (pivotIdx == 0x2ff)
                    {
                        row = new RandomGaussRow();
                        row.SetA(0x2ff);
                        row.SetB();
                    }
                    if (pivotIdx == 0x3ff)
                    {
                        row = new RandomGaussRow();
                        row.SetA(0x3ff);
                        row.SetB();
                    }

                    // apply pivotIdx-1 pivots
                    for (int k = 0; k < pivotIdx; k++)
                    {
                        if (row.GetA(k))
                        {
                            row ^= pivots[k];
                            //var ppp = pivots[k];
                            //for (int p = 0; p < 1024; p++)
                            //    row.A[p] ^= ppp.A[p];
                            //row.B ^= ppp.B;
                        }
                    }

                    // check if this row is a new pivot
                    if (row.GetA(pivotIdx))
                    {
                        pivots.Add(row);
                        //    Console.WriteLine("Found pivot for column " + pivotIdx.ToString());
                        break;
                    }
                }
            }

            var result = new bool[1024];

            for (int j = 1023; j >= 0; j--)
            {
                bool val = pivots[j].GetB();
                result[j] = val;
                for (int k = 0; k < j; k++)
                {
                    if (pivots[k].GetA(j))
                    {
                        pivots[k].B ^= val;
                    }
                }
            }

            return(result);
        }
예제 #14
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));
        }