using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Launcher_Editor { class Program { static void Main(string[] args) { Console.WriteLine(FFXIVLoginStringDecodeBinary("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV\\ffxivlogin.exe")); } public static string FFXIVLoginStringDecodeBinary(string path) { Console.OutputEncoding = System.Text.Encoding.UTF8; byte[] data = File.ReadAllBytes(path); //int offset = 0x5405a; //int offset = 0x5425d; int offset = 0x53ea0; while (true) { string result = ""; uint key = (uint)data[offset + 0] << 8 | data[offset + 1]; uint key2 = data[offset + 2]; key = RotateRight(key, 1) & 0xFFFF; key -= 0x22AF; key &= 0xFFFF; key2 = key2 ^ key; key = RotateRight(key, 1) & 0xFFFF; key -= 0x22AF; key &= 0xFFFF; uint finalKey = key; key = data[offset + 3]; uint count = (key2 & 0xFF) << 8; key = key ^ finalKey; key &= 0xFF; count |= key; int count2 = 0; while (count != 0) { uint encrypted = data[offset + 4 + count2]; finalKey = RotateRight(finalKey, 1) & 0xFFFF; finalKey -= 0x22AF; finalKey &= 0xFFFF; encrypted = encrypted ^ (finalKey & 0xFF); result += (char)encrypted; count--; count2++; } offset += 4 + count2; } } public static string FFXIVLoginStringDecode(byte[] data) { string result = ""; uint key = (uint)data[0] << 8 | data[1]; uint key2 = data[2]; key = RotateRight(key, 1) & 0xFFFF; key -= 0x22AF; key2 = key2 ^ key; key = RotateRight(key, 1) & 0xFFFF; key -= 0x22AF; uint finalKey = key; key = data[3]; uint count = (key2 & 0xFF) << 8; key = key ^ finalKey; key &= 0xFF; count |= key; int count2 = 0; while (count != 0) { uint encrypted = data[4 + count2]; finalKey = RotateRight(finalKey, 1) & 0xFFFF; finalKey -= 0x22AF; encrypted = encrypted ^ (finalKey & 0xFF); result += (char)encrypted; count--; count2++; } return result; } public static byte[] FFXIVLoginStringEncode(uint key, string text) { key = key & 0xFFFF; uint count = 0; byte[] asciiBytes = Encoding.ASCII.GetBytes(text); byte[] result = new byte[4 + text.Length]; for (count = 0; count < text.Length; count++) { result[result.Length - count - 1] = (byte)(asciiBytes[asciiBytes.Length - count - 1] ^ (key & 0xFF)); key += 0x22AF; key &= 0xFFFF; key = RotateLeft(key, 1) & 0xFFFF; } count = count ^ key; result[3] = (byte)(count & 0xFF); key += 0x22AF & 0xFFFF; key = RotateLeft(key, 1) & 0xFFFF; result[2] = (byte)(key & 0xFF); key += 0x22AF & 0xFFFF; key = RotateLeft(key, 1) & 0xFFFF; result[1] = (byte)(key & 0xFF); result[0] = (byte)((key >> 8) & 0xFF); return result; } public static uint RotateLeft(uint value, int bits) { return (value << bits) | (value >> (16 - bits)); } public static uint RotateRight(uint value, int bits) { return (value >> bits) | (value << (16 - bits)); } } }