SHARE
TWEET

Final Fantasy IX Steam 2016 - Savedata decompiler

MaKiPL Apr 16th, 2016 289 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.IO;
  3. using System.Security;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6.  
  7. namespace FFIX_Save_Extractor
  8. {
  9.     class Program
  10.     {
  11.         private static int BlockSizee = 18432 - 462; //This one is tricky, but works!
  12.         static private int slotID = 0;
  13.         static private int saveID = 1;
  14.  
  15.         //Max slot ID is 10 and max saveID is 15. Therefore max individual saves is 150.
  16.  
  17.         private static SecureString password = new SecureString();
  18.         private static string Pathe = @""; //Change me if you want to instantly debug your file!
  19.         static void Main(string[] args)
  20.         {
  21.             Console.WriteLine("Welcome to Final Fantasy IX Steam save decoder v1.0!");
  22.             Console.WriteLine("Please enter path to SavedData_ww.dat file, or drag and drop it here:");
  23.             string Path  = Pathe.Length != 0 ? Pathe :Console.ReadLine();
  24.             if (Path[0] == '"' && Path[Path.Length - 1] == '"')
  25.                 Path = Path.Replace("\"", "");
  26.             Console.WriteLine("Please enter your slotID (e.g. slot1 is 0, slot2 is 1): ");
  27.             slotID = int.Parse(Console.ReadLine());
  28.             Console.WriteLine("Please enter your saveID (e.g. save1 is 0, save2 is 1): ");
  29.             saveID = int.Parse(Console.ReadLine());
  30.             FileStream FS = new FileStream(Path, FileMode.Open);
  31.             BinaryReader br = new BinaryReader(FS);
  32.             FS.Seek((long)(320 - (int)FS.Position), SeekOrigin.Current);
  33.             int num = 153600;
  34.             int num2 = 18432 + slotID * 15 * 18432 + saveID * 18432;
  35.             FS.Seek((long)num, SeekOrigin.Current); //?
  36.             FS.Seek((long)num2, SeekOrigin.Current); //?
  37.             byte[] buffer = br.ReadBytes(GetCipherSize(BlockSizee + 4));
  38.             byte[] result = Decrypt(buffer);
  39.             File.WriteAllBytes(Path + string.Format(".Slot{0}Save{1}", slotID > 9 ? slotID.ToString(): "0" + slotID, saveID > 9 ? saveID.ToString() : "0" + saveID), result);
  40.             FS.Close();
  41.             Console.WriteLine("File {0} decompressed!", Path);
  42.             Console.ReadKey();
  43.             return;
  44.         }
  45.  
  46.         static public int GetCipherSize(int plainTextSize)
  47.         {
  48.             int num = 16;
  49.             return plainTextSize + num - plainTextSize % num;
  50.         }
  51.  
  52.         public static byte[] Decrypt(byte[] bytesToBeDecrypted)
  53.         {
  54.             byte[] array = GetPassword();
  55.             byte[] result = null;
  56.             byte[] salt = GetSalt();
  57.             using (MemoryStream memoryStream = new MemoryStream())
  58.             {
  59.                 using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
  60.                 {
  61.                     rijndaelManaged.KeySize = 256;
  62.                     rijndaelManaged.BlockSize = 128;
  63.                     Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(array, salt, 1000);
  64.                     rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
  65.                     rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
  66.                     rijndaelManaged.Mode = CipherMode.CBC;
  67.                     CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(), CryptoStreamMode.Write);
  68.                         cryptoStream.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
  69.                         //cryptoStream.Close();
  70.                     result = memoryStream.ToArray();
  71.                 }
  72.             }
  73.             return result;
  74.         }
  75.         private static byte[] GetPassword()
  76.         {
  77.             string[] array = new string[]
  78.             {
  79.             "67434cd0-1ca3-11e5-9a21-1697f925ec7b",
  80.             "7a5313a0-1ca3-11e5-b939-0800200c9a66"
  81.             };
  82.             string[] array2 = array;
  83.             for (int i = 0; i < array2.Length; i++)
  84.             {
  85.                 string text = array2[i];
  86.                 for (int j = 0; j < text.Length; j++)
  87.                 {
  88.                     password.AppendChar(text[j]);
  89.                 }
  90.             }
  91.             byte[] bytes = Encoding.UTF8.GetBytes(password.ToString());
  92.             password.Clear();
  93.             return bytes;
  94.         }
  95.         private static byte[] GetSalt()
  96.         {
  97.             return new byte[]
  98.             {
  99.             3,
  100.             3,
  101.             1,
  102.             4,
  103.             7,
  104.             0,
  105.             9,
  106.             7
  107.             };
  108.         }
  109.     }
  110. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top