[Mitm] Je n'arrive pas à désérialiser le 42

Inscrit
30 Juin 2020
Messages
23
Reactions
12
#1
Bonjour,
Je rencontre un soucis dans la désérialisation du packet 42.

Voici ma fonction deserialize: https://www.pastiebin.com/5f01cf59b1e8b
Les données du packet:
D2 01 00 19 6D 65 72 6B 61 74 6F 72 2E 61 6E 6B 61 6D 61 2D 67 61 6D 65 73 2E 63 6F 6D 00 02 B3 2B BB 03 01 20 74 69 B6 A8 5E BD 10 8E 66 9D 48 D4 9A 99 C2 FC 20 E3 BA 86 56 79 66 8C 9D 77 29 36 2C 38 64 8F

L'erreur:
System.NullReferenceException : 'La référence d'objet n'est pas définie à une instance d'un objet.'

D2.Bot.Protocol.Messages.SelectedServerDataMessage.Ports.get retournée null.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#2
Tu devrais privilégier les listes aux tableaux, ne connaissant pas à l'avance le nombre de ports que le serveur t'envoie.
C#:
Ports = new List<int>();

for (int i = 0; i < PortsLen; i++)
{
    Port.Add((int)reader.ReadVarUhShort());
}
Idem pour les tickets.
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#3
Yes t'as raison j'arrive à le deserialiser maintenant merci !
Mais maintenant je rencontre un autre soucis, pour gérer le 42 je fait ça:

C#:
BigEndianReader reader = new BigEndianReader(msg.Data);
SelectedServerDataMessage ssdm = new SelectedServerDataMessage();
ssdm.Deserialize(reader);

var url = ssdm.Address;
Uri myUri = new Uri("http://" + url);
var ip = Dns.GetHostAddresses(myUri.Host)[0];

BigEndianWriter wr = new BigEndianWriter();

ssdm.Address = "127.0.0.1";
ssdm.Ports.Add(5555);

ssdm.PackOld(wr);
sender.Associated.Send(wr.Data);

RemoteClient.Stop();
LocalClient.Stop();

SwitchToGameServer(new Client(new IPEndPoint(ip, ssdm.Ports[0])));
Dans le SwitchToGameServer je connecte RemoteClient et je lui réassocie le client local.
RemoteClient recoi bien le packet 1 (ProtocolRequired) sauf que le client local directement après lui envoie le packet 182, et le client distant lui envoie 183 puis ça s'arrête là.
 
Dernière édition par un modérateur:

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#4
Ouf, utilise les balises code la prochaine fois s'il te plait.
-> https://cadernis.fr/index.php?threads/utilisation-des-balises-bb-codes.1532/

[code=csharp]Console.WriteLine("Hello Cadernis !");[/code]

Sinon tu dois bien fermer la connexion une fois le SelectedServerDataMessage envoyé au client de jeu.
Ensuite tu attends que celui-ci se reconnecte à ton serveur, pour pouvoir à nouveau servir de proxy.
Normalement si tu redirige correctement le 183, la connexion se poursuit.
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#5
Les balises.. désolé j'ai vraimment essayé de les mettre mais j'ai pas réussi, je pensais pas qu'il y avait un topic sur ça , ça explique pas mal de choses. ^^
Mais je me posais la question.. le client local je suis pas obliger de le fermer ? Seulement le client distant qui est en communication avec Ank@ma ?
Vu que dans ma procédure, j'écrit un nouvel SSDM, l'envoie au client, ferme la connexion du client distant, crée un nouveau client distant sur l'adresse du serveur, le client local sans besoin d'être éteint reçoit tout naturellement le SSDM puis s'y connecte.

Mais en faisant ça je reçoit uniquement le 1 du client distant, ce qui veut dire que le client local à partir de la fermeture du client distant n'est plus en communication avec personne, et ceux même si recrée un nouveau client distant attribué au même serveur mitm. Bref il doit y avoir une erreur quelque part, je vais revoir mon code, merci pour tes réponses en tout cas, ca ma bien aidé.
Bye, bye
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#6
Tu dois sauvegarder les IPs, Ports & Tickets du client qui souhaite transiter vers le serveur de jeu.
Une fois qu'il se connecte, tu lui envoi le HelloGameMessage manuellement et il te répond avec son ticket.
A partir du ticket, tu détermine l'IP / Port correspondant et enfin tu ouvres la connexion vers le serveur dofus,
puis tu rediriges le trafic entre les deux.
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#7
A partir du ticket ? c'est à dire ? en décryptant le ticket on obtiens une ip et un port ?
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#8
Rien à voir avec un quelconque chiffrement.
Dans le SelectedServerDataMessage, le serveur t'envoi port, ip et ticket.
Tu sauvegardes le tout dans une liste, et via le ticket, tu récupère l'ip et le port correspondant, simplement.
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#9
Je pige pas la fin de ta phrase "via le ticket, tu récupères l'ip et le port correspondant" , je comprend pas vu que je récupère déjà l'ip et le port en désérializant SelectedServer, pas besoin du ticket non ?
D'ailleurs j'envoie comme tu as dit HelloGameMessage manuellement, le client me répond avec son ticket puis après plus rien, il se connecte même pas au serveur ^^
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#10
Le client se déconnecte, puis se reconnecte sur ton serveur,
Tu ne sais pas à quel ip / port de jeu il est associé, ok ?
Donc tu lui envoi le HelloGameMessage,
Il te retourne son ticket, et donc via ce ticket tu retrouves IP / port du serveur de jeu auquel ton client est associé,
que tu as préalablement sauvegardé, durant sa phase d'authentification au serveur de login via le paquet SSDM.
Tu te connecte à cette ip / port et tu send le ticket et tu recommence à faire le proxy.
C'est clair ?
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#11
Déso.. je comprend toujours pas.
Suite au SelectedServerMessage modifié, j'envoie HelloGameMessage. Je reçois de la part du client : AuthentificationTicketMessage, avec effectivement son ticket mais le truc c'est que c'est du charabia, par exemple je reçois : e3a0e49d2f8f60aff0b240b5be2bf435. En quoi ce string peut m'apporter une IP et un Port ?

