// Try to decrypt incoming data.
        public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length)
        {
            #region m_Encryption != null
            if (m_Encryption != null)
            {
                // If we're decrypting using LoginCrypt and we've already been relayed,
                // only decrypt a single packet using logincrypt and then disable it
                if (m_AlreadyRelayed && m_Encryption is LoginEncryption)
                {
                    uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2);

                    // Swap the seed
                    newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000);

                    // XOR it with the old seed
                    newSeed ^= m_Seed;

                    IClientEncryption newEncryption = new GameEncryption(newSeed);

                    // Game Encryption comes first
                    newEncryption.clientDecrypt(ref buffer, length);

                    // The login encryption is still used for this one packet
                    m_Encryption.clientDecrypt(ref buffer, length);

                    // Swap the encryption schemes
                    m_Encryption = newEncryption;
                    m_Seed = newSeed;

                    return;
                }

                m_Encryption.clientDecrypt(ref buffer, length);
                return;
            }
            #endregion

            #region Port Scan
            //11JUN2008 GOW SVN fix ** START ***
            // If the client did not connect on the game server port,
            // it's not our business to handle encryption for it
            //if (((IPEndPoint)from.Socket.LocalEndPoint).Port != Listener.Port) 
            //{
            //    m_Encryption = new NoEncryption();
            //    return;
            //}
            bool handle = false;

            for (int i = 0; i < Listener.EndPoints.Length; i++)
            {
                IPEndPoint ipep = (IPEndPoint)Listener.EndPoints[i];

                if (((IPEndPoint)from.Socket.LocalEndPoint).Port == ipep.Port)
                    handle = true;
            }

            if (!handle)
            {
                m_Encryption = new NoEncryption();
                return;
            }
            #endregion

            #region !m_Seeded
            // For simplicities sake, enqueue what we just received as long as we're not initialized
            m_Buffer.Enqueue(buffer, 0, length);
            // Clear the array
            length = 0;

            // If we didn't receive the seed yet, queue data until we can read the seed
            //if (!m_Seeded) 
            //{
            //    // Now check if we have at least 4 bytes to get the seed
            //    if (m_Buffer.Length >= 4) 
            //    {
            //        byte[] m_Peek = new byte[m_Buffer.Length];
            //        m_Buffer.Dequeue( m_Peek, 0, m_Buffer.Length ); // Dequeue everything
            //        m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
            //        m_Seeded = true;

            //        Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
            //        length = 4;
            //    } 
            //    else 
            //    {
            //        return;
            //    }
            //}
            //http://uodev.de/viewtopic.php?t=5097&postdays=0&postorder=asc&start=15&sid=dfb8e6c73b9e3eb95c1634ca3586e8a7
            //if (!m_Seeded)
            //{
            //    int seed_length = m_Buffer.GetSeedLength();

            //    if (m_Buffer.Length >= seed_length)
            //    {
            //        byte[] m_Peek = new byte[m_Buffer.Length];
            //        m_Buffer.Dequeue(m_Peek, 0, seed_length);

            //        if (seed_length == 4)
            //            m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
            //        else if (seed_length == 21)
            //            m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);

            //        m_Seeded = true;

            //        Buffer.BlockCopy(m_Peek, 0, buffer, 0, seed_length);
            //        length = seed_length;
            //    }
            //    else
            //    {
            //        return;
            //    }
            //}

            //11JUN2008 My Version

            if (!m_Seeded)
            {
                if (m_Buffer.Length <= 3) //Short Length, try again.
                {
                    Console.WriteLine("Encryption: Failed - Short Lenght");
                    return;
                }
                //else if ((m_Buffer.Length == 83) && (m_Buffer.GetPacketID() == 239)) //New Client
                //{
                //    byte[] m_Peek = new byte[21];
                //    m_Buffer.Dequeue(m_Peek, 0, 21);

                //    m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);
                //    m_Seeded = true;

                //    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21);
                //    length = 21;

                //    Console.WriteLine("Encryption: Passed - New Client");
                //}

                //05MAR2009 Smjert's fix for double log in.  *** START ***
                else if ((m_Buffer.Length == 83 || m_Buffer.Length == 21) && (m_Buffer.GetPacketID() == 239)) //New Client
                {
                    length = m_Buffer.Length;
                    byte[] m_Peek = new byte[21];
                    m_Buffer.Dequeue(m_Peek, 0, 21);

                    m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21);


                    Console.WriteLine("Encryption: Passed - New Client");

                    // We need to wait the next packet
                    if (length == 21)
                        return;

                    length = 21;
                }

                else if (m_Buffer.Length >= 4) //Old Client
                //05MAR2009 Smjert's fix for double log in.  *** END ***
                {
                    byte[] m_Peek = new byte[4];
                    m_Buffer.Dequeue(m_Peek, 0, 4);

                    m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
                    length = 4;

                    Console.WriteLine("Encryption: Passed - Old Client");
                }
                else //It should never reach here.
                {
                    Console.WriteLine("Encryption: Failed - It should never reach here");
                    return;
                }
            }
            #endregion

            // If the context isn't initialized yet, that means we haven't decided on an encryption method yet
            #region m_Encryption == null
            if (m_Encryption == null)
            {
                int packetLength = m_Buffer.Length;
                int packetOffset = length;
                m_Buffer.Dequeue(buffer, length, packetLength); // Dequeue everything
                length += packetLength;

                // This is special handling for the "special" UOG packet
                if (packetLength >= 3)
                {
                    if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF))
                    {
                        m_Encryption = new NoEncryption();
                        return;
                    }
                }

                // Check if the current buffer contains a valid login packet (62 byte + 4 byte header)
                // Please note that the client sends these in two chunks. One 4 byte and one 62 byte.
                if (packetLength == 62)
                {
                    Console.WriteLine("Checking packetLength 62 == " + packetLength);
                    // Check certain indices in the array to see if the given data is unencrypted
                    if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00)
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        LoginEncryption encryption = new LoginEncryption();
                        if (encryption.init(m_Seed, buffer, packetOffset, packetLength))
                        {
                            Console.WriteLine("Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name);
                            m_Encryption = encryption;
                            Console.WriteLine("Encryption: Check 1");
                            byte[] packet = new byte[packetLength];
                            Console.WriteLine("Encryption: Check 2");
                            Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                            Console.WriteLine("Encryption: Check 3");
                            encryption.clientDecrypt(ref packet, packet.Length);
                            Console.WriteLine("Encryption: Check 4");
                            Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                            Console.WriteLine("Encryption: Check 5");
                            //return; //Just throwing this in.
                        }
                        else
                        {
                            Console.WriteLine("Detected an unknown client.");
                        }
                    }
                }
                else if (packetLength == 65)
                {
                    Console.WriteLine("Checking packetLength 65 == " + packetLength);
                    // If its unencrypted, use the NoEncryption class
                    if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF))
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                        }
                    }
                    else
                    {
                        // If it's not an unencrypted packet, simply assume it's encrypted with the seed
                        m_Encryption = new GameEncryption(m_Seed);

                        byte[] packet = new byte[packetLength];
                        Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                        m_Encryption.clientDecrypt(ref packet, packet.Length);
                        Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                    }
                }

                // If it's still not initialized, copy the data back to the queue and wait for more
                if (m_Encryption == null)
                {
                    Console.WriteLine("Encryption: Check - Waiting");
                    m_Buffer.Enqueue(buffer, packetOffset, packetLength);
                    length -= packetLength;
                    return;
                }
            }
            #endregion
        }
Example #2
0
        // Try to decrypt incoming data.
        public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length)
        {
            #region m_Encryption != null
            if (m_Encryption != null)
            {
                // If we're decrypting using LoginCrypt and we've already been relayed,
                // only decrypt a single packet using logincrypt and then disable it
                if (m_AlreadyRelayed && m_Encryption is LoginEncryption)
                {
                    uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2);

                    // Swap the seed
                    newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000);

                    // XOR it with the old seed
                    newSeed ^= m_Seed;

                    IClientEncryption newEncryption = new GameEncryption(newSeed);

                    // Game Encryption comes first
                    newEncryption.clientDecrypt(ref buffer, length);

                    // The login encryption is still used for this one packet
                    m_Encryption.clientDecrypt(ref buffer, length);

                    // Swap the encryption schemes
                    m_Encryption = newEncryption;
                    m_Seed       = newSeed;

                    return;
                }

                m_Encryption.clientDecrypt(ref buffer, length);
                return;
            }
            #endregion

            #region Port Scan
            //11JUN2008 RunUO SVN fix ** START ***
            // If the client did not connect on the game server port,
            // it's not our business to handle encryption for it
            //if (((IPEndPoint)from.Socket.LocalEndPoint).Port != Listener.Port)
            //{
            //    m_Encryption = new NoEncryption();
            //    return;
            //}
            bool handle = false;

            for (int i = 0; i < Listener.EndPoints.Length; i++)
            {
                IPEndPoint ipep = (IPEndPoint)Listener.EndPoints[i];

                if (((IPEndPoint)from.Socket.LocalEndPoint).Port == ipep.Port)
                {
                    handle = true;
                }
            }

            if (!handle)
            {
                m_Encryption = new NoEncryption();
                return;
            }
            //11JUN2008 RunUO SVN fix ** END ***
            #endregion

            #region !m_Seeded
            // For simplicities sake, enqueue what we just received as long as we're not initialized
            m_Buffer.Enqueue(buffer, 0, length);
            // Clear the array
            length = 0;

            // If we didn't receive the seed yet, queue data until we can read the seed
            //if (!m_Seeded)
            //{
            //    // Now check if we have at least 4 bytes to get the seed
            //    if (m_Buffer.Length >= 4)
            //    {
            //        byte[] m_Peek = new byte[m_Buffer.Length];
            //        m_Buffer.Dequeue( m_Peek, 0, m_Buffer.Length ); // Dequeue everything
            //        m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
            //        m_Seeded = true;

            //        Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
            //        length = 4;
            //    }
            //    else
            //    {
            //        return;
            //    }
            //}
            //http://uodev.de/viewtopic.php?t=5097&postdays=0&postorder=asc&start=15&sid=dfb8e6c73b9e3eb95c1634ca3586e8a7
            //if (!m_Seeded)
            //{
            //    int seed_length = m_Buffer.GetSeedLength();

            //    if (m_Buffer.Length >= seed_length)
            //    {
            //        byte[] m_Peek = new byte[m_Buffer.Length];
            //        m_Buffer.Dequeue(m_Peek, 0, seed_length);

            //        if (seed_length == 4)
            //            m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
            //        else if (seed_length == 21)
            //            m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);

            //        m_Seeded = true;

            //        Buffer.BlockCopy(m_Peek, 0, buffer, 0, seed_length);
            //        length = seed_length;
            //    }
            //    else
            //    {
            //        return;
            //    }
            //}

            //11JUN2008 My Version

            if (!m_Seeded)
            {
                if (m_Buffer.Length <= 3) //Short Length, try again.
                {
                    Console.WriteLine("Encryption: Failed - Short Lenght");
                    return;
                }
                //else if ((m_Buffer.Length == 83) && (m_Buffer.GetPacketID() == 239)) //New Client
                //{
                //    byte[] m_Peek = new byte[21];
                //    m_Buffer.Dequeue(m_Peek, 0, 21);

                //    m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);
                //    m_Seeded = true;

                //    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21);
                //    length = 21;

                //    Console.WriteLine("Encryption: Passed - New Client");
                //}

                //05MAR2009 Smjert's fix for double log in.  *** START ***
                else if ((m_Buffer.Length == 83 || m_Buffer.Length == 21) && (m_Buffer.GetPacketID() == 239)) //New Client
                {
                    length = m_Buffer.Length;
                    byte[] m_Peek = new byte[21];
                    m_Buffer.Dequeue(m_Peek, 0, 21);

                    m_Seed   = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21);


                    Console.WriteLine("Encryption: Passed - New Client");

                    // We need to wait the next packet
                    if (length == 21)
                    {
                        return;
                    }

                    length = 21;
                }

                else if (m_Buffer.Length >= 4) //Old Client
                //05MAR2009 Smjert's fix for double log in.  *** END ***
                {
                    byte[] m_Peek = new byte[4];
                    m_Buffer.Dequeue(m_Peek, 0, 4);

                    m_Seed   = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
                    length = 4;

                    Console.WriteLine("Encryption: Passed - Old Client");
                }
                else //It should never reach here.
                {
                    Console.WriteLine("Encryption: Failed - It should never reach here");
                    return;
                }
            }
            #endregion

            // If the context isn't initialized yet, that means we haven't decided on an encryption method yet
            #region m_Encryption == null
            if (m_Encryption == null)
            {
                int packetLength = m_Buffer.Length;
                int packetOffset = length;
                m_Buffer.Dequeue(buffer, length, packetLength); // Dequeue everything
                length += packetLength;

                // This is special handling for the "special" UOG packet
                if (packetLength >= 3)
                {
                    if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF))
                    {
                        m_Encryption = new NoEncryption();
                        return;
                    }
                }

                // Check if the current buffer contains a valid login packet (62 byte + 4 byte header)
                // Please note that the client sends these in two chunks. One 4 byte and one 62 byte.
                if (packetLength == 62)
                {
                    Console.WriteLine("Checking packetLength 62 == " + packetLength);
                    // Check certain indices in the array to see if the given data is unencrypted
                    if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00)
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        LoginEncryption encryption = new LoginEncryption();
                        if (encryption.init(m_Seed, buffer, packetOffset, packetLength))
                        {
                            Console.WriteLine("Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name);
                            m_Encryption = encryption;
                            Console.WriteLine("Encryption: Check 1");
                            byte[] packet = new byte[packetLength];
                            Console.WriteLine("Encryption: Check 2");
                            Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                            Console.WriteLine("Encryption: Check 3");
                            encryption.clientDecrypt(ref packet, packet.Length);
                            Console.WriteLine("Encryption: Check 4");
                            Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                            Console.WriteLine("Encryption: Check 5");
                            //return; //Just throwing this in.
                        }
                        else
                        {
                            Console.WriteLine("Detected an unknown client.");
                        }
                    }
                }
                else if (packetLength == 65)
                {
                    Console.WriteLine("Checking packetLength 65 == " + packetLength);
                    // If its unencrypted, use the NoEncryption class
                    if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF))
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                        }
                    }
                    else
                    {
                        // If it's not an unencrypted packet, simply assume it's encrypted with the seed
                        m_Encryption = new GameEncryption(m_Seed);

                        byte[] packet = new byte[packetLength];
                        Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                        m_Encryption.clientDecrypt(ref packet, packet.Length);
                        Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                    }
                }

                // If it's still not initialized, copy the data back to the queue and wait for more
                if (m_Encryption == null)
                {
                    Console.WriteLine("Encryption: Check - Waiting");
                    m_Buffer.Enqueue(buffer, packetOffset, packetLength);
                    length -= packetLength;
                    return;
                }
            }
            #endregion
        }
Example #3
0
        // Try to decrypt incoming data.
        public void DecodeIncomingPacket( NetState from, ref byte[] buffer, ref int length )
        {
            if (m_Encryption != null)
            {
                // If we're decrypting using LoginCrypt and we've already been relayed,
                // only decrypt a single packet using logincrypt and then disable it
                if (m_AlreadyRelayed && m_Encryption is LoginEncryption)
                {
                    uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2);

                    // Swap the seed
                    newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000);

                    // XOR it with the old seed
                    newSeed ^= m_Seed;

                    IClientEncryption newEncryption = new GameEncryption(newSeed);

                    // Game Encryption comes first
                    newEncryption.clientDecrypt(ref buffer, length);

                    // The login encryption is still used for this one packet
                    m_Encryption.clientDecrypt(ref buffer, length);

                    // Swap the encryption schemes
                    m_Encryption = newEncryption;
                    m_Seed = newSeed;

                    return;
                }

                m_Encryption.clientDecrypt(ref buffer, length);
                return;
            }

            // If the client did not connect on the game server port,
            // it's not our business to handle encryption for it
            if (((IPEndPoint)from.Socket.LocalEndPoint).Port != Listener.Port)
            {
                m_Encryption = new NoEncryption();
                return;
            }

            // For simplicities sake, enqueue what we just received as long as we're not initialized
            m_Buffer.Enqueue(buffer, 0, length);
            // Clear the array
            length = 0;

            // If we didn't receive the seed yet, queue data until we can read the seed
            if (!m_Seeded)
            {
                // Now check if we have at least 4 bytes to get the seed
                if (m_Buffer.Length >= 4)
                {
                    byte[] m_Peek = new byte[m_Buffer.Length];
                    m_Buffer.Dequeue( m_Peek, 0, m_Buffer.Length ); // Dequeue everything
                    m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
                    length = 4;
                }
                else
                {
                    return;
                }
            }

            // If the context isn't initialized yet, that means we haven't decided on an encryption method yet
            if (m_Encryption == null)
            {
                int packetLength = m_Buffer.Length;
                int packetOffset = length;
                m_Buffer.Dequeue( buffer, length, packetLength); // Dequeue everything
                length += packetLength;

                // This is special handling for the "special" UOG packet
                if (packetLength >= 3)
                {
                    if (buffer[packetOffset] == 0xf1 && buffer[packetOffset+1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset+2] == (packetLength & 0xFF))
                    {
                        m_Encryption = new NoEncryption();
                        return;
                    }
                }

                // Check if the current buffer contains a valid login packet (62 byte + 4 byte header)
                // Please note that the client sends these in two chunks. One 4 byte and one 62 byte.
                if (packetLength == 62)
                {
                    // Check certain indices in the array to see if the given data is unencrypted
                    if (buffer[packetOffset] == 0x80 && buffer[packetOffset+30] == 0x00 && buffer[packetOffset+60] == 0x00)
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        LoginEncryption encryption = new LoginEncryption();
                        if (encryption.init(m_Seed, buffer, packetOffset, packetLength))
                        {
                            Console.WriteLine( "Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name );
                            m_Encryption = encryption;

                            byte[] packet = new byte[packetLength];
                            Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                            encryption.clientDecrypt(ref packet, packet.Length);
                            Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                        }
                        else
                        {
                            Console.WriteLine("Detected an unknown client.");
                        }
                    }
                }
                else if (packetLength == 65)
                {
                    // If its unencrypted, use the NoEncryption class
                    if ( buffer[packetOffset] == '\x91' && buffer[packetOffset+1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset+2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset+3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset+4] == (m_Seed & 0xFF) )
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    } else {
                        // If it's not an unencrypted packet, simply assume it's encrypted with the seed
                        m_Encryption = new GameEncryption(m_Seed);

                        byte[] packet = new byte[packetLength];
                        Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                        m_Encryption.clientDecrypt(ref packet, packet.Length);
                        Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                    }
                }

                // If it's still not initialized, copy the data back to the queue and wait for more
                if (m_Encryption == null)
                {
                    m_Buffer.Enqueue(buffer, packetOffset, packetLength);
                    length -= packetLength ;
                    return;
                }
            }
        }
