Python IdentificationMessage et AESKey

Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#1
Bonjour à tous,

Cela faisait un petit moment que je n'étais pas passé sur le forum et j'ai récemment eu l'envie de me lancer une fois de plus dans le développement d'un bot socket pour D mais en Python cette fois.
Bref, aujourd'hui je me heurte au paquet IdentifiactionMessage, que j'ai traduis et que je dois maintenant envoyer au serveur du jeu.
En jetant un oeil au source du jeu je suis tombé sur cette partie :
Code:
case msg is HelloConnectMessage:
  hcmsg = HelloConnectMessage(msg);
  AuthentificationManager.getInstance().setPublicKey(hcmsg.key);
  AuthentificationManager.getInstance().setSalt(hcmsg.salt);
  AuthentificationManager.getInstance().initAESKey();
  iMsg = AuthentificationManager.getInstance().getIdentificationMessage();
  _log.info("Current version : " + iMsg.version.major + "." + iMsg.version.minor + "." + iMsg.version.release + "." + iMsg.version.revision + "." + iMsg.version.patch);
  dhf = Kernel.getWorker().getFrame(DisconnectionHandlerFrame) as DisconnectionHandlerFrame;
  time = Math.round(getTimer() / 1000);
  elapsedTimesSinceConnectionFail = new Vector.<uint>();
  failureTimes = StoreDataManager.getInstance().getData(Constants.DATASTORE_MODULE_DEBUG,"connection_fail_times");
  if(failureTimes)
  {
  i = 0;
  while(i < failureTimes.length)
  {
  elapsedSeconds = time - failureTimes[i];
  if(elapsedSeconds <= 3600)
  {
  elapsedTimesSinceConnectionFail[i] = elapsedSeconds;
  }
  i++;
  }
  dhf.resetConnectionAttempts();
  }
  iMsg.failedAttempts = elapsedTimesSinceConnectionFail;
  ConnectionsHandler.getConnection().send(iMsg);
  KernelEventsManager.getInstance().processCallback(HookList.ConnectionTimerStart);
  TimeManager.getInstance().reset();
  return true;
Cependant je bloque sur le AuthentificationManager et principalement sur l'initialisation de L'AESKey. Comment cela fonctionne-t-il ? Comment procéder pour générer aléatoirement cette clé ?

Cordialement,
Kangogoo
 
Inscrit
18 Février 2015
Messages
228
Reactions
7
#2
l'aesKey n'est juste qu'une suite de Lettre (je ne sais pas s'il y a des chiffres à verifier) qui te permetteras par la suite pour décrypter le Ticket quand le server te le demanderas
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#3
La aesKey est générée au HelloConnectMessage côté client, puis envoyé au serveur via le IdentificationMessage au niveau du RSA.

Le serveur crypte ensuite le ticket avec cette aesKey.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#4
Quelle est donc la procédure a suivre pour envoyer le IdentificationMessage au serveur ?
 
Inscrit
18 Février 2015
Messages
228
Reactions
7
#5
La aesKey est générée au HelloConnectMessage côté client, puis envoyé au serveur via le IdentificationMessage au niveau du RSA.

Le serveur crypte ensuite le ticket avec cette aesKey.
au tant pour moi x)
Quelle est donc la procédure a suivre pour envoyer le IdentificationMessage au serveur ?
en gros à la connexion le serveur envoi le protocolRequired au client pour voir si le protocol est bien à jour ensuite le il envoi directement après le HelloConnect

donc après que tu te soit connecté tu dois attendre que tu recois le HelloConnect pour pouvoir envoyer le IdentificationMessage avec les id de connexion et l'aesKey
 
Dernière édition par un modérateur:
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#6
Je reçois bien a la fois de le ProtocolRequired et le HelloConnectMessage, là n'est pas le soucis, il réside plutot dans la marche a suivre pour sérialiser correctement le IdentificationMessage que je dois transmettre au serveur ? Que dois-je faire des infos reçu dans le HelloConnectMessage et comment renvoyer mes identifiants de connexion au serveur de jeu.
 
Inscrit
18 Février 2015
Messages
228
Reactions
7
#7
Je reçois bien a la fois de le ProtocolRequired et le HelloConnectMessage, là n'est pas le soucis, il réside plutot dans la marche a suivre pour sérialiser correctement le IdentificationMessage que je dois transmettre au serveur ? Que dois-je faire des infos reçu dans le HelloConnectMessage et comment renvoyer mes identifiants de connexion au serveur de jeu.
la réponse a ta question se trouve dans le AuthentificationFrame et le AuthenticationManager dans le dofusinvoker, suis le même procéder que dans le case pour le HelloConnect
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#8
la réponse a ta question se trouve dans le AuthentificationFrame et le AuthenticationManager dans le dofusinvoker, suis le même procéder que dans le case pour le HelloConnect
C'est la que réside tout le problème, en effet lorsque je suis le même procéder je me heurte au AuthentificationManager et à la méthode generateRandomAESKey ainsi que cipherRsa qui contienne tout deux des instructions machines (ASM) lorsque je décompile les sources. Comment dois-je procéder pour générer ma clef AES de manière aléatoire ?
 
