Récupérer l'ID d'un personnage en jeu

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#1
Bonjour,

Pour envoyer un ExchangePlayerRequestMessage (message que le client envoie pour demander un échange), j'ai besoin de l'ID du joueur cible.

Voici le code de sérialization/désérialization du message en question :
JavaScript:
public function serializeAs_ExchangePlayerRequestMessage(param1:ICustomDataOutput) : void
      {
         super.serializeAs_ExchangeRequestMessage(param1);
         if(this.target < 0 || this.target > 9007199254740990)
         {
            throw new Error("Forbidden value (" + this.target + ") on element target.");
         }
         param1.writeVarLong(this.target);
      }

private function _targetFunc(param1:ICustomDataInput) : void
      {
         this.target = param1.readVarUhLong();
         if(this.target < 0 || this.target > 9007199254740990)
         {
            throw new Error("Forbidden value (" + this.target + ") on element of ExchangePlayerRequestMessage.target.");
         }
      }
L'ID est donc a priori un entier long non signé.

Cependant, je n'arrive pas à trouver comment récupérer cet ID : en effet, après avoir cherché l'ID manuellement avec Wireshark (ID de mon personnage cible récupéré préalablement durant la sélection du personnage), il semble qu'il ne soit jamais envoyé par le serveur. La première fois que je rencontre l'ID est lorsque le client l'envoie... ce qui n'est pas logique.

Le serveur envoie bien d'autres ID, comme le contextualId qui fait partie de GameContextActorInformations :
JavaScript:
public function serializeAs_GameContextActorInformations(param1:ICustomDataOutput) : void
      {
         if(this.contextualId < -9007199254740990 || this.contextualId > 9007199254740990)
         {
            throw new Error("Forbidden value (" + this.contextualId + ") on element contextualId.");
         }
         param1.writeDouble(this.contextualId);
         this.look.serializeAs_EntityLook(param1);
         param1.writeShort(this.disposition.getTypeId());
         this.disposition.serialize(param1);
      }
Mais comme vous pouvez le voir, il s'agit d'un type double et non d'un entier non signé...

Savez-vous comment récupérer cet ID ?

Merci !
 

zahid98

Membre Actif
Inscrit
13 Decembre 2014
Messages
352
Reactions
2
#2
Salut , pour envoyer une requête d’échange le joueur cible doit-être bien présent sur le carte , deux paquets sont envoyés donc par le serveur pour identifier chaque joueur de la carte , en effet :
  • MapComplementaryInformationsDataMessage : tu peux jeter un coup d’œil sur msg.actors (ou la fonction deseralize du message et tu vas comprendre) , tu as la dessus l'id et le nom de chaque joueur présent sur la carte .
  • GameRolePlayShowActorMessage : à chaque fois qu'un joueur arrive sur la carte , ce paquet doit être reçu par le client pour l'identifier .
et pour finalement répondre à ta question de nombre réel et entier non signé , un nombre réel peut être bien un entier non signé , après ça fait longtemps que je n'ai pas touché à Dofus Desktop , je vais rien dire à ce propos pour éviter les bêtises :3 .​
 
Inscrit
14 Mars 2015
Messages
68
Reactions
0
#3
MapComplementaryInformationsDataMessage : pour les client déjà présent dans la map ( lors que tu arrive sur la carte)
GameRolePlayShowActorMessage : pour les client arrive sur la map
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#4
Salut , pour envoyer une requête d’échange le joueur cible doit-être bien présent sur le carte , deux paquets sont envoyés donc par le serveur pour identifier chaque joueur de la carte , en effet :
  • MapComplementaryInformationsDataMessage : tu peux jeter un coup d’œil sur msg.actors (ou la fonction deseralize du message et tu vas comprendre) , tu as la dessus l'id et le nom de chaque joueur présent sur la carte .
  • GameRolePlayShowActorMessage : à chaque fois qu'un joueur arrive sur la carte , ce paquet doit être reçu par le client pour l'identifier .
