/// <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(); }
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); } }
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; } }
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; } }
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); }
/// <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); } }
/// <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; }
/// <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; }
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); }
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); }
/// <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; }
/// <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; }
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); }
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)); }