décrypter le ticket reçu du paquet 42

Inscrit
30 Juin 2018
Messages
12
Reactions
0
#1
Salut les gens,çà fait deux jours que je suis entrain de comprendre comment décrypter le ticket (liste des bytes ) du paquet 42 pour l'envoyer sous forme string dans le paquet suivant , mais je me suis bloquer . ma question si quelqu'un peux m'aider c'est comment je peux décrypter le ticket et merci .
 
Inscrit
13 Avril 2016
Messages
72
Reactions
0
#2
Salut, premièrement ça aurait été cool que tu nous dises quel message correspond à l'ID 42 :'(
Fin bref, le message en question est: SelectedServerDataMessage.
Il suffit de trouver la frame qui s'occupe de ce message dans les sources de Dofus.

Voici la frame en question:
com.ankamagames.dofus.logic.connection.frames.ServerSelectionFrame.
Il faut chercher la fonction process et on obtient:
Code:
public function process(msg:Message) : Boolean
      {
         var slmsg:ServersListMessage = null;
         var initFrame:Frame = null;
         var ssumsg:ServerStatusUpdateMessage = null;
         var serverHasBeenUpdated:Boolean = false;
         var ssaction:ServerSelectionAction = null;
         var ssdemsg:SelectedServerDataExtendedMessage = null;
         var ssdmsg:SelectedServerDataMessage = null;
         var escmsg:ExpectedSocketClosureMessage = null;
         var asaction:AcquaintanceSearchAction = null;
         var asmsg:AcquaintanceSearchMessage = null;
         var asemsg:AcquaintanceSearchErrorMessage = null;
         var reasonSearchError:String = null;
         var aslmsg:AcquaintanceServerListMessage = null;
         var ssrmsg:SelectedServerRefusedMessage = null;
         var error:* = null;
         var mslm:MigratedServerListMessage = null;
         var knownServer:GameServerInformations = null;
         var serverAlreadyInName:String = null;
         var serverSelectedName:String = null;
         var commonMod:Object = null;
         var server:* = undefined;
         var ssmsg:ServerSelectionMessage = null;
         var errorText:* = null;
         switch(true)
         {
            case msg is ServersListMessage:
               slmsg = msg as ServersListMessage;
               PlayerManager.getInstance().server = null;
               this._serversList = slmsg.servers;
               this._serversList.sort(serverDateSortFunction);
               this._alreadyConnectedToServerId = slmsg.alreadyConnectedToServerId;
               initFrame = Kernel.getWorker().getFrame(InitializationFrame);
               if(initFrame)
               {
                  Kernel.getWorker().removeFrame(initFrame);
               }
               if(!Berilia.getInstance().uiList["CharacterHeader"])
               {
                  KernelEventsManager.getInstance().processCallback(HookList.AuthenticationTicketAccepted);
               }
               this.broadcastServersListUpdate();
               return true;
            case msg is ServerStatusUpdateMessage:
               ssumsg = msg as ServerStatusUpdateMessage;
               serverHasBeenUpdated = false;
               for each(knownServer in this._serversList)
               {
                  if(ssumsg.server.id == knownServer.id)
                  {
                     knownServer.charactersCount = ssumsg.server.charactersCount;
                     knownServer.completion = ssumsg.server.completion;
                     knownServer.isSelectable = ssumsg.server.isSelectable;
                     knownServer.status = ssumsg.server.status;
                     serverHasBeenUpdated = true;
                  }
               }
               if(!serverHasBeenUpdated)
               {
                  this._serversList.push(ssumsg.server);
                  this._serversList.sort(serverDateSortFunction);
               }
               _log.info("Server " + ssumsg.server.id + " status changed to " + ssumsg.server.status + ".");
               this.broadcastServersListUpdate();
               return true;
            case msg is ServerSelectionAction:
               ssaction = msg as ServerSelectionAction;
               if(this._alreadyConnectedToServerId > 0 && ssaction.serverId != this._alreadyConnectedToServerId)
               {
                  this._serverSelectionAction = ssaction;
                  serverAlreadyInName = Server.getServerById(this._alreadyConnectedToServerId).name;
                  serverSelectedName = Server.getServerById(ssaction.serverId).name;
                  commonMod = UiModuleManager.getInstance().getModule("Ankama_Common").mainClass;
                  commonMod.openPopup(I18n.getUiText("ui.popup.warning"),I18n.getUiText("ui.server.alreadyInFightOnAnotherServer",[serverAlreadyInName,serverSelectedName]),[I18n.getUiText("ui.common.ok"),I18n.getUiText("ui.common.cancel")],[this.onValidServerSelection,this.onCancelServerSelection],this.onValidServerSelection,this.onCancelServerSelection);
                  return true;
               }
               GuestModeManager.getInstance().forceGuestMode = false;
               for each(server in this._serversList)
               {
                  if(server.id == ssaction.serverId)
                  {
                     if(server.status == ServerStatusEnum.ONLINE || server.status == ServerStatusEnum.NOJOIN)
                     {
                        ssmsg = new ServerSelectionMessage();
                        ssmsg.initServerSelectionMessage(ssaction.serverId);
                        ConnectionsHandler.getConnection().send(ssmsg);
                        KernelEventsManager.getInstance().processCallback(HookList.ServerConnectionStarted);
                     }
                     else
                     {
                        errorText = "Status";
                        switch(server.status)
                        {
                           case ServerStatusEnum.OFFLINE:
                              errorText = errorText + "Offline";
                              break;
                           case ServerStatusEnum.STARTING:
                              errorText = errorText + "Starting";
                              break;
                           case ServerStatusEnum.SAVING:
                              errorText = errorText + "Saving";
                              break;
                           case ServerStatusEnum.STOPING:
                              errorText = errorText + "Stoping";
                              break;
                           case ServerStatusEnum.FULL:
                              errorText = errorText + "Full";
                              break;
                           case ServerStatusEnum.STATUS_UNKNOWN:
                           default:
                              errorText = errorText + "Unknown";
                        }
                        KernelEventsManager.getInstance().processCallback(HookList.SelectedServerRefused,server.id,errorText,this.getSelectableServers());
                     }
                  }
               }
               return true;
            case msg is SelectedServerDataExtendedMessage:
               ssdemsg = msg as SelectedServerDataExtendedMessage;
               this._serversList = ssdemsg.servers;
               this._serversList.sort(serverDateSortFunction);
               this.broadcastServersListUpdate(true);
            case msg is SelectedServerDataMessage:
               ssdmsg = msg as SelectedServerDataMessage;
               ConnectionsHandler.connectionGonnaBeClosed(DisconnectionReasonEnum.SWITCHING_TO_GAME_SERVER);
               this._selectedServer = ssdmsg;
               AuthentificationManager.getInstance().gameServerTicket = AuthentificationManager.getInstance().decodeWithAES(ssdmsg.ticket).toString();
               PlayerManager.getInstance().server = Server.getServerById(ssdmsg.serverId);
               PlayerManager.getInstance().kisServerPort = 0;
               PlayerManager.getInstance().gameServerPort = ssdmsg.port;
               return true;
            case msg is ExpectedSocketClosureMessage:
               escmsg = msg as ExpectedSocketClosureMessage;
               if(escmsg.reason != DisconnectionReasonEnum.SWITCHING_TO_GAME_SERVER)
               {
                  this._worker.process(new WrongSocketClosureReasonMessage(DisconnectionReasonEnum.SWITCHING_TO_GAME_SERVER,escmsg.reason));
                  return true;
               }
               this._worker.addFrame(new GameServerApproachFrame());
               ConnectionsHandler.connectToGameServer(this._selectedServer.address,this._selectedServer.port);
               return true;
            case msg is AcquaintanceSearchAction:
               asaction = msg as AcquaintanceSearchAction;
               asmsg = new AcquaintanceSearchMessage();
               asmsg.initAcquaintanceSearchMessage(asaction.friendName);
               ConnectionsHandler.getConnection().send(asmsg);
               return true;
            case msg is AcquaintanceSearchErrorMessage:
               asemsg = msg as AcquaintanceSearchErrorMessage;
               switch(asemsg.reason)
               {
                  case 1:
                     reasonSearchError = "unavailable";
                     break;
                  case 2:
                     reasonSearchError = "no_result";
                     break;
                  case 3:
                     reasonSearchError = "flood";
                     break;
                  case 0:
                  default:
                     reasonSearchError = "unknown";
               }
               KernelEventsManager.getInstance().processCallback(HookList.AcquaintanceSearchError,reasonSearchError);
               return true;
            case msg is AcquaintanceServerListMessage:
               aslmsg = msg as AcquaintanceServerListMessage;
               KernelEventsManager.getInstance().processCallback(HookList.AcquaintanceServerList,aslmsg.servers);
               return true;
            case msg is SelectedServerRefusedMessage:
               ssrmsg = msg as SelectedServerRefusedMessage;
               this._serversList.forEach(this.getUpdateServerStatusFunction(ssrmsg.serverId,ssrmsg.serverStatus));
               this.broadcastServersListUpdate();
               switch(ssrmsg.error)
               {
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_DUE_TO_STATUS:
                     error = "Status";
                     switch(ssrmsg.serverStatus)
                     {
                        case ServerStatusEnum.OFFLINE:
                           error = error + "Offline";
                           break;
                        case ServerStatusEnum.STARTING:
                           error = error + "Starting";
                           break;
                        case ServerStatusEnum.NOJOIN:
                           error = error + "Nojoin";
                           break;
                        case ServerStatusEnum.SAVING:
                           error = error + "Saving";
                           break;
                        case ServerStatusEnum.STOPING:
                           error = error + "Stoping";
                           break;
                        case ServerStatusEnum.FULL:
                           error = error + "Full";
                           break;
                        case ServerStatusEnum.STATUS_UNKNOWN:
                        default:
                           error = error + "Unknown";
                     }
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_ACCOUNT_RESTRICTED:
                     error = "AccountRestricted";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_COMMUNITY_RESTRICTED:
                     error = "CommunityRestricted";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_LOCATION_RESTRICTED:
                     error = "LocationRestricted";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_SUBSCRIBERS_ONLY:
                     error = "SubscribersOnly";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_REGULAR_PLAYERS_ONLY:
                     error = "RegularPlayersOnly";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_MONOACCOUNT_CANNOT_VERIFY:
                     error = "MonoaccountCannotVerify";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_MONOACCOUNT_ONLY:
                     error = "MonoaccountOnly";
                     break;
                  case 9:
                     error = "ServerFull";
                     break;
                  case ServerConnectionErrorEnum.SERVER_CONNECTION_ERROR_NO_REASON:
                  default:
                     error = "NoReason";
               }
               KernelEventsManager.getInstance().processCallback(HookList.SelectedServerRefused,ssrmsg.serverId,error,this.getSelectableServers());
               return true;
            case msg is MigratedServerListMessage:
               mslm = msg as MigratedServerListMessage;
               KernelEventsManager.getInstance().processCallback(HookList.MigratedServerList,mslm.migratedServerIds);
               return true;
            default:
               return false;
         }
      }
Et regardant attentivement on a:
Code:
case msg is SelectedServerDataMessage:
               ssdmsg = msg as SelectedServerDataMessage;
               ConnectionsHandler.connectionGonnaBeClosed(DisconnectionReasonEnum.SWITCHING_TO_GAME_SERVER);
               this._selectedServer = ssdmsg;
               AuthentificationManager.getInstance().gameServerTicket = AuthentificationManager.getInstance().decodeWithAES(ssdmsg.ticket).toString();
               PlayerManager.getInstance().server = Server.getServerById(ssdmsg.serverId);
               PlayerManager.getInstance().kisServerPort = 0;
               PlayerManager.getInstance().gameServerPort = ssdmsg.port;
               return true;
On remarque donc que le ticket envoyé par ce message est chiffré avec AES.
La fonction decodeWithAES:
Code:
public function initAESKey() : void
      {
         this._AESKey = this.generateRandomAESKey();
      }
     
      public function decodeWithAES(byteArrayOrVector:*) : ByteArray
      {
         var i:int = 0;
         var aesCipher:ICipher = Crypto.getCipher("simple-aes256-cbc",this._AESKey,new NullPad());
         this._AESKey.position = 0;
         var result:ByteArray = new ByteArray();
         result.writeBytes(this._AESKey,0,16);
         if(byteArrayOrVector is Vector.<int> || byteArrayOrVector is Vector.<uint>)
         {
            for(i = 0; i < byteArrayOrVector.length; i++)
            {
               result.writeByte(byteArrayOrVector[i]);
            }
         }
         else if(byteArrayOrVector is ByteArray)
         {
            result.writeBytes(byteArrayOrVector as ByteArray);
         }
         else
         {
            throw new ArgumentError("Argument must be a bytearray or a vector of int/uint");
         }
         aesCipher.decrypt(result);
         return result;
      }
Je trouve ce code très bizarre alors j'ai été regardé les sources de Cookie bot et je vois ça:
https://github.com/yovanoc/cookiebo...0e586775/Cookie/FullSocket/FullSocket.cs#L267
https://github.com/yovanoc/cookiebo...6775/Cookie.API/Utils/Cryptography/AES.cs#L71

Ce que je trouve encore plus bizarre, à croire que ce ticket n'a pas besoin d'être déchiffré :vicieux:
 
Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#3
Je trouve ce code très bizarre alors j'ai été regardé les sources de Cookie bot et je vois ça:
https://github.com/yovanoc/cookiebo...0e586775/Cookie/FullSocket/FullSocket.cs#L267
https://github.com/yovanoc/cookiebo...6775/Cookie.API/Utils/Cryptography/AES.cs#L71

Ce que je trouve encore plus bizarre, à croire que ce ticket n'a pas besoin d'être déchiffré :vicieux:
Ça me paraît effectivement bizarre.
J'ai plutôt tendance a penser qu'il faut déchiffrer ce ticket avec la clé AES envoyé dans le credentials de l'IdentificationMessage (ID : 4).
 
Inscrit
30 Juin 2018
Messages
12
Reactions
0
#4
bonjour ,
merci pour pour ta réponse et je suis désolé pour ma réponse tardive . dans le code que tu m'as indiqué en github le ticket est bien déchiffré avant l’envoie avec algo de AES with no padding (ils ont bien utilise le clé AES ) . j'ai réussi à déchiffre le ticket avec cette méthode mais quand je l'envoi je ne reçois aucune réponse de la part du serveur (exactement le paquet 1), je ne sais pas le problème d'ou viens si tu veux je peux te montre mon code de déchiffrement il est simple et aussi une capture de wireshark .
 
Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#5
Le sujet étant résolu via une discussion en privé, je me permet de partager la solution dans cette discussion afin qu'une personne ayant le même problème puisse tomber dessus via une recherche.

Le problème venait du fait que le message AuthenticationTicketMessage (ID : 110) était envoyé au serveur d'authentification et non au serveur de jeu (L'IP de ce serveur est reçus dans le message SelectedServerDataExtendedMessage (ID : 6469)).

