Ok, j'ai fouillé un peu plus le forum, je trouve pas ou ne comprends pas quand certains parle de Mitm + RDM (qui est pourtant mon cas).
Donc en résumant :
1) Un tableau de 32 bytes est généré aléatoirement, qui correspond à une valeur AESkey (bien avant la réception du RDM, donc je pense que le RNG n'est pas modifié à ce moment là)
private var _AESKey:ByteArray;
private function generateRandomAESKey() : ByteArray
{
var ba:ByteArray = new ByteArray();
for(var i:int = 0; i < AES_KEY_LENGTH; i++)
{
ba = Math.floor(Math.random() * 256);
}
return ba;
}
public function initAESKey() : void
{
this._AESKey = this.generateRandomAESKey();
}
2) Cette valeur AESKey, est envoyée via le champ credential à un moment (avec user, mdp, etc....) dans le message IdentificationMessage, et ce champ credential est chiffré avant envoie en RSA
case msg is HelloConnectMessage:
hcmsg = HelloConnectMessage(msg);
AuthentificationManager.getInstance().setPublicKey(hcmsg.key);
AuthentificationManager.getInstance().setSalt(hcmsg.salt);
AuthentificationManager.getInstance().initAESKey();
iMsg = AuthentificationManager.getInstance().getIdentificationMessage();
private function cipherRsa(login:String, pwd:String, certificate:TrustCertificate) : Vector.<int>
{
var baOut:ByteArray = null;
var debugOutput:ByteArray = null;
var n:int = 0;
var baIn:ByteArray = new ByteArray();
baIn.writeUTFBytes(this._salt);
baIn.writeBytes(this._AESKey);
if(certificate)
{
baIn.writeUnsignedInt(certificate.id);
baIn.writeUTFBytes(certificate.hash);
}
baIn.writeByte(login.length);
baIn.writeUTFBytes(login);
baIn.writeUTFBytes(pwd);
try
{
if(File.applicationDirectory.resolvePath("debug-login.txt") || File.applicationDirectory.resolvePath("debuglogin.txt"))
{
_log.debug("login with certificate");
debugOutput = new ByteArray();
baIn.position = 0;
debugOutput.position = 0;
debugOutput = RSA.publicEncrypt((new PUBLIC_KEY_V2() as ByteArray).readUTFBytes((new PUBLIC_KEY_V2() as ByteArray).length),baIn);
}
}
catch(e:Error)
{
_log.error("Erreur lors du log des informations de login " + e.getStackTrace());
}
baOut = RSA.publicEncrypt(this._publicKey,baIn);
var ret:Vector.<int> = new Vector.<int>();
baOut.position = 0;
var i:int = 0;
while(baOut.bytesAvailable != 0)
{
n = baOut.readByte();
ret = n;
i++;
}
return ret;
}
3) La valeur _AESKey est utilisé pour décoder le ticket du message reçu : SelectedServerDataMessage, pour être ensuite stocké dans le champ gameServerTicket de AuthentificationManager
ssdmsg = msg as SelectedServerDataMessage;
ConnectionsHandler.connectionGonnaBeClosed(DisconnectionReasonEnum.SWITCHING_TO_GAME_SERVER);
this._selectedServer = ssdmsg;
AuthentificationManager.getInstance().gameServerTicket = AuthentificationManager.getInstance().decodeWithAES(ssdmsg.ticket).toString();
4) Dans la fonction addCryptedMessage de HumanCheck (reçu du RawDataMessage), un champ _hashKey est généré à partir d'un hash du champ gameServerTicket de AuthentificationManager
Donc, j'ai effectivement dit que je cherchais à récupérer la valeur _AESKey, car pour de ce que je sais pour l'instant, c'est le seul moyen d'avoir le gameServerTicket de AuthentificationManager (en interceptant SelectedServerDataMessage via un sniffer et de déchiffrer le ticket), qui est véritablement l'information que je cherche.
Une recherche plain text dans mon ide préféré, et je ne trouve rien me permettant d'intercepter, à un moment cette information.
![img]()
Actuellement les pistes que j'envisage :
* Utiliser un dofusInvoker.swf patché au lancement de dofus, puis le remplacer immadiatement par celui d'origine, histoire de ne pas à avoir à gérer les messages modo CheckFileMessage, mais en revanche possible détection dans le future que le swf chargé en mémoire par le processus dofus.exe n'est pas le bon (c'est pas impossible on dirait, ffdec permet de le faire). Ce patch par exemple pourrait intégrer un nouveau message du protocole dofus (pas de nouvelle classe, juste un parsing à la main) et qui prend en entrée un ByteArray et qui retourne ce ByteArray avec son hash ajouté à la fin (j'appelle le HASH_FUNCTION en gros). Comme ça mon bot fabrique son paquet custom, l'envoi au client dofus pour hash, puis récupère le résultat et le renvoi au serveur.
* Enfin de compte j'en ai pas d'autre (à part retourner sur du clic)