예제 #1
0
        private CASCHandler(CASCConfig config) : base(config)
        {
            using (var fs = OpenEncodingFile(this))
                Encoding = new EncodingHandler(fs);

            if ((CASCConfig.LoadFlags & LoadFlags.Download) != 0)
            {
                using (var fs = OpenDownloadFile(Encoding, this))
                    Download = new DownloadHandler(fs);
            }

            KeyService.LoadKeys();

            using (var fs = OpenRootFile(Encoding, this))
            {
                if (config.GameType == CASCGameType.WoW)
                {
                    Root = new WowRootHandler(fs);
                }
                else
                {
                    using (var ufs = new FileStream("unk_root", FileMode.Create))
                        fs.BaseStream.CopyTo(ufs);

                    throw new Exception("Unsupported game " + config.BuildUID);
                }
            }

            if ((CASCConfig.LoadFlags & LoadFlags.Install) != 0)
            {
                using (var fs = OpenInstallFile(Encoding, this))
                    Install = new InstallHandler(fs);
            }
        }
예제 #2
0
        private static (byte[] data, bool isDecrypted) Decrypt(byte[] data, int index)
        {
            byte keyNameSize = data[1];

            if (keyNameSize == 0 || keyNameSize != 8)
            {
                throw new BLTEDecoderException(2, "keyNameSize == 0 || keyNameSize != 8");
            }

            byte[] keyNameBytes = new byte[keyNameSize];
            Array.Copy(data, 2, keyNameBytes, 0, keyNameSize);

            ulong keyName = BitConverter.ToUInt64(keyNameBytes, 0);

            byte IVSize = data[keyNameSize + 2];

            if (IVSize != 4 || IVSize > 0x10)
            {
                throw new BLTEDecoderException(2, "IVSize != 4 || IVSize > 0x10");
            }

            byte[] IVpart = new byte[IVSize];
            Array.Copy(data, keyNameSize + 3, IVpart, 0, IVSize);

            if (data.Length < IVSize + keyNameSize + 4)
            {
                throw new BLTEDecoderException(2, "data.Length < IVSize + keyNameSize + 4");
            }

            int dataOffset = keyNameSize + IVSize + 3;

            byte encType = data[dataOffset];

            if (encType != ENCRYPTION_SALSA20 && encType != ENCRYPTION_ARC4) // 'S' or 'A'
            {
                throw new BLTEDecoderException(2, "encType != ENCRYPTION_SALSA20 && encType != ENCRYPTION_ARC4");
            }

            dataOffset++;

            // expand to 8 bytes
            byte[] IV = new byte[8];
            Array.Copy(IVpart, IV, IVpart.Length);

            // magic
            for (int shift = 0, i = 0; i < sizeof(int); shift += 8, i++)
            {
                IV[i] ^= (byte)((index >> shift) & 0xFF);
            }

            byte[] key = KeyService.GetKey(keyName);

            bool hasKey = key != null;

            if (key == null)
            {
                key = new byte[16];
                if (CASCConfig.ThrowOnMissingDecryptionKey && index == 0)
                {
                    throw new BLTEDecoderException(3, "unknown keyname {0:X16}", keyName);
                }
                //return null;
            }

            if (encType == ENCRYPTION_SALSA20)
            {
                ICryptoTransform decryptor = KeyService.SalsaInstance.CreateDecryptor(key, IV);

                return(decryptor.TransformFinalBlock(data, dataOffset, data.Length - dataOffset), hasKey);
            }
            else
            {
                // ARC4 ?
                throw new BLTEDecoderException(2, "encType ENCRYPTION_ARC4 not implemented");
            }
        }
