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); } }
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"); } }
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); } }
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); } }