et pour finalement répondre à ta question de nombre réel et entier non signé , un nombre réel peut être bien un entier non signé , après ça fait longtemps que je n'ai pas touché à Dofus Desktop , je vais rien dire à ce propos pour éviter les bêtises :3 .​
Mes deux joueurs sont bien présents sur la même carte.

Je m'excuse, mais je n'ai pas tout compris à ce que tu as dis...
  • Es-tu en train de dire que le contextualId est le même ID que celui que je dois envoyer dans le ExchangePlayerRequestMessage ?
  • Si ce n'est pas le cas, comment récupérer l'ID à envoyer dans le ExchangePlayerRequestMessage ?

J'ai regardé PlayedCharacterUpdatesFrame, en particulier cette partie :
JavaScript:
case msg is MapComplementaryInformationsDataMessage:
               mcidmsg = msg as MapComplementaryInformationsDataMessage;
               for each(grai in mcidmsg.actors)
               {
                  grpci = grai as GameRolePlayCharacterInformations;
                  if(grpci && grpci.contextualId == PlayedCharacterManager.getInstance().id)
                  {
                     ...
                     break;
                  }
               }
               return false;
Il semblerait que le contextualId (type double) soit comparé au id (type uint64)... mais moi, à aucun moment ces deux nombres sont égaux.
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#6
contextualId = id actor
D'accord. Corrige-moi si je me trompe : cet ID est donc bien différent de l'ID du joueur, ce n'est pas cet ID que je dois envoyer dans le ExchangePlayerRequestMessage ?

Du coup, j'en reviens toujours à la même question : comment obtenir l'ID que je dois envoyer dans le ExchangePlayerRequestMessage ?
 
Inscrit
14 Mars 2015
Messages
68
Reactions
0
#7
c'est le meme id que tu dois envoyer dans le exchange
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#8
c'est le meme id que tu dois envoyer dans le exchange
Quelqu'un pourrait-il confirmer cela ?

Après avoir analysé les paquets avec Wireshark, je ne retrouve l'ID que le client envoie dans le ExchangePlayerRequestMessage qu'une seule fois : dans le UpdateMapPlayersAgressableStatusMessage. Et ce message ne contient pas de contextualId de type double, mais un playerIds (tableau) de type uint.

Désolé, mais j'ai vraiment du mal à comprendre... surtout que le UpdateMapPlayersAgressableStatusMessage ne contient pas d'informations pour lier un playerId à un pseudo ou à un contextualId...

Au secours :'( !
 
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#11
Surement que je me suis trompé de personne.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#13
Je confirme ce que dit @librosang , Tu reçois d'abord des ids uniques à chaque joueur via le paquet 226, qui sont en double.
Et par la suite, le serveur se sert de cet UID en uinteger et/ou integer.

Donc pour envoyer le ExchangePlayerRequestMessage , il s'agit bien du même UID, même si le type n'est pas le même.
De toute façon il n'existe qu'un identificateur unique pour chaque personnage, tu ne peux pas te tromper.
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#14
Je confirme ce que dit @librosang , Tu reçois d'abord des ids uniques à chaque joueur via le paquet 226, qui sont en double.
Et par la suite, le serveur se sert de cet UID en uinteger et/ou integer.

Donc pour envoyer le ExchangePlayerRequestMessage , il s'agit bien du même UID, même si le type n'est pas le même.
De toute façon il n'existe qu'un identificateur unique pour chaque personnage, tu ne peux pas te tromper.
D'accord, merci de ta confirmation.

Mon bot ne reçoit pas de MapComplementaryInformationsDataMessage (226) car il ne change pas de map. Il ne reçoit que des GameRolePlayShowActorMessage (5632) quand quelqu'un arrive sur la map, mais apparemment ce n'est pas grave (corrigez-moi si je me trompe) puisqu'il s'agit du même ID (contextualId de type double) qu'il y a dans le 226.

