Example #1
0
        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,
            });
        }
Example #2
0
        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);
        }
Example #3
0
        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();
        }
Example #4
0
        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()
            });
        }