예제 #3
0
        private CASCHandler(CASCConfig config, BackgroundWorkerEx worker) : base(config, worker)
        {
            Logger.WriteLine("CASCHandler: loading encoding data...");

            using (var _ = new PerfCounter("new EncodingHandler()"))
            {
                using (var fs = OpenEncodingFile(this))
                    EncodingHandler = new EncodingHandler(fs, worker);
            }

            Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Download) != 0)
            {
                Logger.WriteLine("CASCHandler: loading download data...");

                using (var _ = new PerfCounter("new DownloadHandler()"))
                {
                    using (var fs = OpenDownloadFile(EncodingHandler, this))
                        DownloadHandler = new DownloadHandler(fs, worker);
                }

                Logger.WriteLine("CASCHandler: loaded {0} download data", EncodingHandler.Count);
            }

            KeyService.LoadKeys();

            Logger.WriteLine("CASCHandler: loading root data...");

            using (var _ = new PerfCounter("new RootHandler()"))
            {
                using (var fs = OpenRootFile(EncodingHandler, this))
                {
                    if (config.GameType == CASCGameType.S2 || config.GameType == CASCGameType.HotS)
                    {
                        RootHandler = new MNDXRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.D3)
                    {
                        RootHandler = new D3RootHandler(fs, worker, this);
                    }
                    else if (config.GameType == CASCGameType.WoW)
                    {
                        RootHandler = new WowRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Agent || config.GameType == CASCGameType.Bna || config.GameType == CASCGameType.Client)
                    {
                        RootHandler = new AgentRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.S1)
                    {
                        RootHandler = new S1RootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.WC3)
                    {
                        RootHandler = new Wc3RootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Hearthstone)
                    {
                        RootHandler = new HSRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Overwatch)
                    {
                        RootHandler = new OwRootHandler(fs, worker, this);
                    }
                    else if (config.GameType == CASCGameType.Destiny2)
                    {
                        RootHandler = new Destiny2RootHandler(fs, worker);
                    }
                    else
                    {
                        using (var ufs = new FileStream("unk_root", FileMode.Create))
                            fs.BaseStream.CopyTo(ufs);
                        throw new Exception("Unsupported game " + config.BuildUID);
                    }
                }
            }

            Logger.WriteLine("CASCHandler: loaded {0} root data", RootHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Install) != 0)
            {
                Logger.WriteLine("CASCHandler: loading install data...");

                using (var _ = new PerfCounter("new InstallHandler()"))
                {
                    using (var fs = OpenInstallFile(EncodingHandler, this))
                        InstallHandler = new InstallHandler(fs, worker);

                    //InstallHandler.Print();
                }

                Logger.WriteLine("CASCHandler: loaded {0} install data", InstallHandler.Count);
            }
        }
예제 #4
0
        private CASCHandler(CASCConfig config, BackgroundWorkerEx worker) : base(config, worker)
        {
            Logger.WriteLine("CASCHandler: loading encoding data...");

            using (var _ = new PerfCounter("new EncodingHandler()"))
            {
                using (var fs = OpenEncodingFile(this))
                    EncodingHandler = new EncodingHandler(fs, worker);
            }

            Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Download) != 0)
            {
                Logger.WriteLine("CASCHandler: loading download data...");

                using (var _ = new PerfCounter("new DownloadHandler()"))
                {
                    using (var fs = OpenDownloadFile(EncodingHandler, this))
                        DownloadHandler = new DownloadHandler(fs, worker);
                }

                Logger.WriteLine("CASCHandler: loaded {0} download data", EncodingHandler.Count);
            }

            KeyService.LoadKeys();

            Logger.WriteLine("CASCHandler: loading root data...");

            using (var _ = new PerfCounter("new RootHandler()"))
            {
                if (config.IsVfsRoot)
                {
                    RootHandler = new TVFSRootHandler(worker, this);
                }
                else
                {
                    using (var fs = OpenRootFile(EncodingHandler, this))
                    {
                        RootHandlerBase UnknownRootHandler()
                        {
                            using (var ufs = new FileStream("unk_root", FileMode.Create))
                                fs.BaseStream.CopyTo(ufs);
                            throw new Exception("Unsupported game " + config.BuildProduct);
                        }

                        RootHandler = config.GameType switch
                        {
                            CASCGameType.S2 => new MNDXRootHandler(fs, worker),
                            CASCGameType.HotS => new MNDXRootHandler(fs, worker),
                            CASCGameType.D3 => new D3RootHandler(fs, worker, this),
                            CASCGameType.WoW => new WowRootHandler(fs, worker),
                            CASCGameType.S1 => new S1RootHandler(fs, worker),
                            CASCGameType.Agent => new DummyRootHandler(fs, worker),
                            CASCGameType.Bna => new DummyRootHandler(fs, worker),
                            CASCGameType.Client => new DummyRootHandler(fs, worker),
                            CASCGameType.Hearthstone => new DummyRootHandler(fs, worker),
                            CASCGameType.Destiny2 => new DummyRootHandler(fs, worker),
                            CASCGameType.Wlby => new DummyRootHandler(fs, worker),
                            CASCGameType.Rtro => new DummyRootHandler(fs, worker),
                            _ => UnknownRootHandler()
                        };
                    }
                }
            }

            Logger.WriteLine("CASCHandler: loaded {0} root data", RootHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Install) != 0)
            {
                Logger.WriteLine("CASCHandler: loading install data...");

                using (var _ = new PerfCounter("new InstallHandler()"))
                {
                    using (var fs = OpenInstallFile(EncodingHandler, this))
                        InstallHandler = new InstallHandler(fs, worker);

                    //InstallHandler.Print();
                }

                Logger.WriteLine("CASCHandler: loaded {0} install data", InstallHandler.Count);
            }
        }