Je reçois donc mon GameRolePlayShowActorMessage correctement. Là où je ne comprends plus, c'est que quand je fais des tests avec deux clients et Wireshark, l'ID (de type double) qui se trouve dans ce message n'est pas égal à l'ID envoyé par le client officiel dans le ExchangePlayerRequestMessage. En effet :
  • Au niveau binaire, ce ne sont pas les mêmes valeurs. Cela peut se comprendre car pour un même nombre X, la représentation binaire d'un double n'est pas la même qu'un entier, cela est normal.
  • Le nombre représenté par le double n'est pas égal non plus au nombre envoyé dans le ExchangePlayerRequestMessage.

Pour vous en convaincre, voici mon dump Wireshark :

===== SERVER : GameMapMovementMessage (951) =====
0000 0e dd 10 00 02 00 86 00 50 00 03 c0 d3 88 00 00
0010 00 00 00

keyMovements.length (ushort) = 00 02 = 2
keyMovements[0] (short) = 00 86 = 86
keyMovements[1] (short) = 00 50 = 50
forcedDirection = 00 03 = 3
actorId = c0 d3 88 00 00 00 00 00 = -20000


===== SERVER : GameRolePlayShowActorMessage (5632) =====
0000 58 01 56 00 24 42 61 85 10 40 01 80 00 01 00 06
0010 1e fc 0f cc 03 cd 03 ce 03 e2 09 00 05 01 ff ff
0020 ff 02 ff 00 00 03 ff ff ff 04 ff 00 00 05 ff 00
0030 00 00 01 78 00 00 00 3c 00 12 01 00 05 54 69 78
0040 69 6e 00 9d 00 08 00 00 00 00 06 c3 bc 4c 00 00
0050 00 42 61 85 10 40 02 40 00

informations.typeId (ushort) = 00 24 = 36 = GameRolePlayCharacterInformations
contextualId (double) = 42 61 85 10 40 01 80 00 = 601975029772.00000


===== SERVER : UpdateMapPlayersAgressableStatusMessage (6454) =====
0000 64 d9 0b 00 01 8c 80 88 c4 c2 11 00 01 00

playerIds.length (ushort) = 00 01 = 1
playerIds[0] (ulong) = 8c 80 88 c4 c2 11 = 2918895560029110412
enable.length (ushort) = 00 01 = 1
enable[0] (byte) = 0


===== SERVER : SetCharacterRestrictionsMessage (170) =====
0000 02 a9 0b 42 61 85 10 40 01 80 00 00 08 00

actorId (double) = 42 61 85 10 40 01 80 00 = 601975029772.00000
flag1 (byte) = 00
flag1 (byte) = 08
flag1 (byte) = 00


===== CLIENT : ExchangePlayerRequestMessage (5773) =====
0000 5a 35 37 01 8c 80 88 c4 c2 11 9e ce a7 fd d5 bd
0010 9a d5 e3 ab 3c 60 87 f5 9b 32 98 66 03 7f 76 9c
0020 ee e6 d5 aa 58 a2 c6 cd 38 10 0c a6 5d df cb da
0030 55 db 55 34 1e a0 28 90 a5 fc

exchangeType (byte) = 01 = 1 = PLAYER_TRADE
target (ulong) = 8c 80 88 c4 c2 11 = 2918895560029110412
sécurité du RDM = le reste

Comme vous pouvez le voir, l'ID de type double n'est pas égal à l'ID du joueur de type ulong, que ce soit en binaire ou en représentation décimale...

Pouvez-vous me dire où je me trompe ?
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#15
Le paquet ExchangePlayerRequestMessage est crypté en AES-256 comme de nombreux paquets d'actions pour qu'ils ne puissent pas être sniffé.
Pour savoir si le paquet est crypté, tu dois te référer à la fonction pack().

Code:
      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_);
      }
Les données, avant d'être envoyées passent par la méthode HASH_FUNCTION qui est initialisé à la réception du paquet RawDataMessage.
Pour plus d'infos, voir ce sujet -> https://cadernis.fr/index.php?threads/incompréhension-du-paquet.1820/#post-20264
Sinon tu n'es pas obligé de crypter toi aussi tes paquets en AES-256, de nombreux bots tournent très bien sans.
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#16
Le paquet ExchangePlayerRequestMessage est crypté en AES-256 comme de nombreux paquets d'actions pour qu'ils ne puissent pas être sniffé.
Pour savoir si le paquet est crypté, tu dois te référer à la fonction pack().

