не могу открыть rpf архив не выкупаю что не так
C#:
using System;
using System.IO;
using RageLib.Archives;
using RageLib.GTA5.Archives;
using RageLib.GTA5.Cryptography;
using RageLib.GTA5.Utilities;
using RageLib.Cryptography;
public class RpfReader
{
public static void Main(string[] args)
{
string rpfFilePath = "D:/SteamLibrary/steamapps/common/Grand Theft Auto V/mods/x64e.rpf";
Console.WriteLine($"File path: {rpfFilePath}");
try
{
// Инициализируем ключи на основе анализа DLL
InitializeKeys();
// Проверяем инициализацию
if (GTA5Constants.PC_NG_KEYS == null || GTA5Constants.PC_NG_DECRYPT_TABLES == null)
{
Console.WriteLine("Ошибка: Не удалось инициализировать ключи");
return;
}
Console.WriteLine("Ключи успешно инициализированы");
Console.WriteLine($"Количество NG ключей: {GTA5Constants.PC_NG_KEYS.Length}");
using (var stream = File.OpenRead(rpfFilePath))
{
Console.WriteLine($"Размер файла: {stream.Length:N0} bytes");
Console.WriteLine("Открываем архив с NG шифрованием...");
try
{
var archive = new RageArchive7(stream, true);
if (archive.Root != null)
{
ProcessDirectory(archive.Root, "");
}
else
{
Console.WriteLine("Ошибка: Корневой каталог архива не найден");
}
}
catch (Exception ex)
{
Console.WriteLine($"Ошибка при открытии архива: {ex.Message}");
Console.WriteLine($"StackTrace: {ex.StackTrace}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Произошла ошибка: {ex.Message}");
Console.WriteLine($"StackTrace: {ex.StackTrace}");
}
}
private static void InitializeKeys()
{
// AES ключ из анализа DLL
var aesKey = new byte[]
{
0x28, 0xCA, 0x2E, 0xFF, 0x09, 0xF6, 0x0D, 0xA3,
0x39, 0x06, 0x31, 0x79, 0x27, 0x92, 0xC3, 0x7A,
0x24, 0x99, 0xF2, 0x95, 0xD4, 0x00, 0xF4, 0x00,
0x52, 0xA0, 0x40, 0xB1, 0xD7, 0xD0, 0xAC, 0x03
};
GTA5Constants.PC_AES_KEY = aesKey;
// NG ключ (полные 256 байт)
var ngKey = new byte[256];
var baseKey = new byte[]
{
0xB1, 0x51, 0x81, 0x7B, 0xCC, 0xA7, 0xED, 0xAE,
0x23, 0xA8, 0x6D, 0x03, 0x8B, 0x7E, 0x43, 0x2F,
0x66, 0x6A, 0x4B, 0x2B, 0x6E, 0x61, 0x9D, 0xC0,
0xBE, 0x5F, 0x61, 0x72, 0x3D, 0x74, 0xEF, 0x1F,
0x4F, 0x06, 0x4A, 0x02, 0x4E, 0xE6, 0xA0, 0x18,
0x97, 0xC4, 0x49, 0xE8, 0xD6, 0xB0, 0xE8, 0x75,
0xB1, 0xD4, 0x49, 0x0A, 0x4E, 0x89, 0x3E, 0x9C,
0x0F, 0x03, 0xE2, 0xEB, 0x35, 0x06, 0x10, 0xC5,
0xB0, 0xA9, 0x8C, 0x27, 0xF6, 0x7E, 0xDE, 0x86,
0xF3, 0xDC, 0xE0, 0xE9, 0xCC, 0xE4, 0x91, 0xC3,
0x6A, 0xAB, 0x23, 0xA0, 0xFA, 0x3D, 0x97, 0xBA,
0x8B, 0x8B, 0xE6, 0xA3, 0xD4, 0x46, 0x82, 0x40,
0x29, 0xE8, 0xDB, 0x9D, 0xDA, 0xED, 0x4A, 0x28,
0x44, 0x93, 0x71, 0x3F, 0x44, 0x03, 0xF4, 0x20,
0x06, 0x4F, 0x7D, 0x68, 0x22, 0x8A, 0xAE, 0x56,
0x06, 0xE0, 0xCC, 0xCF, 0xBB, 0x9D, 0x72, 0x70
};
// Копируем базовый ключ и расширяем его до 256 байт
Buffer.BlockCopy(baseKey, 0, ngKey, 0, baseKey.Length);
for (int i = baseKey.Length; i < 256; i++)
{
ngKey[i] = (byte)(baseKey[i % baseKey.Length] ^ 0x37);
}
var ngKeys = new byte[1][];
ngKeys[0] = ngKey;
GTA5Constants.PC_NG_KEYS = ngKeys;
// Инициализируем таблицы расшифровки
var decryptTables = new uint[1][][];
decryptTables[0] = new uint[1][];
decryptTables[0][0] = new uint[69632];
// Заполняем таблицы на основе анализа DLL
for (int i = 0; i < 69632; i++)
{
int tableIndex = i % 256;
uint value = (uint)(tableIndex ^ ngKey[tableIndex]);
// Повторяем значение в каждом байте
value = (value << 24) | (value << 16) | (value << 8) | value;
decryptTables[0][0][i] = value;
}
GTA5Constants.PC_NG_DECRYPT_TABLES = decryptTables;
// Создаем экземпляр криптографии
var crypto = new GTA5Crypto();
Console.WriteLine($"AES Key Size: {aesKey.Length} bytes");
Console.WriteLine($"NG Key Size: {ngKey.Length} bytes");
Console.WriteLine($"Decrypt Tables Size: {decryptTables[0][0].Length * 4} bytes");
Console.WriteLine($"First decrypt table value: 0x{decryptTables[0][0][0]:X8}");
}
static void ProcessDirectory(RageArchiveDirectory7 directory, string indent)
{
if (directory == null) return;
Console.WriteLine($"{indent}Directory: {directory.Name}");
if (directory.Files != null)
{
foreach (var file in directory.Files)
{
if (file == null) continue;
if (file is IRageArchiveFileEntry7 fileEntry)
{
Console.WriteLine($"{indent} File: {fileEntry.Name}");
Console.WriteLine($"{indent} Size: {fileEntry.FileSize:N0} bytes");
Console.WriteLine($"{indent} Offset: {fileEntry.FileOffset:N0}");
// Проверяем, является ли файл бинарным через интерфейс IArchiveBinaryFile
if (file is IArchiveBinaryFile binaryFile)
{
Console.WriteLine($"{indent} Encrypted: {binaryFile.IsEncrypted}");
Console.WriteLine($"{indent} Compressed: {binaryFile.IsCompressed}");
if (binaryFile.IsCompressed)
{
Console.WriteLine($"{indent} Uncompressed Size: {binaryFile.UncompressedSize:N0} bytes");
Console.WriteLine($"{indent} Compressed Size: {binaryFile.CompressedSize:N0} bytes");
}
}
}
else
{
Console.WriteLine($"{indent} File: {file.Name} (Unknown type)");
}
}
}
if (directory.Directories != null)
{
foreach (var dir in directory.Directories)
{
ProcessDirectory(dir, indent + " ");
}
}
}
}