Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using CoreExtensions.IO;
- using CoreExtensions;
- using System.Security.Cryptography;
- using Crypto;
- using Ionic.Zlib;
- using Org.BouncyCastle.Security;
- using Org.BouncyCastle.Crypto.Parameters;
- using Org.BouncyCastle.Math;
- using Org.BouncyCastle.Crypto;
- namespace FFCrypt
- {
- public class FastFile
- {
- private EndianReader br { get; set; }
- public FastFile(string fileName)
- {
- // Create reader
- this.br = new EndianReader(new FileStream(fileName, FileMode.Open), EndianStyle.BigEndian);
- // Verify magic
- if (br.ReadInt32() != 0x49576666)
- Console.WriteLine("Invalid fast file magic!");
- if (br.ReadInt32() != 0x30313030)
- Console.WriteLine("Invalid fast file magic!");
- // Read our count?
- int count = br.ReadInt32();
- br.ReadInt32();
- // Verify second magic
- if (br.ReadInt64() != 0x5048454542733731)
- Console.WriteLine("Invalid fast file magic!");
- // Move
- this.br.ReadInt32();
- // Get our zone
- EndianReader zoneReader = this.GetZone();
- // Raed
- this.ReadZoneFile(zoneReader);
- }
- private EndianReader GetZone()
- {
- // Read IV table feed/name
- byte[] feed = this.br.ReadBytes(0x20);
- byte[] sig = this.br.ReadBytes(0x100);
- // Build our IV table
- byte[] table = this.InitIVTable(feed);
- // Go past sig
- this.br.BaseStream.Position = 0x13C;
- // Set key
- byte[] Key = { 0x1a, 0xc1, 0xd1, 0x2d, 0x52, 0x7c, 0x59, 0xb4, 0x0e,
- 0xca, 0x61, 0x91, 0x20, 0xff, 0x82, 0x17, 0xcc, 0xff,
- 0x09, 0xcd, 0x16, 0x89, 0x6f, 0x81, 0xb8, 0x29, 0xc7,
- 0xf5, 0x27, 0x93, 0x40, 0x5d };
- // Init Salsa
- Salsa20 salsa = new Salsa20();
- salsa.Key = Key;
- // Make filestream
- FileStream fileStream = new FileStream("C:\\ZONEFILE", FileMode.Create);
- // Create output
- BinaryWriter bw = new BinaryWriter(fileStream);
- // Store our section index
- int sectionIndex = 0;
- // Keep going till we get an empty section
- while(true)
- {
- // Read section size
- int sectionSize = this.br.ReadInt32();
- if (sectionSize == 0)
- break;
- // Read section data
- byte[] sectionData = this.br.ReadBytes(sectionSize);
- // Set our IV
- salsa.IV = this.GetIV(table, sectionIndex);
- // Get our decrypted data
- byte[] decData = salsa.CreateDecryptor().TransformFinalBlock(sectionData, 0, sectionSize);
- // Get hash
- byte[] sectionHash = Security.SHA1(decData);
- // Create new buffer
- byte[] compressedData = new byte[decData.Length + 2];
- // Copy our decrypted data
- Array.Copy(decData, 0, compressedData, 2, decData.Length);
- // Setup header
- compressedData[0] = 0x78;
- compressedData[1] = 0x01;
- // Write our compressed data
- bw.Write(ZlibStream.UncompressBuffer(compressedData));
- // Update IV table
- this.UpdateIVTable(ref table, sectionIndex, sectionHash);
- // Increment our section index
- sectionIndex++;
- }
- // Save our IV table
- File.WriteAllBytes("C:\\IVTABLE", table);
- // Create binary reader and move to start
- EndianReader br = new EndianReader(fileStream, EndianStyle.BigEndian);
- br.BaseStream.Position = 0;
- // Return our reader
- return br;
- }
- private void ReadZoneFile(EndianReader br)
- {
- // Move to start
- br.BaseStream.Position = 0;
- // Read file size - 0x24
- int fileSize = br.ReadInt32();
- // Read unknowns
- int unknown1 = br.ReadInt32();
- int unknown2 = br.ReadInt32();
- int unknown3 = br.ReadInt32();
- int unknown4 = br.ReadInt32();
- int unknown5 = br.ReadInt32();
- int unknown6 = br.ReadInt32();
- int unknown7 = br.ReadInt32();
- int unknown8 = br.ReadInt32();
- int stringTableCount = br.ReadInt32();
- int padding1 = br.ReadInt32();
- // Read our indexCount
- int indexCount = br.ReadInt32();
- int padding2 = br.ReadInt32();
- // Move to our string table
- br.BaseStream.Position += stringTableCount * 4;
- // Create list of strings
- List<string> strings = new List<string>();
- while (true)
- {
- string str = "";
- char c = (char)255;
- while (c != 0)
- {
- if (c != (char)255)
- str += c;
- c = br.ReadChar();
- }
- // Add our string
- strings.Add(str);
- if (str == "")
- break;
- }
- }
- private static byte[] Reverse64(byte[] Input)
- {
- byte[] buffer = new byte[Input.Length];
- Array.Copy(Input, buffer, Input.Length);
- for (int x = 0; x < Input.Length; x += 8)
- Array.Reverse(buffer, x, 8);
- Array.Reverse(buffer);
- return buffer;
- }
- public byte[] GetIV(byte[] Table, int Index)
- {
- // Create buffer
- byte[] Buffer = new byte[0x8];
- // Compute
- int num1 = (4 * Index % 4 + 0xFA0) + Index % 4 + (Index - (Index % 4));
- int num2 = this.unk((long)0x51EB851F * num1, 0x20);
- // Get our start index
- int startIndex = 20 * (num1 - 200 * ((num2 >> 6) + (num2 >> 31)));
- // Copy buffer
- Array.Copy(Table, startIndex, Buffer, 0, 0x8);
- // Return our buffer
- return Buffer;
- }
- public byte[] InitIVTable(byte[] Feed)
- {
- // Init tables
- byte[] Table = new byte[0xFB0];
- // Build table
- int ptr = 0;
- for (int i = 0; i < 200; i++)
- {
- for (int x = 0; x < 5; x++)
- {
- // Check next byte
- if (Feed[ptr] == 0x00)
- ptr = 0;
- // Copy 4 times
- Table[(i * 20) + (x * 4)] = Feed[ptr];
- Table[(i * 20) + (x * 4) + 1] = Feed[ptr];
- Table[(i * 20) + (x * 4) + 2] = Feed[ptr];
- Table[(i * 20) + (x * 4) + 3] = Feed[ptr];
- ptr++;
- }
- }
- // Copy BlockNums
- Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA0, 4);
- Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA4, 4);
- Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA8, 4);
- Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFAC, 4);
- // Return table
- return Table;
- }
- private void UpdateIVTable (ref byte[] Table, int Index, byte[] sectionHash)
- {
- // Get our block num index
- int blockNumIndex = Index % 4;
- // Get our block num
- int blockNum = BitConverter.ToInt32(Table, 0xFA0 + (blockNumIndex * 4)) * 4 + Index;
- // Compute
- int num2 = this.unk((long)0x51EB851F * blockNum, 0x20);
- int startIndex = 20 * ((int)blockNum - 200 * ((num2 >> 6) + (num2 >> 31))) + 1;
- // Store our hash index
- int hashIndex = 0;
- for (int x = 0; x < 4; x++)
- {
- Table[startIndex - 1] ^= sectionHash[hashIndex];
- Table[startIndex] ^= sectionHash[hashIndex + 1];
- Table[startIndex + 1] ^= sectionHash[hashIndex + 2];
- Table[startIndex + 2] ^= sectionHash[hashIndex + 3];
- Table[startIndex + 3] ^= sectionHash[hashIndex + 4];
- // Increment indexes
- startIndex += 5;
- hashIndex += 5;
- }
- }
- private int unk(long arg1, byte arg2)
- {
- long result;
- if (arg2 >= 0x40u)
- result = 0;
- else
- result = arg1 >> arg2;
- return (int)result;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement