internal GrpMetaData UnpackHeader(CowArray <byte> header) { uint width = header.ToUInt32(0); uint height = header.ToUInt32(4); int bpp = header.ToInt32(8); int packed_size = header.ToInt32(0x0C); int unpacked_size = header.ToInt32(0x10); if (0 == width || 0 == height || width > 0x7fff || height > 0x7fff || (bpp != 24 && bpp != 8) || unpacked_size <= 0 || packed_size < 0) { return(null); } return(new GrpMetaData { Width = width, Height = height, BPP = bpp, PackedSize = packed_size, UnpackedSize = unpacked_size, Offset = header.ToInt32(0x14), HeaderSize = 0x18, AlphaChannel = false, }); }
byte[] QueryKey(string arc_name) { if (VFS.IsVirtual) { return(null); } var dir = VFS.GetDirectoryName(arc_name); var parent_dir = Directory.GetParent(dir).FullName; var exe_files = VFS.GetFiles(VFS.CombinePath(parent_dir, "*.exe")).Concat(VFS.GetFiles(VFS.CombinePath(dir, "*.exe"))); foreach (var exe_entry in exe_files) { try { using (var exe = new ExeFile.ResourceAccessor(exe_entry.Name)) { var code = exe.GetResource("CIPHERCODE", "CODE"); if (null == code) { continue; } if (20 == code.Length) { code = new CowArray <byte> (code, 4, 16).ToArray(); } return(code); } } catch { /* ignore errors */ } } return(null); }
public override ArcFile TryOpen(ArcView file) { if (null == KnownSchemes) { throw new OperationCanceledException("Outdated encryption schemes database"); } var cpz = CpzHeader.Parse(file); if (null == cpz) { return(null); } var index = file.View.ReadBytes(cpz.IndexOffset, cpz.IndexSize); if (!cpz.VerifyIndex(index)) { return(null); } int file_table_size = cpz.DirEntriesSize + cpz.FileEntriesSize; if (cpz.IndexKeySize > 24) { var index_key = UnpackIndexKey(index, file_table_size, cpz.IndexKeySize); for (int i = 0; i < file_table_size; ++i) { index[i] ^= index_key[(i + 3) % 0x3FF]; } } ArchiveKey arc_key = null; if (cpz.Version > 6) { arc_key = FindArchiveKey(file.Name); } if (null == arc_key) { arc_key = new ArchiveKey(); } var index_copy = new CowArray <byte> (index, 0, file_table_size).ToArray(); var cmvs_md5 = cpz.CmvsMd5.Clone() as uint[]; foreach (var scheme in KnownSchemes.Values.Where(s => s.Version == cpz.Version)) { var arc = ReadIndex(file, scheme, cpz, index, arc_key); if (null != arc) { return(arc); } // both CmvsMd5 and index was altered by ReadIndex in decryption attempt Array.Copy(cmvs_md5, cpz.CmvsMd5, 4); Array.Copy(index, index_copy, file_table_size); } throw new UnknownEncryptionScheme(); }
static unsafe void DecryptData(byte[] data, int pos, int length, uint key, uint seed) { if (pos < 0 || pos + length > data.Length) { throw new ArgumentOutOfRangeException("pos", "Invalid byte array index."); fixed(byte *data8 = &data[pos]) { uint *data32 = (uint *)data8; for (int count = length / 4; count > 0; --count) { *data32 ^= key; key += Binary.RotL(*data32, 16) ^ seed; data32++; } } } RepiEntry EntryFromMd5(byte[] data, int pos, StringBuilder builder) { var key = new CowArray <byte> (data, pos, 16).ToArray(); string name; if (KnownNames.TryGetValue(key, out name)) { var entry = FormatCatalog.Instance.Create <RepiEntry> (name); entry.HasEncryptionKey = true; return(entry); } builder.Clear(); for (int i = 0; i < 16; ++i) { builder.AppendFormat("{0:x2}", key[i]); } return(new RepiEntry { Name = builder.ToString() }); }