Advertisement
Guest User

Black Ops Decryption

a guest
Oct 1st, 2011
3,383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.02 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using CoreExtensions.IO;
  7. using CoreExtensions;
  8. using System.Security.Cryptography;
  9. using Crypto;
  10. using Ionic.Zlib;
  11. using Org.BouncyCastle.Security;
  12. using Org.BouncyCastle.Crypto.Parameters;
  13. using Org.BouncyCastle.Math;
  14. using Org.BouncyCastle.Crypto;
  15.  
  16. namespace FFCrypt
  17. {
  18.     public class FastFile
  19.     {
  20.         private EndianReader br { get; set; }
  21.         public FastFile(string fileName)
  22.         {
  23.             // Create reader
  24.             this.br = new EndianReader(new FileStream(fileName, FileMode.Open), EndianStyle.BigEndian);
  25.  
  26.             // Verify magic
  27.             if (br.ReadInt32() != 0x49576666)
  28.                 Console.WriteLine("Invalid fast file magic!");
  29.  
  30.             if (br.ReadInt32() != 0x30313030)
  31.                 Console.WriteLine("Invalid fast file magic!");
  32.  
  33.             // Read our count?
  34.             int count = br.ReadInt32();
  35.             br.ReadInt32();
  36.  
  37.             // Verify second magic
  38.             if (br.ReadInt64() != 0x5048454542733731)
  39.                 Console.WriteLine("Invalid fast file magic!");
  40.  
  41.             // Move
  42.             this.br.ReadInt32();
  43.  
  44.             // Get our zone
  45.             EndianReader zoneReader = this.GetZone();
  46.  
  47.             // Raed
  48.             this.ReadZoneFile(zoneReader);
  49.         }
  50.  
  51.         private EndianReader GetZone()
  52.         {
  53.             // Read IV table feed/name
  54.             byte[] feed = this.br.ReadBytes(0x20);
  55.             byte[] sig = this.br.ReadBytes(0x100);
  56.  
  57.             // Build our IV table
  58.             byte[] table = this.InitIVTable(feed);
  59.  
  60.             // Go past sig
  61.             this.br.BaseStream.Position = 0x13C;
  62.  
  63.             // Set key
  64.             byte[] Key = { 0x1a, 0xc1, 0xd1, 0x2d, 0x52, 0x7c, 0x59, 0xb4, 0x0e,
  65.                              0xca, 0x61, 0x91, 0x20, 0xff, 0x82, 0x17, 0xcc, 0xff,
  66.                              0x09, 0xcd, 0x16, 0x89, 0x6f, 0x81, 0xb8, 0x29, 0xc7,
  67.                              0xf5, 0x27, 0x93, 0x40, 0x5d };
  68.  
  69.             // Init Salsa
  70.             Salsa20 salsa = new Salsa20();
  71.             salsa.Key = Key;
  72.  
  73.             // Make filestream
  74.             FileStream fileStream = new FileStream("C:\\ZONEFILE", FileMode.Create);
  75.  
  76.             // Create output
  77.             BinaryWriter bw = new BinaryWriter(fileStream);
  78.  
  79.             // Store our section index
  80.             int sectionIndex = 0;
  81.  
  82.             // Keep going till we get an empty section
  83.             while(true)
  84.             {
  85.                 // Read section size
  86.                 int sectionSize = this.br.ReadInt32();
  87.                 if (sectionSize == 0)
  88.                     break;
  89.  
  90.                 // Read section data
  91.                 byte[] sectionData = this.br.ReadBytes(sectionSize);
  92.  
  93.                 // Set our IV
  94.                 salsa.IV = this.GetIV(table, sectionIndex);
  95.  
  96.                 // Get our decrypted data
  97.                 byte[] decData = salsa.CreateDecryptor().TransformFinalBlock(sectionData, 0, sectionSize);
  98.  
  99.                 // Get hash
  100.                 byte[] sectionHash = Security.SHA1(decData);
  101.  
  102.                 // Create new buffer
  103.                 byte[] compressedData = new byte[decData.Length + 2];
  104.  
  105.                 // Copy our decrypted data
  106.                 Array.Copy(decData, 0, compressedData, 2, decData.Length);
  107.  
  108.                 // Setup header
  109.                 compressedData[0] = 0x78;
  110.                 compressedData[1] = 0x01;
  111.  
  112.                 // Write our compressed data
  113.                 bw.Write(ZlibStream.UncompressBuffer(compressedData));
  114.  
  115.                 // Update IV table
  116.                 this.UpdateIVTable(ref table, sectionIndex, sectionHash);
  117.  
  118.                 // Increment our section index
  119.                 sectionIndex++;
  120.             }
  121.  
  122.             // Save our IV table
  123.             File.WriteAllBytes("C:\\IVTABLE", table);
  124.  
  125.             // Create binary reader and move to start
  126.             EndianReader br = new EndianReader(fileStream, EndianStyle.BigEndian);
  127.             br.BaseStream.Position = 0;
  128.  
  129.             // Return our reader
  130.             return br;
  131.         }
  132.  
  133.         private void ReadZoneFile(EndianReader br)
  134.         {
  135.             // Move to start
  136.             br.BaseStream.Position = 0;
  137.  
  138.             // Read file size - 0x24
  139.             int fileSize = br.ReadInt32();
  140.  
  141.             // Read unknowns
  142.             int unknown1 = br.ReadInt32();
  143.             int unknown2 = br.ReadInt32();
  144.             int unknown3 = br.ReadInt32();
  145.             int unknown4 = br.ReadInt32();
  146.             int unknown5 = br.ReadInt32();
  147.             int unknown6 = br.ReadInt32();
  148.             int unknown7 = br.ReadInt32();
  149.             int unknown8 = br.ReadInt32();
  150.             int stringTableCount = br.ReadInt32();
  151.             int padding1 = br.ReadInt32();
  152.  
  153.             // Read our indexCount
  154.             int indexCount = br.ReadInt32();
  155.  
  156.             int padding2 = br.ReadInt32();
  157.  
  158.             // Move to our string table
  159.             br.BaseStream.Position += stringTableCount * 4;
  160.  
  161.             // Create list of strings
  162.             List<string> strings = new List<string>();
  163.             while (true)
  164.             {
  165.                 string str = "";
  166.                 char c = (char)255;
  167.                 while (c != 0)
  168.                 {
  169.                     if (c != (char)255)
  170.                         str += c;
  171.                     c = br.ReadChar();
  172.                 }
  173.  
  174.                 // Add our string
  175.                 strings.Add(str);
  176.                 if (str == "")
  177.                     break;
  178.             }
  179.         }
  180.         private static byte[] Reverse64(byte[] Input)
  181.         {
  182.             byte[] buffer = new byte[Input.Length];
  183.             Array.Copy(Input, buffer, Input.Length);
  184.             for (int x = 0; x < Input.Length; x += 8)
  185.                 Array.Reverse(buffer, x, 8);
  186.  
  187.             Array.Reverse(buffer);
  188.             return buffer;
  189.         }
  190.  
  191.         public byte[] GetIV(byte[] Table, int Index)
  192.         {
  193.             // Create buffer
  194.             byte[] Buffer = new byte[0x8];
  195.  
  196.             // Compute
  197.             int num1 = (4 * Index % 4 + 0xFA0) + Index % 4 + (Index - (Index % 4));
  198.             int num2 = this.unk((long)0x51EB851F * num1, 0x20);
  199.  
  200.             // Get our start index
  201.             int startIndex = 20 * (num1 - 200 * ((num2 >> 6) + (num2 >> 31)));
  202.  
  203.             // Copy buffer
  204.             Array.Copy(Table, startIndex, Buffer, 0, 0x8);
  205.  
  206.             // Return our buffer
  207.             return Buffer;
  208.         }
  209.  
  210.         public byte[] InitIVTable(byte[] Feed)
  211.         {
  212.             // Init tables
  213.             byte[] Table = new byte[0xFB0];
  214.            
  215.             // Build table
  216.             int ptr = 0;
  217.             for (int i = 0; i < 200; i++)
  218.             {
  219.                 for (int x = 0; x < 5; x++)
  220.                 {
  221.                     // Check next byte
  222.                     if (Feed[ptr] == 0x00)
  223.                         ptr = 0;
  224.  
  225.                     // Copy 4 times
  226.                     Table[(i * 20) + (x * 4)] = Feed[ptr];
  227.                     Table[(i * 20) + (x * 4) + 1] = Feed[ptr];
  228.                     Table[(i * 20) + (x * 4) + 2] = Feed[ptr];
  229.                     Table[(i * 20) + (x * 4) + 3] = Feed[ptr];
  230.                     ptr++;
  231.                 }
  232.             }
  233.  
  234.             // Copy BlockNums
  235.             Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA0, 4);
  236.             Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA4, 4);
  237.             Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFA8, 4);
  238.             Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, Table, 0xFAC, 4);
  239.  
  240.             // Return table
  241.             return Table;
  242.         }
  243.  
  244.         private void UpdateIVTable (ref byte[] Table, int Index, byte[] sectionHash)
  245.         {
  246.             // Get our block num index
  247.             int blockNumIndex = Index % 4;
  248.  
  249.             // Get our block num
  250.             int blockNum = BitConverter.ToInt32(Table, 0xFA0 + (blockNumIndex * 4)) * 4 + Index;
  251.  
  252.             // Compute
  253.             int num2 = this.unk((long)0x51EB851F * blockNum, 0x20);
  254.             int startIndex = 20 * ((int)blockNum - 200 * ((num2 >> 6) + (num2 >> 31))) + 1;
  255.  
  256.             // Store our hash index
  257.             int hashIndex = 0;
  258.  
  259.             for (int x = 0; x < 4; x++)
  260.             {
  261.                 Table[startIndex - 1] ^= sectionHash[hashIndex];
  262.                 Table[startIndex] ^= sectionHash[hashIndex + 1];
  263.                 Table[startIndex + 1] ^= sectionHash[hashIndex + 2];
  264.                 Table[startIndex + 2] ^= sectionHash[hashIndex + 3];
  265.                 Table[startIndex + 3] ^= sectionHash[hashIndex + 4];
  266.  
  267.                 // Increment indexes
  268.                 startIndex += 5;
  269.                 hashIndex += 5;
  270.             }
  271.         }
  272.  
  273.  
  274.         private int unk(long arg1, byte arg2)
  275.         {
  276.             long result;
  277.  
  278.             if (arg2 >= 0x40u)
  279.                 result = 0;
  280.             else
  281.                 result = arg1 >> arg2;
  282.             return (int)result;
  283.         }
  284.     }
  285. }
  286.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement