Ejemplo n.º 1
0
        private Blowfish DeduceEncryptionKey(byte[] packet, int pos, int length)
        {
            ulong guessedNullBlock = 0;

            // This is possible because block cipher mode of operation implemented in FFXIV is ECB mode and most of packets are filled with 0x00 byte.
            // (actually, there's so many bytes are filled with 0x00 that it's enough to inspect the first packet sent from the server.)
            //
            // We know that the encryption key is derived from "keyPhrase", "timestamp" and "gameVersion".
            // where "keyPhrase" and "timestamp" are sent as a plaintext in the initial handkeshake phase.
            // Only thing not sent off the wire is the "gameVersion" component but this component can be brute forced in a reasonable time
            // and verify the key by exploiting the fact that ECB mode lacks diffusion.
            //
            // https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB)
            {
                var processor = new BlockProcessor();
                processor.Process(packet, pos, length);
                guessedNullBlock = processor.GetHighestKey();
            }

            for (var gameVer = 1000; gameVer <= 65000; gameVer += 10)
            {
                var key      = LobbyKeyHelper.MakeKey(_initPacket, (ushort)gameVer);
                var blowfish = new Blowfish(key);

                var nullBlock = new byte[8];
                blowfish.Encipher(nullBlock, 0, 8);

                var attempedBlock = BitConverter.ToUInt64(nullBlock, 0);
                if (attempedBlock == guessedNullBlock)
                {
                    return(blowfish);
                }
            }

            // Failed to guess a key for whatever reason; just use hardcoded key as a fallback.
            var fallbackKey = LobbyKeyHelper.MakeKey(_initPacket, FallbackGameVersion);

            return(new Blowfish(fallbackKey));
        }
 public LobbyEncryptionProvider(byte[] initPacket)
 {
     EncKey    = MakeKey(BitConverter.ToUInt32(initPacket, 116), initPacket.Skip(52).TakeWhile(x => x != 0x00).ToArray());
     _blowfish = new Blowfish(EncKey);
 }