Mais bon si je résume bien la procédure ça se passe comme ça :
1. ServerSelection de la part du client
2. SelectedServerDataMessage de la part d'Ank@ma, on récupère l'adresse, et le port (Address: merkator.ankama-games.com Port: 5555 dans mon cas.)
3. On n'envoie pas SelectedServerDataMessage au client local, à la place on modifie l'adresse par : 127.0.0.1 et le port par 5555. On envoie le message modifié au client.
4. Juste après avoir envoyé SelectedServerDataMessage au client local, on envoie HelloGameMessage
5. On reçoit le fameux Ticket de AuthentificationTicketMessage, on le sauvegarde
6. On ferme la connexion du client distant connecté à Ank@ma, on ferme ensuite le client local
7. On crée un nouveau client distant avec l'IP et le Port qu'on a recu dans le SelectedServerDataMessage original, soit l'ip et le port du serveur Merkator.
8. Le client se reconnecte automatiquement à notre serveur MITM et donc établi une liaison avec notre nouveau client distant connecté à Merkator.

Sauf qu'évidemment rien ne se passe comme prévu, ou alors il y a quelque chose que je n'ai pas compris.
Comme tu l'as vu dans AuthentificationTicketMessage je reçois un string qui n'a aucun sens pour moi, c'est pour ça que j'ai parlé de chiffrement.

Désolé de forcer, mais bon cette phase de redirection vers le serveur de jeu est primordiale pour réaliser un MITM, et je pense que ce topic servira énormément aux nouveaux qui désirent réaliser un MITM. Et tout cela grâce à toi. ^^
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#12
T'es le seul à pas comprendre qu'il faut suvegarder les Ip / Port / Ticket du SSDM et que le ticket sert à identifier le client pour resortir ces mêmes infos sur le partie de jeu.
Je ne sais pas comment te l'expliquer autrement.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#13
-> Login
1) Tu recois le SSDM
2) Tu stoque l'ip, le port et le ticket dans une liste
3) Le client se déco

-> Game
4) Le client se co en local sur ton serveur
5) Tu lui send le HelloGameMessage
6) Tu récupère son ticket
7) Tu récupère l'ip et le port associé au ticket (cf étape 2)
8) Tu te connecte à l'ip et au port en question
9) Tu recois le HelloGameMessage
10) Tu envoi le ticket
11) Tu rediriges le traffic
 
Inscrit
30 Juin 2020
Messages
23
Reactions
12
#14
C'est bon j'ai résolu mon problème autrement ^^
Voici ma solution :
C#:
if (msg.MessageId == 42)
                {
                    BigEndianReader reader = new BigEndianReader(msg.Data);
                    SelectedServerDataMessage ssdm = new SelectedServerDataMessage();
                    ssdm.Deserialize(reader);

                    this.Address = ssdm.Address;
                    this.Port = ssdm.Ports[0];

                    ssdm.Address = "127.0.0.1";
                    ssdm.Ports.Clear();
                    ssdm.Ports.Add(5555);

                    BigEndianWriter wr = new BigEndianWriter();
                    ssdm.PackOld(wr);
                    sender.Associated.Send(wr.Data);

                    LocalClient.Stop();
                    RemoteClient.Stop();

                }
                else
                {
                    sender.Associated.Send(data);
                }

C#:
  private void Srv_ConnectionAccepted(Client sender)
        {
            LogUpdateServer("Un nouveau client s'est connecté.");

            this.LocalClient = sender;
            this.RemoteClient = new Client();

            if (Address != null)
            {
                string hostname =   Address;
                IPAddress[] addresslist = Dns.GetHostAddresses(hostname);

                this.GameServer = new Client();
                this.UpdateGameServer();
                this.GameServer.Start(IPAddress.Parse(addresslist[0].ToString()), 5555);
                Address = null;
            }
            else
            {
                this.UpdateClient();
                this.RemoteClient.Start(IPAddress.Parse("34.252.21.81"), 5555);
            }
        }
Si ça peu aider quelqu'un ^^
 
Haut Bas