using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
public static class Lineage2Decrypter
{
// Ключ для дешифрования с помощью XOR
private static byte s_keyXOR; //Lineage2Ver111
private static byte[] s_lineage2Verbyte; //Lineage2Ver111,Lineage2Ver121
// Основная функция для дешифрования файла Lineage2
public static string L2DecodeU(string fileName)
{
// Проверяем, существует ли файл
if (!File.Exists(fileName)) return fileName;
// Считываем данные из файла
byte[] fileData = File.ReadAllBytes(fileName);
// Находим начальный индекс строки "Lineage2Ver111" в массиве байт
bool isLineage2Ver = FindStringIndex(fileData, Encoding.Unicode.GetBytes("Lineage2Ver111"));
if (isLineage2Ver)
{
s_keyXOR = 0xAC;
s_lineage2Verbyte = Encoding.Unicode.GetBytes("Lineage2Ver111"); //Lineage2Ver111
}
else // Если строка не найдена "Lineage2Ver111", тогда ищем "Lineage2Ver121"
{
isLineage2Ver = FindStringIndex(fileData, Encoding.Unicode.GetBytes("Lineage2Ver121"));
s_keyXOR = (byte)GetXORKey121(Path.GetFileName(fileName));
s_lineage2Verbyte = Encoding.Unicode.GetBytes("Lineage2Ver121"); //Lineage2Ver121
}
// Если строка найдена, то дешифруем файл
if (isLineage2Ver)
{
// Дешифруем данные с помощью XOR
byte[] decryptedData = DecryptData(fileData, s_lineage2Verbyte.Length, s_keyXOR);
// Создаем имя выходного файла
string outputFilePath = "temp";
int counter = 1;
string newFileName = "dec-" + Path.GetFileName(fileName);
// Проверяем, существует ли файл
if (!File.Exists("temp/dec-" + Path.GetFileName(fileName)))
{
outputFilePath = "temp/dec-" + Path.GetFileName(fileName);
}
else {
// Проверка, существует ли файл
while (File.Exists(Path.Combine(outputFilePath, newFileName)))
{
newFileName = $"({counter}){"dec-" + Path.GetFileName(fileName)}";
counter++;
}
outputFilePath = "temp/" + newFileName;
// MessageBox.Show(newFileName);
}
// Создаем папку "temp", если она не существует
string outputDirectory = Path.GetDirectoryName(outputFilePath);
if (!Directory.Exists(outputDirectory))
{
Directory.CreateDirectory(outputDirectory);
}
// Используем using-блок для автоматического закрытия файла
using (var outputFile = File.OpenWrite(outputFilePath))
{
// Сохраняем дешифрованные данные в выходной файл
outputFile.Write(decryptedData, 0, decryptedData.Length);
}
// Возвращаем имя выходного файла
return outputFilePath;
}
// Если строка не найдена, то файл не зашифрован
return fileName;
}
// Метод для поиска начала зашифрованных данных в массиве байт
private static bool FindStringIndex(byte[] data, byte[] pattern)
{
// Предполагаем, что совпадение найдено
bool match = false;
// Проходим по массиву данных, начиная с первого байта
for (int i = 0; i <= pattern.Length - 1; i++)
{
// Если байты совпадают
if (data[i] == pattern[i])
{
match = true;
}
else
{
match = false;
break;
}
}
return match;
}
// Метод для дешифрования данных с помощью XOR
private static byte[] DecryptData(byte[] data, int startIndex, byte key)
{
// Создаем массив для хранения дешифрованных данных
byte[] decryptedData = new byte[data.Length - startIndex];
// Проходим по массиву данных, начиная с заданного индекса
for (int i = startIndex, j = 0; i < data.Length; i++, j++)
{
// Дешифруем каждый байт с помощью XOR
decryptedData[j] = (byte)(data[i] ^ key);
}
// Возвращаем массив дешифрованных данных
return decryptedData;
}
// Метод для получения ключа XOR для Lineage2Ver121
private static int GetXORKey121(string filename)
{
int sum = 0;
foreach (char c in filename.ToLower())
{
sum += (byte)c;
}
return sum & 0xff;
}
// Метод для удаления временных файлов по завершению программы
public static void DeleteTempFiles()
{
if (Directory.Exists("temp"))
{
// Используем рекурсивное удаление для удаления всех файлов и подпапок
Directory.Delete("temp", true);
}
}
}