A remote interface to handle a connection to a default minecraft client
Inheritance: RemoteInterface
Beispiel #1
0
 public async Task ClientTest()
 {
     for (int i = ProtocolInformation.MinSupportedClientVersion;
          i <= ProtocolInformation.MaxSupportedClientVersion;
          i++)
     {
         var stream = new MemoryStream ();
         var client = new ClientRemoteInterface(
             new BigEndianStream(stream), i);
         foreach (Type item in client.EndPoint.GetPackets ())
         {
             stream = new MemoryStream ();
             client = new ClientRemoteInterface(
                 new BigEndianStream(stream), i);
             if (PacketEndPoint.IsPacketSupported(item, i) == true)
             {
                 try
                 {
                     var packet = Activator.CreateInstance(item) as Packet;
                     if (packet is HandshakeRequest) (packet as HandshakeRequest).ProtocolVersion = (byte) i;
                     await client.SendPacketAsync(packet);
                     stream.Seek(0, SeekOrigin.Begin);
                     client.EndPoint.Stream.Context = PacketContext.Server;
                     await client.ReadPacketAsync ();
                     Assert.AreEqual(stream.Position, stream.Length, item.Name);
                 }
                 catch (Exception ex)
                 {
                     Assert.Fail(item.ToString (), ex);
                 }
             }
         }
     }
 }
        private static async void WaitForClient(int port)
        {
            TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, port));
            try
            {
                listener.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not bind to the specific port" + Environment.NewLine + ex.ToString());
                Environment.Exit(1);
                return;
            }

            while (true)
            {
                bool error = false;
                Console.WriteLine("Waiting for a client to connect at " + listener.LocalEndpoint.ToString());
                var client = await listener.AcceptTcpClientAsync();

                Console.WriteLine("Client connected");

                using (ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Magenta))
                Console.WriteLine("Waiting for Handshake Request (0x02)");

                var clientRemoteInterface = new ClientRemoteInterface(
    new BigEndianStream(
        new FullyReadStream(
            client.GetStream())), 39);

                var packet = clientRemoteInterface.ReadPacket();

                if (packet is PlayerListPing)
                {
                    Console.WriteLine("Server list Ping (0xFE) received. answering...");
                    await clientRemoteInterface.SendPacketAsync(new DisconnectPacket { Reason = "Minecraft Client Debug Server§0§1" });
                    client.Close();
                    continue;
                }
                else if (packet is HandshakeRequest)
                {
                    var handshakePacket = packet as HandshakeRequest;
                    using (ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Green))
                    {
                        Console.WriteLine("<Handshake packet>");
                        error = error || !Test(" Username: "******"Username out of range");
                        Console.WriteLine(" Host: " + handshakePacket.Host);
                        error = error || !Test(" Protocol Version: " + handshakePacket.ProtocolVersion, handshakePacket.ProtocolVersion == 39, "Protocol Version missmatch");
                        Console.WriteLine("</Handshake packet>");
                    }

                    if (error)
                    {
                        await clientRemoteInterface.SendPacketAsync(new DisconnectPacket { Reason = "0x02 expected" });
                        client.Close();
                        continue;
                    }
                    byte[] randomBuffer = new byte[4];
                    new Random().NextBytes(randomBuffer);
                    var buffer = new byte[4];
                    new Random().NextBytes(buffer);
                    //buffer = MD5.Create().ComputeHash(buffer);
                    buffer[0] = 42;
                    var serverId = BitConverter.ToString(buffer).Replace("-", "").ToLower();

                    var encryptionRequest = new EncryptionKeyRequest
                    {
                        ServerId = serverId,
                        PublicKey = _keyPair.GetPublic(),
                        VerifyToken = randomBuffer
                    };

                    using (ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Yellow))
                    {
                        Console.WriteLine("<Handshake response packet>");
                        Console.WriteLine(" ServerId: " + serverId);
                        Console.WriteLine(" Public Key: " + BitConverter.ToString(_keyPair.GetPublic()).Replace("-", "").ToLower());
                        Console.WriteLine(" VerifyToken: " + BitConverter.ToString(randomBuffer).Replace("-", "").ToLower());
                        Console.WriteLine("</Handshake response packet>");
                    }

                    await clientRemoteInterface.SendPacketAsync(encryptionRequest);

                    using (ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Magenta))
                        Console.WriteLine("Waiting for 0xFC Encryption response packet");

                    packet = clientRemoteInterface.ReadPacket();

                    if (packet is EncryptionKeyResponse)
                    {
                        var encryptionKeyResponse = packet as EncryptionKeyResponse;
                        Console.WriteLine("<Encryption key response packet>");
                        Console.WriteLine(" Shared Key: " + FormatArray(encryptionKeyResponse.SharedKey.ToArray()));
                        Console.WriteLine(" Verify Token: " + FormatArray(encryptionKeyResponse.VerifyToken.ToArray()));
                        Console.WriteLine("</Encryption key response packet>");

                        Console.WriteLine("Decryption Verify Token");
                        var verification = Pdelvo.Minecraft.Network.ProtocolSecurity.RSADecrypt(encryptionKeyResponse.VerifyToken.ToArray(), _keyPair.GetPrivate(), true);
                        error = error || Test("Received Verify Token: " + FormatArray(verification),
                            verification.Length == randomBuffer.Length
                          && verification.Zip(randomBuffer, (a, b) => a == b).All(a => a), "Verification Token missmatch");


                        if (error)
                        {

                            using (ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Red))
                            {
                                Console.WriteLine("Verfiy Token was not encrypted correctly");
                                if (verification.Length == randomBuffer.Length
                          && verification.Zip(randomBuffer, (a, b) => a == b).All(a => a))
                                {
                                    Console.WriteLine("The provided verify token is the one sended to the server, which is not correct. the token must be encrypted using the rsa public key in the handshake packet.");
                                }
                            }
                            await clientRemoteInterface.SendPacketAsync(new DisconnectPacket { Reason = "Verify Token missmatch" });
                            client.Close();
                            continue;
                        }

                        Console.WriteLine("Decrypting aes key...");

                        byte[] encryptedKey = encryptionKeyResponse.SharedKey.ToArray();
                        var decrypt = Pdelvo.Minecraft.Network.ProtocolSecurity.RSADecrypt(encryptedKey, _keyPair.GetPrivate(), true);

                        //using(ConsoleHelpers.ChangeForegroundColor(ConsoleColor.Green))
                        //    Console.WriteLine("Received shared key: " + );
                    }
                    else
                    {
                        error = true;
                        Console.WriteLine("Invalid packet received. 0xFC expected. Packet was " + packet.ToString());
                        await clientRemoteInterface.SendPacketAsync(new DisconnectPacket { Reason = "0x02 expected" });
                        client.Close();
                        continue;
                    }

                }
                else
                {
                    error = true;
                    Console.WriteLine("Invalid packet received. 0x02 expected. Packet was " + packet.ToString());
                    await clientRemoteInterface.SendPacketAsync(new DisconnectPacket { Reason = "0x02 expected" });
                    client.Close();
                    continue;
                }
            }
        }
Beispiel #3
0
        public async Task TestPlayerPing()
        {
            var playerPing = new PlayerListPing ();
            var stream = new MemoryStream ();
            var oldServer = new ServerRemoteInterface(
                new BigEndianStream(stream), 46);

            oldServer.SendPacketAsync(playerPing);
            stream.Seek(0, SeekOrigin.Begin);
            var server = new ClientRemoteInterface(
                new BigEndianStream(stream), 0);

            Packet packet = server.ReadPacket ();

            Assert.IsInstanceOfType(packet, typeof (PlayerListPing));

            var p = packet as PlayerListPing;

            Assert.AreEqual(p.MagicByte, 0);

            stream = new MemoryStream ();
            var newServer = new ServerRemoteInterface(
                new BigEndianStream(stream), 47);

            newServer.SendPacketAsync(playerPing);
            stream.Seek(0, SeekOrigin.Begin);
            server = new ClientRemoteInterface(
                new BigEndianStream(stream), 0);

            packet = server.ReadPacket ();

            Assert.IsInstanceOfType(packet, typeof (PlayerListPing));

            p = packet as PlayerListPing;

            Assert.AreEqual(p.MagicByte, 1);
        }