Code:
      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_);
      }
Les données, avant d'être envoyées passent par la méthode HASH_FUNCTION qui est initialisé à la réception du paquet RawDataMessage.
Pour plus d'infos, voir ce sujet -> https://cadernis.fr/index.php?threads/incompréhension-du-paquet.1820/#post-20264
Sinon tu n'es pas obligé de crypter toi aussi tes paquets en AES-256, de nombreux bots tournent très bien sans.
Sauf erreur de ma part, c'est un hash des données du message qui est chiffré, pas le contenu du message en lui-même (CF. : https://cadernis.fr/index.php?threads/recoder-addcryptedhash-hash_function.1855/).

D'ailleurs, dans mon dump posté ci-dessus, on voit bien qu'on repère l'ID du joueur en clair (8c 80 88 c4 c2 11) dans le ExchangePlayerRequestMessage. Cet ID est le même que celui dans le UpdateMapPlayersAgressableStatusMessage envoyé plus tôt, ça ne peut pas être une coïncidence.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#17
Oui c'est le même car le RawDataMessage ne change plus, donc la hashKey non plus.
Après je peux me tromper, si ça se trouve le hash est désactivé mais ce n'est pas un hash des données mais bien du contenu du message.
 

Geuwp

Contributeur
Inscrit
16 Janvier 2015
Messages
37
Reactions
1
#18
Oui c'est le même car le RawDataMessage ne change plus, donc la hashKey non plus.
Après je peux me tromper, si ça se trouve le hash est désactivé mais ce n'est pas un hash des données mais bien du contenu du message.
Admettons que le contenu du ExchangePlayerRequestMessage soit effectivement chiffré. En revanche, le contenu du UpdateMapPlayersAgressableStatusMessage n'est pas chiffré (tu peux vérifier le pack()), or on retrouve les mêmes 6 octets de données qui correspondent à l'ID : 8c 80 88 c4 c2 11.

De plus, si on regarde la fonction addCryptedHash(), on s'aperçoit qu'elle ne chiffre pas le contenu, mais que :
  1. Elle crée un hash du contenu du paquet (ligne 14 ci-dessous)
  2. Elle chiffre le hash (ligne 21 ci-dessous)
  3. Elle ajoute le hash chiffré à la fin du contenu du paquet (ligne 24 ci-dessous). Le contenu du paquet reste donc en clair.
JavaScript:
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);
}

Es-tu d'accord avec cela ?
 
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#19
Moi je suis entièrement d'accord avec toi sur le fait que le hash ne modifie en rien le contenu du packet, c'est juste que le hash chiffré s'ajoute à la fin du contenu du packet comme tu l'as dit. Donc, pour revenir à ton problème (on s'en écarte), comme l'a dit Alexandre, je peux t'assurer que les Ids du GameRolePlayShowActorMessage sont les mêmes que ceux que tu envoies lors de l'échange à un joueur. Je n'utilise pas Wireshark, mais si tu trouves pas les mêmes valeurs, c'est car tu ne lis pas comme les IOs le font. Enfin bref, si tu veux trouver un Id ce que tu peux faire c'est envoyer ce packet :

JavaScript:
    Public Sub envoi181(name As String)
        Dim details As New BasicWhoIsRequestMessage
        details.verbose = True
        details.search = name
        Send(details, Target.Server)
    End Sub
    Public Sub paq180(Data As Dofus.IO.CustomDataWrapper)
        Dim CSM As New BasicWhoIsMessage
        CSM.Deserialize(Data)
        _mitm.SetChat("Name : " & CSM.playerName & " ID : " & CSM.playerId, LogType.Sucess)
    End Sub
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#20
C'est bien cela, le hash a pas mal changé.
@Geuwp
 
Haut Bas