public static byte[] encryptLua(byte[] luaContent, byte[] key, bool newEngine, int version) { //newEngine - игры, выпущенные с Tales From the Borderlands и переизданные на новом движке BlowFishCS.BlowFish DoEncLua = new BlowFishCS.BlowFish(key, version); byte[] header = new byte[4]; byte[] checkHeader = new byte[4]; Array.Copy(luaContent, 0, checkHeader, 0, 4); if (Encoding.ASCII.GetString(checkHeader) == "\x1bLua") { if (newEngine == true) { header = Encoding.ASCII.GetBytes("\x1bLEn"); byte[] tempLua = new byte[luaContent.Length - 4]; Array.Copy(luaContent, 4, tempLua, 0, luaContent.Length - 4); tempLua = DoEncLua.Crypt_ECB(tempLua, 7, false); Array.Copy(header, 0, luaContent, 0, 4); Array.Copy(tempLua, 0, luaContent, 4, tempLua.Length); } else { luaContent = DoEncLua.Crypt_ECB(luaContent, version, false); } } else if ((Encoding.ASCII.GetString(checkHeader) != "\x1bLEn") && (Encoding.ASCII.GetString(checkHeader) != "\x1bLEo") && (Encoding.ASCII.GetString(checkHeader) != "\x1bLua")) { if (newEngine == true) { header = Encoding.ASCII.GetBytes("\x1bLEo"); byte[] tempLua2 = new byte[luaContent.Length]; Array.Copy(luaContent, 0, tempLua2, 0, luaContent.Length); tempLua2 = DoEncLua.Crypt_ECB(tempLua2, 7, false); luaContent = new byte[tempLua2.Length + 4]; Array.Copy(header, 0, luaContent, 0, 4); Array.Copy(tempLua2, 0, luaContent, 4, luaContent.Length - 4); } else { luaContent = DoEncLua.Crypt_ECB(luaContent, version, false); } } return(luaContent); }
public static int meta_find_encrypted(byte[] binContent, string NeedData, int pos, byte[] DecKey, int version) //Для поиска в зашифрованных данных (обычно для поиска текстур) { int bufsz = 128; //Размер буфера по умолчанию int result = 0; int Max_scan_size = 2048; //Проверка только определённого участка bool IsFinding = true; BlowFishCS.BlowFish decBuf = new BlowFishCS.BlowFish(DecKey, version); if (pos > binContent.Length - 4) { pos = 4; //Начинать поиск после заголовка файла } while (IsFinding) { byte[] buffer = new byte[bufsz]; buffer = new byte[bufsz]; if (buffer.Length > binContent.Length - pos) { bufsz = binContent.Length - pos; buffer = new byte[bufsz]; } Array.Copy(binContent, pos, buffer, 0, bufsz); pos++; Max_scan_size--; byte[] checkBuffer = decBuf.Crypt_ECB(buffer, version, true); int bfPos = 0; //Позиция в blowfish while (Methods.ConvertHexToString(checkBuffer, bfPos, NeedData.Length, MainMenu.settings.ASCII_N, 1) != NeedData) { bfPos++; if (Methods.ConvertHexToString(checkBuffer, bfPos, NeedData.Length, MainMenu.settings.ASCII_N, 1) == NeedData) { result = bfPos + pos - 1; IsFinding = false; } if ((bfPos + NeedData.Length + 1) > checkBuffer.Length) { break; } } if ((pos >= binContent.Length) || (Max_scan_size < 0)) { result = -1; IsFinding = false; } } return(result); }
public static byte[] decryptLua(byte[] luaContent, byte[] key, int version) { byte[] headerCheck = new byte[4]; Array.Copy(luaContent, 0, headerCheck, 0, 4); BlowFishCS.BlowFish decLuaNew = new BlowFishCS.BlowFish(key, 7); byte[] tempLua; switch (Encoding.ASCII.GetString(headerCheck)) { case "\x1bLEn": tempLua = new byte[luaContent.Length - 4]; Array.Copy(luaContent, 4, tempLua, 0, luaContent.Length - 4); byte[] luaHeader = { 0x1B, 0x4C, 0x75, 0x61 }; //.Lua - начало заголовка tempLua = decLuaNew.Crypt_ECB(tempLua, 7, true); Array.Copy(luaHeader, 0, luaContent, 0, 4); Array.Copy(tempLua, 0, luaContent, 4, tempLua.Length); break; case "\x1bLEo": tempLua = new byte[luaContent.Length - 4]; Array.Copy(luaContent, 4, tempLua, 0, luaContent.Length - 4); tempLua = decLuaNew.Crypt_ECB(tempLua, 7, true); luaContent = new byte[tempLua.Length]; Array.Copy(tempLua, 0, luaContent, 0, luaContent.Length); break; default: BlowFishCS.BlowFish decLua = new BlowFishCS.BlowFish(key, version); luaContent = decLua.Crypt_ECB(luaContent, version, true); break; } return(luaContent); }
public byte[] encryptFunction(byte[] bytes, byte[] key, int archiveVersion) { BlowFishCS.BlowFish enc = new BlowFishCS.BlowFish(key, archiveVersion); Methods.meta_crypt(bytes, key, archiveVersion, false); return(enc.Crypt_ECB(bytes, archiveVersion, false)); }
public static int meta_crypt(byte[] file, byte[] key, int version_archive, bool decrypt) { uint file_type = 0; long i, block_size = 0, block_crypt = 0, block_clean = 0, blocks; int meta = 1; if (file.Length < 4) { return((int)file_type); } byte[] check_type = new byte[4]; Array.Copy(file, 0, check_type, 0, 4); file_type = BitConverter.ToUInt32(check_type, 0); uint p = (uint)file.Length; uint l = p + (uint)file.Length; /* * block_size, * block_crypt * blocks_clean */ switch (file_type) { case 0x4D545245: meta = 0; break; //ERTM case 0x4D42494E: meta = 0; break; //NIBM case 0xFB4A1764: block_size = 0x80; block_crypt = 0x20; block_clean = 0x50; break; case 0xEB794091: block_size = 0x80; block_crypt = 0x20; block_clean = 0x50; break; case 0x64AFDEFB: block_size = 0x80; block_crypt = 0x20; block_clean = 0x50; break; case 0x64AFDEAA: block_size = 0x100; block_crypt = 0x8; block_clean = 0x18; break; case 0x4D424553: block_size = 0x40; block_crypt = 0x40; block_clean = 0x64; break; //SEBM default: meta = 0; break; } if (block_size != 0) { blocks = (file.Length - 4) / block_size; long poz = 0; byte[] temp_file = new byte[file.Length - 4]; Array.Copy(file, 4, temp_file, 0, temp_file.Length); for (i = 0; i < blocks; i++) { byte[] block = new byte[block_size]; Array.Copy(temp_file, poz, block, 0, block_size); if (p >= l) { break; } if (i % block_crypt == 0) { BlowFishCS.BlowFish enc = new BlowFishCS.BlowFish(key, version_archive); //block = enc.Crypt_ECB(block, version_archive, false); block = enc.Crypt_ECB(block, version_archive, decrypt); Array.Copy(block, 0, temp_file, poz, block.Length); } else if ((i % block_clean == 0) && (i > 0)) { Array.Copy(block, 0, temp_file, poz, block.Length); } else { XorBlock(ref block, 0xff); Array.Copy(block, 0, temp_file, poz, block.Length); } p += (uint)block_size; poz += block_size; } Array.Copy(temp_file, 0, file, 4, temp_file.Length); } return(meta); }
public static string FindingDecrytKey(byte[] bytes, string TypeFile, ref byte[] KeyEnc, ref int version) //Ищем ключ расшифровки для файлов langdb, dlog и d3dtx { string result = null; byte[] decKey = null; byte[] CheckVersion = new byte[4]; Array.Copy(bytes, 4, CheckVersion, 0, 4); if ((BitConverter.ToInt32(CheckVersion, 0) < 0) || (BitConverter.ToInt32(CheckVersion, 0) > 6)) { if (KeyEnc != null) { try { byte[] tmpFile = new byte[bytes.Length]; Array.Copy(bytes, 0, tmpFile, 0, bytes.Length); Methods.meta_crypt(tmpFile, KeyEnc, version, true); byte[] CheckVer = new byte[4]; Array.Copy(tmpFile, 4, CheckVer, 0, 4); if ((BitConverter.ToInt32(CheckVer, 0) > 0) && (BitConverter.ToInt32(CheckVer, 0) < 6)) { Array.Copy(tmpFile, 0, bytes, 0, bytes.Length); if (TypeFile == "texture" || TypeFile == "font") { int TexturePosition = -1; if (TypeFile == "texture") { TexturePosition = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { TexturePosition = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } if (FindStartOfStringSomething(bytes, TexturePosition, "DDS ") == -1) { int DDSPos = meta_find_encrypted(bytes, "DDS ", TexturePosition, KeyEnc, version); byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(KeyEnc, version); tempHeader = decHeader.Crypt_ECB(tempHeader, version, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); } } result = "File successfully decrypted."; return(result); } } catch { KeyEnc = null; //I don't know why I did this... } } for (int a = 0; a < MainMenu.gamelist.Count; a++) { byte[] CheckVerOld = CheckVersion; //Old encryption method (for versions 2-6) byte[] tempFileOld = new byte[bytes.Length]; //A temporary file for old encryption method byte[] CheckVerNew = CheckVersion; //Newer encryption method (for versions 7-9) byte[] tempFileNew = new byte[bytes.Length]; //A temporary file for newer encryption method decKey = MainMenu.gamelist[a].key; Array.Copy(bytes, 0, tempFileOld, 0, bytes.Length); Array.Copy(bytes, 0, tempFileNew, 0, bytes.Length); if (((BitConverter.ToInt32(CheckVerOld, 0) < 0) || BitConverter.ToInt32(CheckVerOld, 0) > 6) || (BitConverter.ToInt32(CheckVerNew, 0) < 0) || (BitConverter.ToInt32(CheckVerNew, 0) > 6)) { Methods.meta_crypt(tempFileOld, decKey, 2, true); CheckVerOld = new byte[4]; Array.Copy(tempFileOld, 4, CheckVerOld, 0, 4); Methods.meta_crypt(tempFileNew, decKey, 7, true); CheckVerNew = new byte[4]; Array.Copy(tempFileNew, 4, CheckVerNew, 0, 4); } if ((BitConverter.ToInt32(CheckVerOld, 0) > 0) && (BitConverter.ToInt32(CheckVerOld, 0) < 6)) { Array.Copy(tempFileOld, 0, bytes, 0, bytes.Length); if (TypeFile == "texture" || TypeFile == "font") { int TexturePosition = -1; if (FindStartOfStringSomething(bytes, 4, "DDS ") == -1)// > bytes.Length - 100) { if (TypeFile == "texture") { TexturePosition = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { TexturePosition = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } int DDSPos = meta_find_encrypted(bytes, "DDS ", TexturePosition, decKey, 2); byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(decKey, 2); tempHeader = decHeader.Crypt_ECB(tempHeader, 2, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); } } result = "Decryption key: " + MainMenu.gamelist[a].gamename + ". Blowfish type: old (versions 2-6)"; KeyEnc = MainMenu.gamelist[a].key; version = 2; break; } else if ((BitConverter.ToInt32(CheckVerNew, 0) > 0) && (BitConverter.ToInt32(CheckVerNew, 0) < 6)) { Array.Copy(tempFileNew, 0, bytes, 0, bytes.Length); if (TypeFile == "texture" || TypeFile == "font") { int TexturePosition = -1; if (TypeFile == "texture") { TexturePosition = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { TexturePosition = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } if (FindStartOfStringSomething(bytes, TexturePosition, "DDS ") == -1)//> bytes.Length - 100) { int DDSPos = meta_find_encrypted(bytes, "DDS ", TexturePosition, decKey, 7); byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(decKey, 7); tempHeader = decHeader.Crypt_ECB(tempHeader, 7, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); } } result = "Decryption key: " + MainMenu.gamelist[a].gamename + ". Blowfish type: new (versions 7-9)"; KeyEnc = MainMenu.gamelist[a].key; version = 7; break; } } } else //Check dds header only file { if ((TypeFile == "texture" || TypeFile == "font") && KeyEnc != null) { try { int DDSstart = -1; if (TypeFile == "texture") { DDSstart = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { DDSstart = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } int DDSPos = meta_find_encrypted(bytes, "DDS ", DDSstart, KeyEnc, version); if ((DDSPos != -1) && (DDSPos < (bytes.Length - 100))) { byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(KeyEnc, version); tempHeader = decHeader.Crypt_ECB(tempHeader, version, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); DDSstart = DDSPos; result = "File successfully decrypted."; return(result); } } catch { KeyEnc = null; } } try { if (TypeFile == "texture" || TypeFile == "font") { int DDSstart = -1; if (TypeFile == "texture") { DDSstart = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { DDSstart = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } for (int i = 0; i < MainMenu.gamelist.Count; i++) { int DDSPos = meta_find_encrypted(bytes, "DDS ", DDSstart, MainMenu.gamelist[i].key, 2); if ((DDSPos != -1) && (DDSPos < (bytes.Length - 100))) { byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(MainMenu.gamelist[i].key, 2); tempHeader = decHeader.Crypt_ECB(tempHeader, 2, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); DDSstart = DDSPos; result = "Decryption key: " + MainMenu.gamelist[i].gamename + ". Blowfish type: old (versions 2-6)"; KeyEnc = MainMenu.gamelist[i].key; break; } } if (DDSstart == -1) { for (int i = 0; i < MainMenu.gamelist.Count; i++) { int DDSPos = meta_find_encrypted(bytes, "DDS ", DDSstart, MainMenu.gamelist[i].key, 7); if ((DDSPos != -1) && (DDSPos < (bytes.Length - 100))) { byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(MainMenu.gamelist[i].key, 7); tempHeader = decHeader.Crypt_ECB(tempHeader, 7, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); DDSstart = DDSPos; result = "Decryption key: " + MainMenu.gamelist[i].gamename + ". Blowfish type: new (versions 7-9)"; KeyEnc = MainMenu.gamelist[i].key; } } } } } catch (Exception ex) { result = "Error " + ex.Message; } } return(result); }
public static string FindingDecrytKey(byte[] bytes, string TypeFile) //Ищем ключ расшифровки для файлов langdb, dlog и d3dtx { string result = null; byte[] decKey; byte[] CheckVersion = new byte[4]; Array.Copy(bytes, 4, CheckVersion, 0, 4); if ((BitConverter.ToInt32(CheckVersion, 0) < 0) || (BitConverter.ToInt32(CheckVersion, 0) > 6)) { for (int a = 0; a < MainMenu.gamelist.Count; a++) { byte[] CheckVerOld = CheckVersion; //Старый метод шифрования (Версии 2-6) byte[] tempFileOld = new byte[bytes.Length]; //Временный файл для расшифровки (старый метод шифрования) byte[] CheckVerNew = CheckVersion; //Поновее метод шифрования (Версии 7-9) byte[] tempFileNew = new byte[bytes.Length]; decKey = MainMenu.gamelist[a].key; Array.Copy(bytes, 0, tempFileOld, 0, bytes.Length); Array.Copy(bytes, 0, tempFileNew, 0, bytes.Length); if (((BitConverter.ToInt32(CheckVerOld, 0) < 0) || BitConverter.ToInt32(CheckVerOld, 0) > 6) || (BitConverter.ToInt32(CheckVerNew, 0) < 0) || (BitConverter.ToInt32(CheckVerNew, 0) > 6)) { Methods.meta_crypt(tempFileOld, decKey, 2, true); CheckVerOld = new byte[4]; Array.Copy(tempFileOld, 4, CheckVerOld, 0, 4); Methods.meta_crypt(tempFileNew, decKey, 7, true); CheckVerNew = new byte[4]; Array.Copy(tempFileNew, 4, CheckVerNew, 0, 4); } if ((BitConverter.ToInt32(CheckVerOld, 0) > 0) && (BitConverter.ToInt32(CheckVerOld, 0) < 6)) { Array.Copy(tempFileOld, 0, bytes, 0, bytes.Length); if (TypeFile == "texture" || TypeFile == "font") { int TexturePosition = -1; if (FindStartOfStringSomething(bytes, 4, "DDS ") > bytes.Length - 100) { if (TypeFile == "texture") { TexturePosition = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { TexturePosition = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } int DDSPos = meta_find_encrypted(bytes, "DDS ", TexturePosition, decKey, 2); byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(decKey, 2); tempHeader = decHeader.Crypt_ECB(tempHeader, 2, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); } } result = "Decryption key: " + MainMenu.gamelist[a].gamename + ". Blowfish type: old (versions 2-6)"; break; } else if ((BitConverter.ToInt32(CheckVerNew, 0) > 0) && (BitConverter.ToInt32(CheckVerNew, 0) < 6)) { Array.Copy(tempFileNew, 0, bytes, 0, bytes.Length); if (TypeFile == "texture" || TypeFile == "font") { int TexturePosition = -1; if (FindStartOfStringSomething(bytes, 4, "DDS ") > bytes.Length - 100) { if (TypeFile == "texture") { TexturePosition = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { TexturePosition = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } int DDSPos = meta_find_encrypted(bytes, "DDS ", TexturePosition, decKey, 7); byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(decKey, 7); tempHeader = decHeader.Crypt_ECB(tempHeader, 7, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); } } result = "Decryption key: " + MainMenu.gamelist[a].gamename + ". Blowfish type: new (versions 7-9)"; break; } } } else //Проверка файлов, в которых зашифрован только заголовок DDS-текстуры { try { if (TypeFile == "texture" || TypeFile == "font") { int DDSstart = -1; //Пока что придумал сделать авторасшифровку для одиночных текстур. Да и вроде шрифты были зашифрованы с 1 текстурой. if (TypeFile == "texture") { DDSstart = FindStartOfStringSomething(bytes, 4, ".d3dtx") + 6; } else { DDSstart = FindStartOfStringSomething(bytes, 4, ".tga") + 4; } for (int i = 0; i < MainMenu.gamelist.Count; i++) { int DDSPos = meta_find_encrypted(bytes, "DDS ", DDSstart, MainMenu.gamelist[i].key, 2); if ((DDSPos != -1) && (DDSPos < (bytes.Length - 100))) { byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(MainMenu.gamelist[i].key, 2); tempHeader = decHeader.Crypt_ECB(tempHeader, 2, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); DDSstart = DDSPos; result = "Decryption key: " + MainMenu.gamelist[i].gamename + ". Blowfish type: old (versions 2-6)"; } } if (DDSstart == -1) { for (int i = 0; i < MainMenu.gamelist.Count; i++) { int DDSPos = meta_find_encrypted(bytes, "DDS ", DDSstart, MainMenu.gamelist[i].key, 7); if ((DDSPos != -1) && (DDSPos < (bytes.Length - 100))) { byte[] tempHeader = new byte[2048]; if (tempHeader.Length > bytes.Length - DDSPos) { tempHeader = new byte[bytes.Length - DDSPos]; } Array.Copy(bytes, DDSPos, tempHeader, 0, tempHeader.Length); BlowFishCS.BlowFish decHeader = new BlowFishCS.BlowFish(MainMenu.gamelist[i].key, 7); tempHeader = decHeader.Crypt_ECB(tempHeader, 7, true); Array.Copy(tempHeader, 0, bytes, DDSPos, tempHeader.Length); DDSstart = DDSPos; result = "Decryption key: " + MainMenu.gamelist[i].gamename + ". Blowfish type: new (versions 7-9)"; } } } } } catch (Exception ex) { result = "Error " + ex.Message; } } return(result); }