Bonjour,
J'ai repris la création de bots sur Dofus 2.0 il y a maintenant une semaine, et je fais face à ma première difficulté : le hash chiffré envoyé avec certains paquets.
Pour expliquer le problème à tout le monde :
- Certains paquets (comme ExchangePlayerRequestMessage par exemple) incluent un hash chiffré avec les données du paquets
- Ce hash est vérifié (apparemment pas systématiquement, mais de manière aléatoire) par le serveur de jeu
- S'il est incorrect, alors le serveur nous déconnecte (voire nous bannis ?)
En examinant le code de ExchangePlayerRequestMessage (par exemple), on peut voir que c'est la fonction stockée dans NetworkMessage.HASH_FUNCTION qui s'occupe de générer ce hash :
override public function pack(param1:ICustomDataOutput) : void
{
var _loc2_:ByteArray = new ByteArray();
this.serialize(new CustomDataWrapper(_loc2_));
if(HASH_FUNCTION != null)
{
HASH_FUNCTION(_loc2_);
}
writePacket(param1,this.getMessageId(),_loc2_);
}
Mais quelle est cette fonction, et comment est-elle assignée à NetworkMessage.HASH_FUNCTION ?
J'a
- À la connexion, le serveur envoie un RawDataMessage qui est en fait un fichier SWF
- Le client exécute ce fichier SWF
- En analysant le code décompilé du SWF, on se rend compte que HASH_FUNCTION est assigné de cette manière :
getDefinitionByName(§_a_-_---§.§_a_--_--§(-1820302786))["HASH_FUNCTION"] = this.addCryptedHash;
J'ai "nettoyé" la fonction addCryptedHash() et ça donne ceci :
public function addCryptedHash(packetBytes:ByteArray) : void
{
var authentificationManagerClass:Object = null;
var gameServerTicketBytes:ByteArray = null;
if(!this._hashKey)
{
gameServerTicketBytes = new ByteArray();
gameServerTicketBytes.writeUTF(authentificationManagerClass.getInstance().getGameServerTicket());
this._hashKey = HumanCheck.hash(gameServerTicketBytes);
}
var cryptedHash:ByteArray = new ByteArray();
cryptedHash.writeBytes(HumanCheck.hash(packetBytes));
cryptedHash.position = 0;
var padder:_SEIWGELDMLL = new _SEIWGELDMLL();
var cipher:_SEGGHWLLXDH = new _SEGGHWLLXDH(new _SEHLHWHWMOW(new _SOLLHGLEIG(this._hashKey), padder));
padder.setBlockSize(cipher.getBlockSize());
cipher.encrypt(cryptedHash);
packetBytes.position = packetBytes.length;
packetBytes.writeBytes(cryptedHash);
}
J'ai donc l'intention de recoder cette fonction dans mon MITM. Voyons les problèmes qui se posent :
- Obtenir le gameServerTicket : pas de problème, on le récupère dans le AuthenticationTicketMessage envoyé par le client
- Recoder HumanCheck.hash() : ça peut aller, la fonction n'est pas bien méchante
- Recoder les classes _SEIWGELDMLL, _SEGGHWLLXDH, _SEHLHWHWMOW et _SOLLHGLEIG : bon, là, ça commence à faire beaucoup...
D'où mes questions :
- Jusque-là, mon raisonnement est-il correct ? N'ai-je pas oublier quelque chose ?
- Est-ce que le code de ce RawDataMessage change fréquemment ?
- Est-ce que les classes ci-dessus ne sont pas en réalité des algorithmes connus, que je n'aie pas besoin de toutes les recoder ?
Merci à vous !