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:
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:
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:
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);
}
}
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/cookiebot/blob/573fec44219bdd2be337dcd06fd383ce0e586775/Cookie/FullSocket/FullSocket.cs#L267
https://github.com/yovanoc/cookiebot/blob/573fec44219bdd2be337dcd06fd383ce0e586775/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: