예제 #1
0
        public void SendToServer(OutMessage message)
        {
            if (message != serverOutMessage)
            {
                message.WriteInternalHead();
                Xtea.Encrypt(message, xteaKey);
                Adler.Generate(message, true);
                message.WriteHead();
            }

            lock (serverSocket)
            {
                serverSocket.Send(message.Buffer, 0, message.Size, SocketFlags.None);
            }
        }
예제 #2
0
        public void SendToClient(OutMessage message)
        {
            if (message != clientOutMessage)
            {
                message.WriteInternalHead();
                Xtea.Encrypt(message, xteaKey);
                Adler.Generate(message, true);
                message.WriteHead();
            }

            lock (clientSocket)
            {
                pendingSend++;
                clientSocket.Send(message.Buffer, 0, message.Size, SocketFlags.None);
                pendingSend--;
            }
        }
예제 #3
0
        private void ParseClientWorldMessage()
        {
#if DEBUG_PROXY
            Trace.WriteLine("[DEBUG] Proxy [ParseClientWorldMessage]");
#endif
            serverOutMessage.Reset();
            Array.Copy(clientInMessage.Buffer, serverOutMessage.Buffer, clientInMessage.Size);
            serverOutMessage.Size = clientInMessage.Size;

            clientInMessage.ReadPosition = 2;

            if (Adler.Generate(clientInMessage) != clientInMessage.ReadChecksum())
            {
                throw new Exception("Wrong checksum.");
            }

            Xtea.Decrypt(clientInMessage, xteaKey);
            clientInMessage.Size         = clientInMessage.ReadInternalHead() + 8;
            clientInMessage.ReadPosition = 8;

            client.ProtocolWorld.ParseClientMessage(clientInMessage);

            SendToServer(serverOutMessage);
        }
예제 #4
0
        private void ParseFirstClientMessage()
        {
#if DEBUG_PROXY
            Trace.WriteLine("[DEBUG] Proxy [ParseFirstClientMessage]");
#endif

            clientInMessage.ReadPosition = 2;
            clientInMessage.Encrypted    = false;

            if (Adler.Generate(clientInMessage) != clientInMessage.ReadUInt())
            {
                throw new Exception("Wrong checksum.");
            }

            byte protocolId = clientInMessage.ReadByte();

            if (protocolId == 0x01)             //Login
            {
                protocol = Protocol.Login;
                ushort clientType      = clientInMessage.ReadUShort();
                ushort protocolVersion = clientInMessage.ReadUShort();

                if (client.Version.Number >= ClientVersion.Version981.Number)
                {
                    uint clientVersion = clientInMessage.ReadUInt();
                }

                uint datSignature = clientInMessage.ReadUInt();
                uint sprSignature = clientInMessage.ReadUInt();
                uint picSignature = clientInMessage.ReadUInt();

                if (client.Version.Number >= ClientVersion.Version981.Number)
                {
                    byte clientPreviewState = clientInMessage.ReadByte();
                }

                Rsa.OpenTibiaDecrypt(clientInMessage);

                Array.Copy(clientInMessage.Buffer, serverOutMessage.Buffer, clientInMessage.Size);
                serverOutMessage.Size          = clientInMessage.Size;
                serverOutMessage.WritePosition = clientInMessage.ReadPosition - 1;                 //the first byte is zero

                xteaKey    = new uint[4];
                xteaKey[0] = clientInMessage.ReadUInt();
                xteaKey[1] = clientInMessage.ReadUInt();
                xteaKey[2] = clientInMessage.ReadUInt();
                xteaKey[3] = clientInMessage.ReadUInt();

                var acc  = clientInMessage.ReadString();                //account name
                var pass = clientInMessage.ReadString();                //password

                if (client.IsOpenTibiaServer)
                {
                    Rsa.OpenTibiaEncrypt(serverOutMessage);
                }
                else
                {
                    Rsa.RealTibiaEncrypt(serverOutMessage);
                }

                Adler.Generate(serverOutMessage, true);
                serverOutMessage.WriteHead();

                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                serverSocket.Connect(loginServers[0].Server, loginServers[0].Port);

                serverSocket.Send(serverOutMessage.Buffer, 0, serverOutMessage.Size, SocketFlags.None);

                serverInMessage.Reset();
                serverSocket.BeginReceive(serverInMessage.Buffer, 0, 2, SocketFlags.None, ServerReceiveCallback, null);
            }
            else if (protocolId == 0x0A)             //Game
            {
                protocol = Protocol.World;

                ushort clientType      = clientInMessage.ReadUShort();
                ushort protocolVersion = clientInMessage.ReadUShort();

                if (client.Version.Number >= ClientVersion.Version981.Number)
                {
                    uint clientVersion      = clientInMessage.ReadUInt();
                    byte clientPreviewState = clientInMessage.ReadByte();
                }

                Rsa.OpenTibiaDecrypt(clientInMessage);

                Array.Copy(clientInMessage.Buffer, serverOutMessage.Buffer, clientInMessage.Size);
                serverOutMessage.Size          = clientInMessage.Size;
                serverOutMessage.WritePosition = clientInMessage.ReadPosition - 1;                 //the first byte is zero

                xteaKey    = new uint[4];
                xteaKey[0] = clientInMessage.ReadUInt();
                xteaKey[1] = clientInMessage.ReadUInt();
                xteaKey[2] = clientInMessage.ReadUInt();
                xteaKey[3] = clientInMessage.ReadUInt();

                clientInMessage.ReadByte();

                var accountName   = clientInMessage.ReadString();
                var characterName = clientInMessage.ReadString();
                var password      = clientInMessage.ReadString();

                if (client.IsOpenTibiaServer)
                {
                    Rsa.OpenTibiaEncrypt(serverOutMessage);
                }
                else
                {
                    Rsa.RealTibiaEncrypt(serverOutMessage);
                }

                Adler.Generate(serverOutMessage, true);
                serverOutMessage.WriteHead();

                serverSocket.Send(serverOutMessage.Buffer, 0, serverOutMessage.Size, SocketFlags.None);
            }
            else
            {
                throw new Exception("Invalid protocol " + protocolId.ToString("X2"));
            }
        }
