Example #1
0
        // fixing PNG headers by guessing is quite simple
        // - the width and heght fields (2x 4 bytes) are XORed with a "random" key
        //   -> this key is an ascii representation of a hash.
        //   -> Thus it consists of 8 chars in the range of '0'..'9' or 'a'..'f'
        // - first we assume dimensions < 65536 in each direction (sounds sane)
        //   -> this means we already have 4 of the 8 key bytes (the two high order bytes from each dimension)
        // - now we walk through all possible key values "00" to "ff" for each of the lower order byte pairs
        //   -> this means 256 (for x dimension) x 256 (for y dimension) tries
        //   -> in each try, we check if the CRC if the IHDR chunk is now correct
        //   ->  if it is correct then we found the remaining 2x2 bytes of the key
        private byte[] FixPngHdr(byte[] hdr, ref string key, ICRCAlgorithm crcAlgo)
        {
            byte[] result = new byte[hdr.Length];
            ulong target_crc = (ulong)hdr[hdr.Length - 4] << 24 |
                (ulong)hdr[hdr.Length - 3] << 16 |
                (ulong)hdr[hdr.Length - 2] << 8 |
                (ulong)hdr[hdr.Length - 1];
            ulong crc;

            hdr.CopyTo(result, 0);

            // first, set higher order positions to zero
            result[4] = result[5] = 0;
            result[8] = result[9] = 0;

            for (int key1 = 0; key1 < 256; key1++)
            {
                // ascii representation of key1
                string k1 = key1.ToString("x2").ToLower();
                byte b1 = (byte)(k1[0]);
                byte b2 = (byte)(k1[1]);

                result[6] = (byte)(hdr[6] ^ b1);
                result[7] = (byte)(hdr[7] ^ b2);

                for (int key2 = 0; key2 < 256; key2++)
                {
                    string k2 = key2.ToString("x2").ToLower();
                    byte b3 = (byte)(k2[0]);
                    byte b4 = (byte)(k2[1]);

                    result[10] = (byte)(hdr[10] ^ b3);
                    result[11] = (byte)(hdr[11] ^ b4);

                    crc = crcAlgo.CalculateCRC(result, result.Length - 4);
                    if (crc == target_crc)
                    {
                        key = Encoding.ASCII.GetString(new byte[] { hdr[4], hdr[5], b1, b2, hdr[8], hdr[9], b3, b4 });
                        return result;
                    }
                }
            }

            key = "";
            return null;
        }