Voici la procédure qu'il faut suivre quand on a reçus le SelectedServerDataExtendedMessage :
  • Extraire le ticket, l'IP et le port du serveur de jeu du message.
  • Se connecter au serveur de jeu.
  • Déchiffrer le ticket avec la clé AES envoyé dans le credentials de l'IdentificationMessage (ID : 4).
  • Envoyé le ticket déchiffré au serveur de jeu via le message AuthenticationTicketMessage (ID : 110).
 
Inscrit
30 Juin 2018
Messages
12
Reactions
0
#6
Le sujet étant résolu via une discussion en privé, je me permet de partager la solution dans cette discussion afin qu'une personne ayant le même problème puisse tomber dessus via une recherche.

Le problème venait du fait que le message AuthenticationTicketMessage (ID : 110) était envoyé au serveur d'authentification et non au serveur de jeu (L'IP de ce serveur est reçus dans le message SelectedServerDataExtendedMessage (ID : 6469)).

Voici la procédure qu'il faut suivre quand on a reçus le SelectedServerDataExtendedMessage :
  • Extraire le ticket, l'IP et le port du serveur de jeu du message.
  • Se connecter au serveur de jeu.
  • Déchiffrer le ticket avec la clé AES envoyé dans le credentials de l'IdentificationMessage (ID : 4).
  • Envoyé le ticket déchiffré au serveur de jeu via le message AuthenticationTicketMessage (ID : 110).
merci j'ai oublie de mettre la solution , je m'excuse.
 
Haut Bas