Inscrit
18 Février 2015
Messages
228
Reactions
7
#9
C'est la que réside tout le problème, en effet lorsque je suis le même procéder je me heurte au AuthentificationManager et à la méthode generateRandomAESKey ainsi que cipherRsa qui contienne tout deux des instructions machines (ASM) lorsque je décompile les sources. Comment dois-je procéder pour générer ma clef AES de manière aléatoire ?
pourquoi voudrais-tu décompiler les fonctions comme celle là tu as surement des fonctions qui permette de faire la même chose sur internet
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#10
Utilise AS3 Sorcerer pour mieux déobfusqué ces fonctions là.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#12
Utilise AS3 Sorcerer pour mieux déobfusqué ces fonctions là.
En effet AS3 Sorcerer deobfusque bien mieux que FFDec :D

Cependant je me heurte maintenant a cette ligne (AuthentificationManager : 160, fonction setPublicKey) que j'ai du mal à traduite :
Code:
var readKey:RSAKey = PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length));
Code:
  public function setPublicKey(param1:Vector.<int>) : void
  {
  var commonMod:Object = null;
  var publicKey:Vector.<int> = param1;
  var baSignedKey:ByteArray = new ByteArray();
  var i:int = 0;
  while(i < publicKey.length)
  {
  baSignedKey.writeByte(publicKey[i]);
  i++;
  }
  baSignedKey.position = 0;
  var key:ByteArray = new ByteArray();
  var readKey:RSAKey = PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length));
  try
  {
  readKey.verify(baSignedKey,key,baSignedKey.length);
  }
  catch(e:Error)
  {
  commonMod = UiModuleManager.getInstance().getModule("Ankama_Common").mainClass;
  commonMod.openPopup(I18n.getUiText("ui.common.error"),I18n.getUiText("ui.server.authentificationImpossible"),[I18n.getUiText("ui.common.ok")]);
  return;
  }
  this._publicKey = "-----BEGIN PUBLIC KEY-----\n" + Base64.encodeByteArray(key) + "-----END PUBLIC KEY-----";
  }
Comment puis-je récupérer la clef publique RSA ? Dois-je la créer/générer ? Ou je peux tout simplement créer une variable de type static avec une valeur de ce type ?
Code:
"MIIBUzANBgkqhkiG9w0BAQEFAAOCAUAAMIIBOwKCATIAq8EYkkGCUg86Bf2CHaM1z1Q2ahQgVXkx" +
        "49I0igwTVCIqG86jsgNb22na1DThZ+IP7DfyBszIecVSP8nwbYPbx6Z7dwq4pnMVx/lx5lyMZUO1" +
        "n/HGEkw1S06AlfXzSg58ci5DL9RJ9ZIa1oMDKtrZiNYA5C3L+7NSCVp/2H/yypWkDjzkFan65+TN" +
        "RExo/2O3+MytJtQ/BXVkbYD58+iiZegddNTNGvz8WlPz2cZvPQt4x1TN+KOgJRKZH5imNAxCtRg6" +
        "l1OLVxfwwUjKFgM4uAsto8vJv5DUFZQMO1Sh9gMpmzeMwXIF4fDD4O1TNiVmu3ABybt2Y4EdaQhs" +
        "/ponC0SNcWbrY0stYbX+Wpk9/Hcxmo3zoduf1ZAdGM01E1g3IjQMd0gOP4v1KQtBjoHim2MCAwEA" +
        "AQ==";
Si il est possible de déclarer de manière static la publique key, ou puis-je trouver ma public key ? (celle qui me sert d'exemple provient d'un autre sujet du forum)
 
Dernière édition:
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#13
Tu peux la déclarer en statique, tout le monde a la même et elle ne change que très rarement.
Elle est dans les données binaires du DofusInvoker.swf. Pas de bol, AS3 Sorcerer ne les gère pas. Mais si tu en utilises un autre, tu pourras les obtenir.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#14
Je suis sous OS X j'utilise donc FFDec mais je ne sais pas si c'est le meilleur à disposition.
Concernant le IdentificationMessage, comment dois-je procéder à la réception du HelloConnectMessage pour serialize le IdentificationMessage correctement.
J'ai traduis le paquet en python et ça me donne cela :
Python:
# coding: utf-8

from Dofus.Network.Messages import Message
from Dofus.Network.Types.Version.VersionExtended import VersionExtended
from Jerakine.Network.Utils.BooleanByteWrapper import BooleanByteWrapper

class IdentificationMessage(Message):

  m_version = VersionExtended()
  m_lang = ""
  m_credentials = []
  m_serverId = 0
  m_autoconnect = False
  m_useCertificate = False
  m_useLoginToken = False
  m_sessionOptionalSalt = 0
  m_failedAttempts = []

  def __init__(self):