Example #4
0
        // Try to decrypt incoming data.
        public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length)
        {
            if (m_Encryption != null)
            {
                // If we're decrypting using LoginCrypt and we've already been relayed,
                // only decrypt a single packet using logincrypt and then disable it
                if (m_AlreadyRelayed && m_Encryption is LoginEncryption)
                {
                    uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2);

                    // Swap the seed
                    newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000);

                    // XOR it with the old seed
                    newSeed ^= m_Seed;

                    IClientEncryption newEncryption = new GameEncryption(newSeed);

                    // Game Encryption comes first
                    newEncryption.clientDecrypt(ref buffer, length);

                    // The login encryption is still used for this one packet
                    m_Encryption.clientDecrypt(ref buffer, length);

                    // Swap the encryption schemes
                    m_Encryption = newEncryption;
                    m_Seed       = newSeed;

                    return;
                }

                m_Encryption.clientDecrypt(ref buffer, length);
                return;
            }

            // If the client did not connect on the game server port,
            // it's not our business to handle encryption for it
            if (((IPEndPoint)from.Socket.LocalEndPoint).Port != Listener.Port)
            {
                m_Encryption = new NoEncryption();
                return;
            }

            // For simplicities sake, enqueue what we just received as long as we're not initialized
            m_Buffer.Enqueue(buffer, 0, length);
            // Clear the array
            length = 0;

            // If we didn't receive the seed yet, queue data until we can read the seed
            if (!m_Seeded)
            {
                // Now check if we have at least 4 bytes to get the seed
                if (m_Buffer.Length >= 4)
                {
                    byte[] m_Peek = new byte[m_Buffer.Length];
                    m_Buffer.Dequeue(m_Peek, 0, m_Buffer.Length);                       // Dequeue everything
                    m_Seed   = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
                    length = 4;
                }
                else
                {
                    return;
                }
            }

            // If the context isn't initialized yet, that means we haven't decided on an encryption method yet
            if (m_Encryption == null)
            {
                int packetLength = m_Buffer.Length;
                int packetOffset = length;
                m_Buffer.Dequeue(buffer, length, packetLength);                  // Dequeue everything
                length += packetLength;

                // This is special handling for the "special" UOG packet
                if (packetLength >= 3)
                {
                    if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF))
                    {
                        m_Encryption = new NoEncryption();
                        return;
                    }
                }

                // Check if the current buffer contains a valid login packet (62 byte + 4 byte header)
                // Please note that the client sends these in two chunks. One 4 byte and one 62 byte.
                if (packetLength == 62)
                {
                    // Check certain indices in the array to see if the given data is unencrypted
                    if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00)
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        LoginEncryption encryption = new LoginEncryption();
                        if (encryption.init(m_Seed, buffer, packetOffset, packetLength))
                        {
                            Console.WriteLine("Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name);
                            m_Encryption = encryption;

                            byte[] packet = new byte[packetLength];
                            Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                            encryption.clientDecrypt(ref packet, packet.Length);
                            Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                        }
                        else
                        {
                            Console.WriteLine("Detected an unknown client.");
                        }
                    }
                }
                else if (packetLength == 65)
                {
                    // If its unencrypted, use the NoEncryption class
                    if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF))
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        // If it's not an unencrypted packet, simply assume it's encrypted with the seed
                        m_Encryption = new GameEncryption(m_Seed);

                        byte[] packet = new byte[packetLength];
                        Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                        m_Encryption.clientDecrypt(ref packet, packet.Length);
                        Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                    }
                }

                // If it's still not initialized, copy the data back to the queue and wait for more
                if (m_Encryption == null)
                {
                    m_Buffer.Enqueue(buffer, packetOffset, packetLength);
                    length -= packetLength;
                    return;
                }
            }
        }
        // Try to decrypt incoming data.
        public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length)
        {
            #region m_Encryption != null
            if (m_Encryption != null)
            {
                // If we're decrypting using LoginCrypt and we've already been relayed,
                // only decrypt a single packet using logincrypt and then disable it
                if (m_AlreadyRelayed && m_Encryption is LoginEncryption)
                {
                    uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2);

                    // Swap the seed
                    newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000);

                    // XOR it with the old seed
                    newSeed ^= m_Seed;

                    IClientEncryption newEncryption = new GameEncryption(newSeed);

                    // Game Encryption comes first
                    newEncryption.ClientDecrypt(ref buffer, length);

                    // The login encryption is still used for this one packet
                    m_Encryption.ClientDecrypt(ref buffer, length);

                    // Swap the encryption schemes
                    m_Encryption = newEncryption;
                    m_Seed       = newSeed;

                    return;
                }

                m_Encryption.ClientDecrypt(ref buffer, length);
                return;
            }
            #endregion

            #region Port Scan
            bool handle = false;

            for (int i = 0; i < Listener.EndPoints.Length; i++)
            {
                IPEndPoint ipep = Listener.EndPoints[i];

                if (((IPEndPoint)from.Socket.LocalEndPoint).Port == ipep.Port)
                {
                    handle = true;
                }
            }

            if (!handle)
            {
                m_Encryption = new NoEncryption();
                return;
            }
            #endregion

            #region !m_Seeded
            // For simplicities sake, enqueue what we just received as long as we're not initialized
            m_Buffer.Enqueue(buffer, 0, length);
            // Clear the array
            length = 0;

            if (!m_Seeded)
            {
                if ((m_Buffer.Length == 83 || m_Buffer.Length == 21) && (m_Buffer.GetPacketID() == 239))                       //New Client
                {
                    length = m_Buffer.Length;
                    byte[] m_Peek = new byte[21];
                    m_Buffer.Dequeue(m_Peek, 0, 21);

                    m_Seed   = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21);

                    // We need to wait the next packet
                    if (length == 21)
                    {
                        return;
                    }

                    length = 21;
                }
                else if (m_Buffer.Length >= 4)                   // Old Client
                {
                    byte[] m_Peek = new byte[4];
                    m_Buffer.Dequeue(m_Peek, 0, 4);

                    m_Seed   = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
                    m_Seeded = true;

                    Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4);
                    length = 4;
                }
                else
                {
                    //Console.WriteLine("Encryption: Failed - Invalid Client.");
                    return;
                }
            }
            #endregion

            // If the context isn't initialized yet, that means we haven't decided on an encryption method yet
            #region m_Encryption == null
            if (m_Encryption == null)
            {
                int packetLength = m_Buffer.Length;
                int packetOffset = length;
                m_Buffer.Dequeue(buffer, length, packetLength);                 // Dequeue everything
                length += packetLength;

                // This is special handling for the "special" UOG packet
                if (packetLength >= 3)
                {
                    if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF))
                    {
                        m_Encryption = new NoEncryption();
                        return;
                    }
                }

                // Check if the current buffer contains a valid login packet (62 byte + 4 byte header)
                // Please note that the client sends these in two chunks. One 4 byte and one 62 byte.
                if (packetLength == 62)
                {
                    // Check certain indices in the array to see if the given data is unencrypted
                    if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00)
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                            from.Dispose();
                            return;
                        }
                    }
                    else
                    {
                        LoginEncryption encryption = new LoginEncryption();
                        if (encryption.Initialize(m_Seed, buffer, packetOffset, packetLength, from))
                        {
                            Console.WriteLine("Client: {0}: Encrypted client detected, using keys for client v{1}.", from, encryption.Name);
                            m_Encryption = encryption;
                            byte[] packet = new byte[packetLength];
                            Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                            encryption.ClientDecrypt(ref packet, packet.Length);
                            Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                        }
                        else
                        {
                            Console.WriteLine("Client: Unknown client detected, disconnecting.");
                            from.Dispose();
                        }
                    }
                }
                else if (packetLength == 65)
                {
                    // If its unencrypted, use the NoEncryption class
                    if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF))
                    {
                        if (Configuration.AllowUnencryptedClients)
                        {
                            m_Encryption = new NoEncryption();
                        }
                        else
                        {
                            RejectNoEncryption(from);
                        }
                    }
                    else
                    {
                        // If it's not an unencrypted packet, simply assume it's encrypted with the seed
                        m_Encryption = new GameEncryption(m_Seed);

                        byte[] packet = new byte[packetLength];
                        Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength);
                        m_Encryption.ClientDecrypt(ref packet, packet.Length);
                        Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength);
                    }
                }

                // If it's still not initialized, copy the data back to the queue and wait for more
                if (m_Encryption == null)
                {
                    m_Buffer.Enqueue(buffer, packetOffset, packetLength);
                    length -= packetLength;
                    return;
                }
            }
            #endregion
        }