Пример #1
0
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Usage: UnWak [FILE] [<path>]");
                Console.WriteLine("Unpack wak file");
                return;
            }

            byte[] wak_buffer = null;

            try
            {
                using (FileStream wak_file = File.OpenRead(args[0]))
                {
                    wak_buffer = new byte[wak_file.Length];
                    wak_file.Read(wak_buffer, 0, (int)wak_file.Length);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine($"Failed to read wak file: {e}");
                Environment.Exit(-1);
            }

            FiletableEntry[] filetable = WakDecryptor.DecryptWak(wak_buffer);
            Console.WriteLine($"Wak file decrypted, found {filetable.Length} files");

            Console.Write("Unpacking...   0%");

            string parent_path = args.Length > 1 ? args[1] : "";

            for (int i = 0; i < filetable.Length; i++)
            {
                FiletableEntry filetable_entry = filetable[i];
                string         path            = Path.Combine(parent_path, filetable_entry.filename);

                try
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                    using (FileStream file = File.Create(path))
                    {
                        file.Write(wak_buffer, filetable_entry.file_offset, filetable_entry.file_size);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine($"\nFailed to write file {path}: {e}");
                    Environment.Exit(-1);
                }

                if (i % (filetable.Length / 100) == 0)
                {
                    Console.Write($"\b\b\b\b{(100 * i / filetable.Length).ToString().PadLeft(3, ' ')}%");
                }
            }

            Console.WriteLine("\b\b\b\b100%\nDone");
        }
Пример #2
0
        /// <summary>
        /// Decrypts the specified wak file and copies the resulting data to the output byte array
        /// </summary>
        /// <param name="wak_file">The wak file to decrypt</param>
        /// <param name="output">The output to which to write the decrypted file</param>
        /// <returns></returns>
        static public FiletableEntry[] DecryptWak(byte[] wak_file, byte[] output)
        {
            byte[] key = new byte[16];
            byte[] IV  = new byte[16];
            GenerateIV(key, Constants.wak_key_seed);
            GenerateIV(IV, Constants.wak_header_IV_seed);

            Aes128CounterMode aes = new Aes128CounterMode(IV);
            ICryptoTransform  ict = aes.CreateDecryptor(key, null);

            ict.TransformBlock(wak_file, 0, 16, output, 0); // decrypt header

            int num_files    = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(output, 4, 4));
            int files_offset = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(output, 8, 4));

            FiletableEntry[] fileTable = new FiletableEntry[num_files];

            GenerateIV(IV, Constants.wak_filetable_IV_seed);
            ict.TransformBlock(wak_file, 16, files_offset - 16, output, 16); // decrypt filetable

            int entry_offset = 16;

            for (int i = 0; i < num_files; i++)
            {
                int    file_offset     = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(output, entry_offset, 4));
                int    file_size       = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(output, entry_offset + 4, 4));
                int    filename_length = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(output, entry_offset + 8, 4));
                string filename        = Encoding.UTF8.GetString(new ReadOnlySpan <byte>(output, entry_offset + 12, filename_length));

                GenerateIV(IV, i);                                                         // file IV
                ict.TransformBlock(wak_file, file_offset, file_size, output, file_offset); // decrypt file

                fileTable[i].file_offset = file_offset;
                fileTable[i].file_size   = file_size;
                fileTable[i].filename    = filename;

                entry_offset += 12 + filename_length;
            }

            return(fileTable);
        }