예제 #5
0
        private void ParseServerLoginMessage()
        {
#if DEBUG_PROXY
            Trace.WriteLine("[DEBUG] Proxy [ParseServerLoginMessage]");
#endif
            serverInMessage.ReadPosition = 2;

            if (Adler.Generate(serverInMessage) != serverInMessage.ReadChecksum())
            {
                throw new Exception("Wrong checksum.");
            }

            Xtea.Decrypt(serverInMessage, xteaKey);
            serverInMessage.Size         = serverInMessage.ReadInternalHead() + 8;
            serverInMessage.ReadPosition = 8;

            clientOutMessage.Reset();
            Array.Copy(serverInMessage.Buffer, clientOutMessage.Buffer, serverInMessage.Size);
            clientOutMessage.Size = serverInMessage.Size;

            while (serverInMessage.ReadPosition < serverInMessage.Size)
            {
                byte cmd = serverInMessage.ReadByte();

                switch (cmd)
                {
                case 0x0A:                         //Error message
                    var msg = serverInMessage.ReadString();
                    break;

                case 0x0B:                         //For your information
                    serverInMessage.ReadString();
                    break;

                case 0x14:                         //MOTD
                    serverInMessage.ReadString();
                    break;

                case 0x1E:                         //Patching exe/dat/spr messages
                case 0x1F:
                case 0x20:
                    //DisconnectClient(0x0A, "A new client is avalible, please download it first!");
                    break;

                case 0x28:                         //Select other login server
                    //selectedLoginServer = random.Next(0, loginServers.Length - 1);
                    break;

                case 0x64:     //character list
                    if (client.Version.Number <= ClientVersion.Version1011.Number)
                    {
                        int nChar = (int)serverInMessage.ReadByte();
                        charList = new CharacterLoginInfo[nChar];

                        for (int i = 0; i < nChar; i++)
                        {
                            charList[i].CharName  = serverInMessage.ReadString();
                            charList[i].WorldName = serverInMessage.ReadString();
                            clientOutMessage.WriteAt(new byte[] { 127, 0, 0, 1 }, serverInMessage.ReadPosition);
                            charList[i].WorldIP = serverInMessage.ReadUInt();
                            clientOutMessage.WriteAt(BitConverter.GetBytes((ushort)worldClientPort), serverInMessage.ReadPosition);
                            charList[i].WorldPort = serverInMessage.ReadUShort();

                            if (client.Version.Number >= ClientVersion.Version981.Number)
                            {
                                serverInMessage.ReadByte();     //isPreviewWorld
                            }
                        }

                        if (client.Version.Number >= ClientVersion.Version1011.Number)
                        {
                            serverInMessage.ReadUShort();     //PremiumTime
                        }
                    }
                    else if (client.Version.Number >= ClientVersion.Version1012.Number)
                    {
                        clientOutMessage.WritePosition = serverInMessage.ReadPosition;

                        byte nWorlds = serverInMessage.ReadByte();
                        clientOutMessage.WriteByte(nWorlds);
                        WorldLoginInfo[] worldList = new WorldLoginInfo[nWorlds];
                        for (byte i = 0; i < nWorlds; i++)
                        {
                            worldList[i].ID = serverInMessage.ReadByte();
                            clientOutMessage.WriteByte(worldList[i].ID);
                            worldList[i].Name = serverInMessage.ReadString();
                            clientOutMessage.WriteString(worldList[i].Name);
                            worldList[i].Hostname = serverInMessage.ReadString();
                            clientOutMessage.WriteString("127.0.0.1");
                            worldList[i].Port = serverInMessage.ReadUShort();
                            clientOutMessage.WriteUShort((ushort)worldClientPort);
                            worldList[i].IsPreviewWorld = serverInMessage.ReadBool();
                            clientOutMessage.WriteByte(Convert.ToByte(worldList[i].IsPreviewWorld));
                        }

                        byte nChars = serverInMessage.ReadByte();
                        clientOutMessage.WriteByte(nChars);
                        charList = new CharacterLoginInfo[nChars];
                        for (byte j = 0; j < nChars; j++)
                        {
                            byte WorldID = serverInMessage.ReadByte();
                            clientOutMessage.WriteByte(WorldID);
                            charList[j].CharName = serverInMessage.ReadString();
                            clientOutMessage.WriteString(charList[j].CharName);
                            charList[j].WorldName     = worldList[WorldID].Name;
                            charList[j].WorldIP       = BitConverter.ToUInt32(Dns.GetHostAddresses(worldList[WorldID].Hostname)[0].GetAddressBytes(), 0);
                            charList[j].WorldPort     = worldList[WorldID].Port;
                            charList[j].WorldIPString = worldList[WorldID].Hostname;
                        }

                        ushort PremiumTime = serverInMessage.ReadUShort();
                        clientOutMessage.WriteUShort(PremiumTime);

                        clientOutMessage.Size = clientOutMessage.WritePosition;
                    }
                    break;

                default:
                    break;
                }
            }

            clientOutMessage.WriteInternalHead();
            Xtea.Encrypt(clientOutMessage, xteaKey);
            Adler.Generate(clientOutMessage, true);
            clientOutMessage.WriteHead();

            SendToClient(clientOutMessage);
        }
