private static byte[] FindKey(byte[] input) { var md5 = new MD5CryptoServiceProvider(); var count = 0; var found = false; var ffHash = new byte[] { 0xde, 0x03, 0xfe, 0x65, 0xa6, 0x76, 0x5c, 0xaa, 0x8c, 0x91, 0x34, 0x3a, 0xcc, 0x62, 0xcf, 0xfc }; var hashList = new HashEntry[(input.Length / 0x200) + 1]; for (var i = 0; i < (input.Length / 0x200); i++, found = false) { var hash = md5.ComputeHash(input, i * 0x200, 0x200); if (BufferSame(hash, ffHash, 16)) //skip ff blocks... continue; // see if we already came up with that hash for (var j = 0; j < count; j++) if (BufferSame(hashList[j].Hash, hash, 16)) { hashList[j].Count++; found = true; break; } // push new hashlist entry if (found) continue; hashList[count] = new HashEntry { Hash = new byte[hash.Length] }; Buffer.BlockCopy(hash, 0, hashList[count].Hash, 0, hash.Length); hashList[count].Count = 1; hashList[count].BlockIndex = i; count++; } //Sort by count, Decending Array.Sort(hashList, (entry1, entry2) => entry2.Count - entry1.Count); //Check the keys one by one var foundOffset = 0; for (var i=0 ; i<hashList.Count() && !found; i++) { foundOffset = hashList[i].BlockIndex * 0x200; if (((input[0x100] ^ input[foundOffset + 0x100]) == 'D') && ((input[0x101] ^ input[foundOffset + 0x101]) == 'I') && ((input[0x102] ^ input[foundOffset + 0x102]) == 'S') && ((input[0x103] ^ input[foundOffset + 0x103]) == 'A')) found = true; } if (!found) return null; //That's not it var outbuf = new byte[0x200]; Buffer.BlockCopy(input, foundOffset, outbuf, 0, 0x200); return outbuf; }