self.m_protocolId = 4
  self.m_version = VersionExtended()
  self.m_credentials = []
  self.m_failedAttempts = []

  def initIdentificationMessage(param1, param2, param3, param4, param5, param6, param7, param8, param9):
  self.m_version = param1;
  self.m_lang = param2;
  self.m_credentials = param3;
  self.m_serverId = param4;
  self.m_autoconnect = param5;
  self.m_useCertificate = param6;
  self.m_useLoginToken = param7;
  self.m_sessionOptionalSalt = param8;
  self.m_failedAttempts = param9;
  return self

  def reset():
  self.m_version = VersionExtended();
  self.m_credentials = [];
  self.m_serverId = 0;
  self.m_autoconnect = False;
  self.m_useCertificate = False;
  self.m_useLoginToken = False;
  self.m_sessionOptionalSalt = 0;
  self.m_failedAttempts = [];

  def serialize(self, writer):
  _loc2_ = 0
  _loc2_ = BooleanByteWrapper.setFlag(_loc2_, 0, self.m_autoconnect)
  _loc2_ = BooleanByteWrapper.setFlag(_loc2_, 1, self.m_useCertificate)
  _loc2_ = BooleanByteWrapper.setFlag(_loc2_, 2, self.m_useLoginToken)
  writer.writeByte(_loc2_)
  self.m_version.serialize(writer)
  writer.writeUTF(self.m_lang)
  writer.writeVarInt(len(self.m_credentials))
  _loc3_ = 0
  while (_loc3_ < len(self.m_credentials)):
  writer.writeByte(self.m_credentials[_loc3_])
  _loc3_ += 1
  writer.writeShort(self.m_serverId)
  if (self.m_sessionOptionalSalt < -9007199254740990 || self.m_sessionOptionalSalt > 9007199254740990):
  Log.Error ("Forbidden value (%s) on element sessionOptionalSalt." %s (self.m_sessionOptionalSalt))
  writer.writeLong(self.m_sessionOptionalSalt)
  writer.writeShort(len(self.m_failedAttempts))
  _loc4_ = 0
  while (_loc4_ < len(self.m_failedAttempts)):
  if (self.m_failedAttempts[_loc4_] < 0):
  Log.Error ("Forbidden value (%s) on element 9 (starting at 1) of failedAttempts." %s (self.m_failedAttempts[_loc4_]))
  write.writeShort(self.m_failedAttempts[_loc_4])
  _loc4_ += 1
Et je procède comme suit pour traiter les paquets reçu :
Python:
# coding: utf-8

from InputOuput.BigEndianReader import BigEndianReader
from Utils.LogClass import Log
from Dofus.Network.MessageReceiver import MessageReceiver


class PacketReader():

  def __init__(self, protocolId, packetLength, packetContent):
  self.m_protocolId = protocolId
  self.m_packetContent = packetContent
  self.m_reader = BigEndianReader(self.m_packetContent)
  self.m_packetLength = packetLength

  def readPacketById(self):
  message = MessageReceiver().parse(self.m_reader, self.m_protocolId, self.m_packetLength)
  if message is not None: print (message.__dict__)
  if (message.protocolId == 3):
  self.handleHelloConnectMessage(message)

  def handleHelloConnectMessage(self, message):
  pass
Comme tu peux le voir je dois donc remplir la fonction handleHelloConnectMessage pour serialize le IdentificationMessage pour pouvoir l'envoyer au serveur et m'authentifier mais je ne sais qu'elle procédure suivre.
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#15
Récupère un clé officiel envoyé par le serveur Dofus officiel dans HelloConnectMessage, et sert toi en a chaque fois que tu envoi ton propre HelloConnectMessage.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#16
Pourquoi récupérer une clef officiel ? Je la récupère déjà avec le deserialize du HelloConnectMessage :
Le soucis qui se présente a moi maintenant c'est comment serialize le IdentificationMessage. En effet comme je l'ai expliquer dans le premier message, cela fais plusieurs année que je n'ai pas codé de bot pour D2, de ce fait mon dernier en date se connecter au serveur de jeu en cryptant le mot de passe en MD5, pour vous dire a quel point cela remonte, en suivant cette méthode (que j'ai retrouvé sur le forum)
Code:
                case 3:
                    int connectionType = reader.ReadByte();
                    string key = reader.ReadString();
                    Log("ConnectionType = " + connectionType + " - Key = " + key + "\r\n");

                    string mdp_hash = MD5(MD5(accountPasswdTextBox.Text) + key); // Hachage du mot de passe
                    DataWriter writer = new DataWriter();
                    writer.WriteByte(2);
                    writer.WriteByte(3);
                    writer.WriteByte(7);
                    writer.WriteShort(35100);
                    writer.WriteByte(0);
                    writer.WriteByte(0);
                    writer.WriteString(accountNameTextBox.Text);
                    writer.WriteString(mdp_hash);
                    writer.WriteShort(0);
                    writer.WriteBool(true);
                    _Socket.Send(writer.Pack(4));
                    break;
Quelle serait-donc la nouvelle procédure à suivre pour se connecter au serveur de jeu sur la version actuelle de D sachant que j'ai traduis le paquet IdentificationMessage et sa méthode serialize ?
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#17
Tout est dans l'AuthentificationManager et l'AuthentificationFrame.
 
Haut Bas