예제 #6
0
        private void ParseServerLoginMessage()
        {
#if DEBUG_PROXY
            Trace.WriteLine("[DEBUG] Proxy [ParseServerLoginMessage]");
#endif
            serverInMessage.ReadPosition = 2;

            if (Adler.Generate(serverInMessage) != serverInMessage.ReadChecksum())
            {
                throw new Exception("Wrong checksum.");
            }

            Xtea.Decrypt(serverInMessage, xteaKey);
            serverInMessage.Size         = serverInMessage.ReadInternalHead() + 8;
            serverInMessage.ReadPosition = 8;

            clientOutMessage.Reset();
            Array.Copy(serverInMessage.Buffer, clientOutMessage.Buffer, serverInMessage.Size);
            clientOutMessage.Size = serverInMessage.Size;

            while (serverInMessage.ReadPosition < serverInMessage.Size)
            {
                byte cmd = serverInMessage.ReadByte();

                switch (cmd)
                {
                case 0x0A:                         //Error message
                    var msg = serverInMessage.ReadString();
                    break;

                case 0x0B:                         //For your information
                    serverInMessage.ReadString();
                    break;

                case 0x0C:     //token succes
                case 0x0D:     //token error
                    serverInMessage.ReadByte();
                    break;

                case 0x11:     //update
                    serverInMessage.ReadString();
                    break;

                case 0x14:                         //MOTD
                    serverInMessage.ReadString();
                    break;

                case 0x1E:                         //Patching exe/dat/spr messages
                case 0x1F:
                case 0x20:
                    //DisconnectClient(0x0A, "A new client is avalible, please download it first!");
                    break;

                case 0x28:                         //session key
                    serverInMessage.ReadString();
                    break;

                case 0x64:     //character list
                    if (client.Version.Number <= ClientVersion.Version1011.Number)
                    {
                        int nChar = (int)serverInMessage.ReadByte();
                        charList = new CharacterLoginInfo[nChar];

                        for (int i = 0; i < nChar; i++)
                        {
                            charList[i].CharName  = serverInMessage.ReadString();
                            charList[i].WorldName = serverInMessage.ReadString();
                            clientOutMessage.WriteAt(new byte[] { 127, 0, 0, 1 }, serverInMessage.ReadPosition);
                            charList[i].WorldIP = serverInMessage.ReadUInt();
                            clientOutMessage.WriteAt(BitConverter.GetBytes((ushort)worldClientPort), serverInMessage.ReadPosition);
                            charList[i].WorldPort = serverInMessage.ReadUShort();

                            if (client.Version.Number >= ClientVersion.Version981.Number)
                            {
                                serverInMessage.ReadByte();     //isPreviewWorld
                            }
                        }

                        if (client.Version.Number >= ClientVersion.Version1011.Number)
                        {
                            serverInMessage.ReadUShort();     //PremiumTime
                        }
                    }
                    else if (client.Version.Number >= ClientVersion.Version1012.Number)
                    {
                        clientOutMessage.WritePosition = serverInMessage.ReadPosition;

                        byte nWorlds = serverInMessage.ReadByte();
                        clientOutMessage.WriteByte(nWorlds);
                        WorldLoginInfo[] worldList = new WorldLoginInfo[nWorlds];
                        for (byte i = 0; i < nWorlds; i++)
                        {
                            worldList[i].ID = serverInMessage.ReadByte();
                            clientOutMessage.WriteByte(worldList[i].ID);
                            worldList[i].Name = serverInMessage.ReadString();
                            clientOutMessage.WriteString(worldList[i].Name);
                            worldList[i].Hostname = serverInMessage.ReadString();
                            clientOutMessage.WriteString("127.0.0.1");
                            worldList[i].Port = serverInMessage.ReadUShort();
                            clientOutMessage.WriteUShort((ushort)worldClientPort);
                            worldList[i].IsPreviewWorld = serverInMessage.ReadBool();
                            clientOutMessage.WriteByte(Convert.ToByte(worldList[i].IsPreviewWorld));
                        }

                        byte nChars = serverInMessage.ReadByte();
                        clientOutMessage.WriteByte(nChars);
                        charList = new CharacterLoginInfo[nChars];
                        for (byte j = 0; j < nChars; j++)
                        {
                            byte WorldID = serverInMessage.ReadByte();
                            clientOutMessage.WriteByte(WorldID);
                            charList[j].CharName = serverInMessage.ReadString();
                            clientOutMessage.WriteString(charList[j].CharName);
                            charList[j].WorldName     = worldList[WorldID].Name;
                            charList[j].WorldIP       = BitConverter.ToUInt32(Dns.GetHostAddresses(worldList[WorldID].Hostname)[0].GetAddressBytes(), 0);
                            charList[j].WorldPort     = worldList[WorldID].Port;
                            charList[j].WorldIPString = worldList[WorldID].Hostname;
                        }

                        /**
                         * Not very accurately named variables, but I'll settle for some pseudocode in case of futher implementations
                         *
                         * if version < 10.80:
                         *      ushort PremiumTime
                         * else if version < 10.82
                         *      bool isPremium
                         *      uint PremiumTime (In seconds from epoch - don't quote me on this :D)
                         * else if version >= 10.82
                         *      byte AccountStatus (0 = normal, 1 = frozen, 2 = suspended)
                         *      bool isPremium
                         *      uint PremiumTime
                         */

                        ushort PremiumTime = serverInMessage.ReadUShort();
                        clientOutMessage.WriteUShort(PremiumTime);

                        if (client.Version.Number >= ClientVersion.Version1090.Number) // From 10.80 - but haven't added 10.80 support.
                        {
                            uint PremiumSeconds = serverInMessage.ReadUInt();          // Not sure about this name.
                            clientOutMessage.WriteUInt(PremiumSeconds);
                        }

                        clientOutMessage.Size = clientOutMessage.WritePosition;
                    }
                    break;

                default:
                    break;
                }
            }

            clientOutMessage.WriteInternalHead();
            Xtea.Encrypt(clientOutMessage, xteaKey);
            Adler.Generate(clientOutMessage, true);
            clientOutMessage.WriteHead();

            SendToClient(clientOutMessage);
        }
