Bonjour à tous,
Vu que le sujet n'est pas encore évoqué et que je viens de passer mes soirées pendant une semaine à faire le matching des protos (j'avais sous-estimé cette partie à première vue), je me suis dis que ça serait un bon sujet pour ma première contribution au forum.
L'objectif est de trouver les équivalences entre le nom des messages en clair qui était dans la version Beta (que l'on trouve un peu de partout sur github) et les versions obfusqués du jeu actuellement.
J'ai décomposé ce travail en plusieurs étapes : création d'une signature par message, matching des signatures identiques et uniques, matching des messages qui ont des signatures identiques par position, modification des messages en clair manuellement.
Création d'une signature par message
C'est la partie la plus simple, j'isole les messages un par un, puis je supprime le nom des variables, je ne garde que le type et la value. Pour les enums je garde tout car les valeurs ne sont pas obfusqués. Je construit un tableau de matching qui va être rempli au fur et à mesure que je vais avancer. Et je remplace tout les types qui ne sont pas des types standard (int32, string, bool, etc..) par soit la valeur matché s'il est déjà dans le tableau, soit "unknown" si je ne sais pas encore à quoi correspond le type.
Je récupère aussi le namespace au début des fichiers non obfu et j'incrémente le namespace quand je descend dans les niveaux d'un message. Ca permet d'avoir le nom complet des messages lors du parsing.
Je converti tous ça en json, et applique un sha256 pour avoir un hash unique.
Je fais ça pour les messages obfu et non obfu pour avoir toutes les signatures, normalement les messages identiques ont forcément la même signature (sauf pour les messages modifiées par Ank@m@ depuis la beta, j'y reviendrait plus tard.
Matching des signatures identiques et uniques
Je vais commencer à trouver des signatures qui n'ont qu'une seule correspondance entre obfu et non obfu (surtout pour les enums c'est le plus simple vu qu'elles sont en clair), ce qui me permet d'alimenter mon tableau de matching et en regénérant mes signatures d'obtenir de plus en plus de signatures uniques. La première fois il identifie environ 150 messages uniques, puis 400 etc..
Une fois qu'un message est identifié, je parcours également les variables du messages pour confirmer également le matching des types spéciaux.
Matching par position
Avec cette technique on arrive également rapidement à un palier où l'on avance plus. Heureusement Ank@m@ nous a fait une autre fleur, bien que les types soient obfu, on retrouve les autres messages car quand ils sont dans un même fichier non obfu, ils ont souvent un nom très proche en obfu.

Donc j'ai ajouté un nouvel élément au matching : la position.
Pour les messages obfu je fais : position(lettre1)x262+position(lettre2)x26+position(lettre3)
Pour les messages non obfu je fais : position(fichier)x100+positionMessageDansFichier
Si un matching est déjà identifié dans un fichier, je prends les deux positions du message et je cherche de proche en proche parmi les matching potentiels des messages proches, quel matching est le plus proche en position.
Au début je me suis fait une petite interface pour afficher la liste des messages et sélectionner à la main les matching pour vérifier que l'hypothèse de la position marcherait bien.

Modification manuelle des messages
Une fois que c'est fait j'ai trouvé environ 1150 matchs, ils restent les autres messages où l'on ne peut pas être trop sûr, soit parce qu'ils sont pas nombreux dans un fichier et aucun du fichier n'a une signature très unique, soit parce que le message a été modifié dans les dernières version du jeu.
Par exemple le message .com.ankama.dofus.server.game.protocol.teleportation.TeleportDestination qui dans la beta était :
message TeleportDestination {
.com.ankama.dofus.server.game.protocol.teleportation.Teleporter type = 1;
int64 map_id = 2;
int32 subarea_id = 3;
int32 level = 4;
int32 cost = 5;
optional .com.ankama.dofus.server.game.protocol.teleportation.TeleportDestination.Anomaly anomaly = 6;
message Anomaly {
int32 bonus_pourcentage = 1;
int64 remaining_time = 2;
}
}
est devenu :
message hgc {
hfh egmd = 1;
int64 egme = 2;
int32 egmf = 3;
int32 egmg = 4;
int32 egmh = 5;
oneof egmj {
hga egmi = 6;
}
message hga {
int32 egly = 1;
int64 eglz = 2;
}
}
J'ai donc mis à jour à la main la définition en clair :
message TeleportDestination {
.com.ankama.dofus.server.game.protocol.teleportation.Teleporter type = 1;
int64 map_id = 2;
int32 subarea_id = 3;
int32 level = 4;
int32 cost = 5;
oneof anomaly {
.com.ankama.dofus.server.game.protocol.teleportation.TeleportDestination.Anomaly = 6;
}
message Anomaly {
int32 bonus_pourcentage = 1;
int64 remaining_time = 2;
}
}
Pour cette partie, je pense que plus on mettra à jour étape par étape au fur et à mesure des mise à jour, plus ça sera facile d'identifier les modifications.
Conclusion
Voila j'espère que c'est assez clair et que ça pourra servir. J'ai commencé le botting sur Dofus il y a plus de 10 ans maintenant, puis je m'y était remis pendant le confinement. Je m'amuse bien avec cette nouvelle version du jeu également.
Merci à tous ceux qui ont contribué sur le forum et le Discord et qui m'ont bien aidé également.
Je ne prétends pas avoir la meilleure solution, j'ai déjà des idées pour améliorer le matching actuel, mais j'ai envie de m'amuser avec un autre sujet maintenant. J'y reviendrai peut-être plus tard si le matching se complexifie avec les nouvelles versions.
Bonne journée et bon code.

