public override Stream OpenEntry(ArcFile arc, Entry entry) { var tent = entry as TacEntry; if (null == tent) { return(base.OpenEntry(arc, entry)); } if (tent.IsPacked) { var input = arc.File.CreateStream(entry.Offset, entry.Size); return(new ZLibStream(input, CompressionMode.Decompress)); } var bf = new Blowfish(tent.Key); if (tent.EncryptedSize < tent.Size) { var header = arc.File.View.ReadBytes(tent.Offset, tent.EncryptedSize); bf.Decipher(header, header.Length); var rest = arc.File.CreateStream(tent.Offset + tent.EncryptedSize, tent.Size - tent.EncryptedSize); return(new PrefixStream(header, rest)); } else if (0 == (tent.Size & 7)) { var input = arc.File.CreateStream(tent.Offset, tent.Size); return(new InputCryptoStream(input, bf.CreateDecryptor())); } else { var data = arc.File.View.ReadBytes(tent.Offset, tent.Size); bf.Decipher(data, data.Length & ~7); return(new BinMemoryStream(data)); } }
public override Stream OpenEntry(ArcFile arc, Entry entry) { var larc = arc as LunaArchive; if (null == arc || !arc.File.View.AsciiEqual(entry.Offset, "LZSS")) { return(base.OpenEntry(arc, entry)); } uint unpacked_size = arc.File.View.ReadUInt32(entry.Offset + 4); Stream input = arc.File.CreateStream(entry.Offset + 8, entry.Size - 8); if (larc.Key != null) { var bf = new Blowfish(larc.Key); input = new InputCryptoStream(input, bf.CreateDecryptor()); return(new LimitStream(input, unpacked_size)); } else { var lz = new LzssStream(input); lz.Config.FrameInitPos = 0xFF0; return(lz); } }
public void WriteToStream(Stream writeTo) { using (var fs = File.OpenRead(sourceFile)) using (var br = new BinaryReader(fs)) { fs.Seek(offset, SeekOrigin.Begin); var encrypted = br.ReadBytes(4).SequenceEqual(new byte[] { 0x4C /*L*/, 0x5A /*Z*/, 0x53 /*S*/, 0x53 /*S*/ }); byte[] fileBytesToSave; if (encrypted) { var decryptedSize = br.ReadUInt32(); var fileBytes = br.ReadBytes((int)size); fileBytesToSave = new byte[decryptedSize]; using (var r = new BinaryReader(new CryptoStream(new MemoryStream(fileBytes, 0, fileBytes.Length), Blowfish.CreateDecryptor(), CryptoStreamMode.Read))) { r.Read(fileBytesToSave, 0, fileBytesToSave.Length); } } else { //Reset Location, so we don't skip first four bytes, after reading FileMagic at LOC:74 br.BaseStream.Seek(offset, SeekOrigin.Begin); fileBytesToSave = br.ReadBytes((int)size); } writeTo.Write(fileBytesToSave, 0, fileBytesToSave.Length); } }
internal override Stream DecryptEntry(Stream input, PazEntry entry) { input = new InputCryptoStream(input, Encryption.CreateDecryptor()); var key = entry.Key; if (null == key) { return(input); } var rc4 = new Rc4Transform(key); if (Version >= 2) { uint crc = Crc32.Compute(key, 0, key.Length); int skip_rounds = (int)(crc >> 12) & 0xFF; for (int i = 0; i < skip_rounds; ++i) { rc4.NextByte(); } } return(new InputCryptoStream(input, rc4)); }
public override ArcFile TryOpen(ArcView file) { if (!file.Name.HasExtension(".paz")) { return(null); } uint signature = file.View.ReadUInt32(0); // XXX encryption is queried for every .paz file var scheme = QueryEncryption(file.Name, signature); uint start_offset = scheme.Version > 0 ? 0x20u : 0u; uint index_size = file.View.ReadUInt32(start_offset); start_offset += 4; byte xor_key = (byte)(index_size >> 24); if (xor_key != 0) { index_size ^= (uint)(xor_key << 24 | xor_key << 16 | xor_key << 8 | xor_key); } if (0 != (index_size & 7) || index_size + start_offset >= file.MaxOffset) { return(null); } var arc_list = new List <Entry>(); var arc_dir = VFS.GetDirectoryName(file.Name); long max_offset = file.MaxOffset; for (char suffix = 'A'; suffix <= 'Z'; ++suffix) { var part_name = VFS.CombinePath(arc_dir, file.Name + suffix); if (!VFS.FileExists(part_name)) { break; } var part = VFS.FindFile(part_name); arc_list.Add(part); max_offset += part.Size; } var arc_name = Path.GetFileNameWithoutExtension(file.Name).ToLowerInvariant(); bool is_audio = AudioPazNames.Contains(arc_name); bool is_video = VideoPazNames.Contains(arc_name); Stream input = file.CreateStream(start_offset, index_size); byte[] video_key = null; List <Entry> dir; try { if (xor_key != 0) { input = new XoredStream(input, xor_key); } var enc = new Blowfish(scheme.ArcKeys[arc_name].IndexKey); input = new InputCryptoStream(input, enc.CreateDecryptor()); using (var index = new ArcView.Reader(input)) { int count = index.ReadInt32(); if (!IsSaneCount(count)) { return(null); } if (is_video) { video_key = index.ReadBytes(0x100); } dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var name = index.BaseStream.ReadCString(); var entry = FormatCatalog.Instance.Create <PazEntry> (name); entry.Offset = index.ReadInt64(); entry.UnpackedSize = index.ReadUInt32(); entry.Size = index.ReadUInt32(); entry.AlignedSize = index.ReadUInt32(); if (!entry.CheckPlacement(max_offset)) { return(null); } entry.IsPacked = index.ReadInt32() != 0; if (string.IsNullOrEmpty(entry.Type) && is_audio) { entry.Type = "audio"; } if (scheme.Version > 0) { string password = ""; if (!entry.IsPacked && scheme.TypeKeys != null) { password = scheme.GetTypePassword(name, is_audio); } if (!string.IsNullOrEmpty(password) || is_video) { password = string.Format("{0} {1:X08} {2}", name.ToLowerInvariant(), entry.UnpackedSize, password); entry.Key = Encodings.cp932.GetBytes(password); } } dir.Add(entry); } } } finally { input.Dispose(); } List <ArcView> parts = null; if (arc_list.Count > 0) { parts = new List <ArcView> (arc_list.Count); try { foreach (var arc_entry in arc_list) { var arc_file = VFS.OpenView(arc_entry); parts.Add(arc_file); } } catch { foreach (var part in parts) { part.Dispose(); } throw; } } if (is_video) { if (scheme.Version < 1) { var table = new byte[0x100]; for (int i = 0; i < 0x100; ++i) { table[video_key[i]] = (byte)i; } video_key = table; } return(new MovPazArchive(file, this, dir, scheme.Version, xor_key, video_key, parts)); } return(new PazArchive(file, this, dir, scheme.Version, xor_key, scheme.ArcKeys[arc_name].DataKey, parts)); }