예제 #7
0
        private void ParseServerLoginMessage()
        {
#if DEBUG_PROXY
            Trace.WriteLine("[DEBUG] Proxy [ParseServerLoginMessage]");
#endif
            serverInMessage.ReadPosition = 2;

            if (Adler.Generate(serverInMessage) != serverInMessage.ReadChecksum())
            {
                throw new Exception("Wrong checksum.");
            }

            Xtea.Decrypt(serverInMessage, xteaKey);
            serverInMessage.Size         = serverInMessage.ReadInternalHead() + 8;
            serverInMessage.ReadPosition = 8;

            clientOutMessage.Reset();
            Array.Copy(serverInMessage.Buffer, clientOutMessage.Buffer, serverInMessage.Size);
            clientOutMessage.Size = serverInMessage.Size;

            while (serverInMessage.ReadPosition < serverInMessage.Size)
            {
                byte cmd = serverInMessage.ReadByte();

                switch (cmd)
                {
                case 0x0A:                         //Error message
                    var msg = serverInMessage.ReadString();
                    break;

                case 0x0B:                         //For your information
                    serverInMessage.ReadString();
                    break;

                case 0x14:                         //MOTD
                    serverInMessage.ReadString();
                    break;

                case 0x1E:                         //Patching exe/dat/spr messages
                case 0x1F:
                case 0x20:
                    //DisconnectClient(0x0A, "A new client is avalible, please download it first!");
                    break;

                case 0x28:                         //Select other login server
                    //selectedLoginServer = random.Next(0, loginServers.Length - 1);
                    break;

                case 0x64:                         //character list
                    int nChar = (int)serverInMessage.ReadByte();
                    charList = new CharacterLoginInfo[nChar];

                    for (int i = 0; i < nChar; i++)
                    {
                        charList[i].CharName  = serverInMessage.ReadString();
                        charList[i].WorldName = serverInMessage.ReadString();
                        clientOutMessage.WriteAt(new byte[] { 127, 0, 0, 1 }, serverInMessage.ReadPosition);
                        charList[i].WorldIP = serverInMessage.ReadUInt();
                        clientOutMessage.WriteAt(BitConverter.GetBytes((ushort)worldClientPort), serverInMessage.ReadPosition);
                        charList[i].WorldPort = serverInMessage.ReadUShort();
                    }
                    break;

                default:
                    break;
                }
            }

            clientOutMessage.WriteInternalHead();
            Xtea.Encrypt(clientOutMessage, xteaKey);
            Adler.Generate(clientOutMessage, true);
            clientOutMessage.WriteHead();

            SendToClient(clientOutMessage);
        }