Python Probleme de deserialisation

Inscrit
28 Avril 2019
Messages
9
Reactions
2
#1
Coucou les gens!

Je suis en train de travailler sur un MITM sur 2.0 et j'ai commence a definir les fonctions de serialization / deserialization pour chaque message. J'arrive donc au message IdentificationMessage (5833) tranquillement mais apres plusieurs heures de debug, j'avoue etre perdu. Voici le fichier as de ce message:

https://pastebin.com/SirPq9hh

Comme on peut le voir, le message est constitue d'un boolean qui va servir a initialiser autoconnect, useCertificate et useLoginToken.
Ensuite on arrive sur une objet "Version" contenant 3 bytes (major, minor, code) suivis d'un int (build) puis un dernier byte (buildType).
Une chaine "lang".
Un vector<Int> credentials.
Un short serveur id.
Un varLong sessionOptionalSalt.
Et enfin un vector<Uint> failedAttempts.

Mon paquet ressemble au suivant:
5b260000000301140102390a0000000f000002667280029a61b853c158875197ad5900b46b1278e566c43cbdd3b0d72b1156c648241f78c579d496ce2b3b919286c0e3f5c44c3fb21ad46ab2fd243b33cb8a0c036a6ecc9b7956fdf531cd1ef7ccc5450520cce6a39b21032cd7a4870c098dceb404f4cf772338319c766264442373d266e81ec19b293d49c3db1cbe3301fe9d4eecb035993ee0502c64ba7ff65f10350763ace75df049e77925645c6cdaca999629a1b78bed05e54c8a53b9dc457fb42c2d7f73c433ca2ea5012fde9e82102fe582869c3af9b32efa94488fac900ffc47c80e42c8762e846e4736c7c9566e7758bb66ed66523b881a2fd84257187d127d3734f1c542a5a537899271bf5eb9a0d54a1c010000000000

5b26 nous donne 1011011001001 10 soit ID 5833 et len_type 2 (ce qui est correct).
Le 0000 0003 est le counter (c'est envoye depuis le client).
Taille du message: 0114 => 276. Voila pour le header.
01 est le premier boolean.
La version est encode sur 8 bytes: 02 39 0a 00 00 00 0f 00
La langue : 00026672 ("fr")

Et la, c'est le drame...
J'essai de lire mon vector<Int> mais j'ai pas l'impression que ca fonctionne... Je lis d'abord le varint encode sur 2 bytes: 8002 (256), puis je lis 256 bytes. Il ne me reste donc plus que 5 octets dans mon message cense encore contenir un short, un varlong et un vector<int>, soit minimum 12 octets (5 de moins que la taille total du message). Je n'ai pourtant fais que suivre pas a pas le fichier as correspondant:
Code:
public function deserializeAs_IdentificationMessage(input:ICustomDataInput) : void
{
     var _val3:int = 0;
     var _val9:uint = 0;
     this.deserializeByteBoxes(input);
     this.version = new Version();
     this.version.deserialize(input);
     this._langFunc(input);
     var _credentialsLen:uint = input.readVarInt();
     for(var _i3:uint = 0; _i3 < _credentialsLen; _i3++)
     {
        _val3 = input.readByte();
        this.credentials.push(_val3);
     }
     this._serverIdFunc(input);
     this._sessionOptionalSaltFunc(input);
     var _failedAttemptsLen:uint = input.readUnsignedShort();
     for(var _i9:uint = 0; _i9 < _failedAttemptsLen; _i9++)
     {
        _val9 = input.readVarUhShort();
        if(_val9 < 0)
        {
           throw new Error("Forbidden value (" + _val9 + ") on elements of failedAttempts.");
        }
        this.failedAttempts.push(_val9);
    }
}
J'arrive bel et bien a lang = fr, et le varint (8002), apres reverification en ligne fait bien 256. Je vois vraiment pas ou j'ai pu me tromper :/

Des idees ?
 
Dernière édition:
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#2
1606843065361.png

Pour information le failedAttemps est vide. Il est possible aussi de recevoir le packet en plusieurs fois, regarde comment est géré ton buffer pour qu'il soit identique avec celui de Dofus. (ton vector<int> de 256 est bon)
 
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#4
J'imagine que son code est en python mais en effet sur ce genre de problème, on a pas vraiment besoin de connaitre ton langage de programmation.
 
Inscrit
28 Avril 2019
Messages
9
Reactions
2
#5
Afficher la pièce jointe 507

Pour information le failedAttemps est vide. Il est possible aussi de recevoir le packet en plusieurs fois, regarde comment est géré ton buffer pour qu'il soit identique avec celui de Dofus. (ton vector<int> de 256 est bon)
Mon buffer est géré pour lire au moins 4 octets de header, recuperer la taille puis lire au moins de la taille du paquet. J'ai un buffer (apres avoir retirer le header la taille et le counter) de 276 octets ce qui correspond bel et bien a la taille donnée dans le header (01 14). Mon paquet est donc complet. Donc si ma taille de vector est 256,, il me reste: 0000000000. Je lis donc le server id (0000). Et apres il me reste 3 octets de valeur 00. Pourtant je dois lire un var long de 8 octets selon les sources. Est-ce que cette taille que me donne le header de 276 est vraiment fiable ?
 
Inscrit
28 Avril 2019
Messages
9
Reactions
2
#6
J'imagine que son code est en python mais en effet sur ce genre de problème, on a pas vraiment besoin de connaitre ton langage de programmation.
Voici ma fonction python :p

Code:
def deserialize(self):
    box = int.from_bytes(self.buffer_reader.read_byte(), "big")
    self.autoconnect["value"] = BooleanByteWrapper.get_flag(box, 0)
    self.useCertificate["value"] = BooleanByteWrapper.get_flag(box, 1)
    self.useLoginToken["value"] = BooleanByteWrapper.get_flag(box, 2)
    self.version["value"] = Version()
    self.version["value"].deserialize(self.buffer_reader)
    self.lang = self.buffer_reader.read_utf()
    credentials_length = self.buffer_reader.read_var_int()
    for i in range(credentials_length):
        self.credentials["value"].append(int.from_bytes(self.buffer_reader.read_byte(), "big"))
    self.serverId = self.buffer_reader.read_short()
    self.sessionOptionalSalt = self.buffer_reader.read_var_long()
    failed_attempts_length = self.buffer_reader.read_ushort()
    for i in range(failed_attempts_length):
        self.failedAttempts["value"].append(self.buffer_reader.read_read_var_uh_short())
Tout bête :p
 
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#7
Tu sais montrer ta classe buffer_reader ?
 
Inscrit
28 Avril 2019
Messages
9
Reactions
2
#8
Tu sais montrer ta classe buffer_reader ?
Belge ? :p

En gros j'ai mon protocolProcessor:
Code:
from module.protocol.processor.protocol_processor import ProtocolProcessor
from module.protocol.network.message_factory import MessageFactory


class D2Protocol(ProtocolProcessor):
    def __init__(self, client):
        ProtocolProcessor.__init__(self, client)

    def get_messages(self, buffer, from_client=False):
        messages = list()
        while len(buffer) and (message := MessageFactory.message(buffer, from_client=from_client)):
            messages.append(message)
            buffer = buffer[message.get_message_size():]
        return messages, buffer

    def from_client(self, data):
        messages, self._client_buffer = self.get_messages(self._client_buffer + data, from_client=True)
        if len(messages):
            for message in messages:
                print(message)

    def from_server(self, data):
        messages, self._server_buffer = self.get_messages(self._server_buffer + data)
        if len(messages):
            for message in messages:
                print(message)

    def send_server(self, message):
        self._client.write(message)
Il recupere les paquet du client et du server dans leur fonction dédiée.

Dans le from_client, on recupere le buffer envoyé par le client D2. On va appeler la fonction get_messages qui va lire le buffer et renvoyer 2 choses. Un buffer mis à jour apres la lecture, et une liste de messages. L'intérêt du buffer mis a jour, c'est si par exemple dans le buffer on a [message1][debutdemessage2] ou un message pas complet. On va return le buffer amputé du message crée (si message il y a) qui sera sauvegarder dans self._client_buffer, et au prochaine datas reçues, on envoi dans get_messages self._client_buffer (les restes du dernier buffer) concatené avec data qui est le nouveau buffer.

get_messages, lui, appelle une factory de Message qui va lire le buffer et retourner une liste de message. On boucle tant que le buffer a pas une taille nulle et tant que le message retourné n'est pas "None". Si tout est bon, on append dans la liste de message et on update le buffer pour repositionner le pointeur apres le message qui vient d'etre lu puis on reboucle.
Pour info:
Code:
def get_message_size(self):
    return 2 + self.len_type + self.length + (0 if self.count is None else 4)
Voila le message factory:
Code:
from module.io.bytes_reader import BytesReader
from module.protocol.network.messages_dict import MessagesDict


class MessageFactory:
    def message(buffer, from_client=False):
        buffer_reader = BytesReader(buffer)

        if len(buffer) < 8:  # If the current buffer is not even the size of a header
            print("Header too small")
            return None

        hi_header = buffer_reader.read(2)
        count = None if not from_client else buffer_reader.read_uint()
        id = int.from_bytes(hi_header, 'big') >> 2
        len_type = int.from_bytes(hi_header, 'big') & 3
        length = int.from_bytes(buffer_reader.read(len_type), 'big')

        if buffer_reader.get_current_buffer().nbytes < length:  # If the current buffer is small than the packet length.
            print("Packet too small")
            return None

        msg = buffer_reader.read(length)

        try:
            msg = MessagesDict[id](BytesReader(msg), len_type, length, count=count)
        except KeyError:
            print("ID not found: %d" % id)
            exit()

        msg.deserialize()
        return msg

    message = staticmethod(message)
Dans ce factory, il y a deux maniere de renvoyer "None" et d'interrompre la boucle de get_messages: Soit le paquet est plus petit qu'un header, soit le paquet apres lecture du header / taille / counter est plus petit que la taille totale du paquet presente dans le header.

Sinon, rien de particulier, on lit le header, puis la taille, puis le counter si besoin, puis le message en entier. On envoit ca dans un dictionnaire de class de message, on le deserialise puis on retourne le message.

Pour le ByteReader:
Code:
from io import BytesIO
import re
from struct import *
from module.io.constant import *


class BytesReader(BytesIO):
    def __init__(self, buffer):
        super().__init__(buffer)

    def get_current_buffer(self):
        return self.getbuffer()[self.tell():]

    def read_byte(self):
        return self.read(1)

    def read_char(self):
        return self.unpack('b')

    def read_uchar(self):
        return self.unpack('B')

    def read_boolean(self):
        return self.unpack('!?')

    def read_short(self):
        return self.unpack('!h', 2)

    def read_ushort(self):
        return self.unpack('!H', 2)

    def read_int(self):
        return self.unpack('!i', 4)

    def read_uint(self):
        return self.unpack('!I', 4)

    def read_int64(self):
        return self.unpack('!q', 8)

    def read_uint64(self):
        return self.unpack('!Q', 8)

    def read_var_long(self):
        return self.read_uint64()

    def read_float(self):
        return self.unpack('!f', 4)

    def read_double(self):
        return self.unpack('!d', 8)

    def read_utf(self):
        length = self.read_ushort()
        return self.unpack(str(length) + 's', length).decode("utf")

    def read_var_int(self):
        value = offset = size = 0
        while offset < INT_SIZE:
            b = self.read_byte()
            print("Byte: ", b.hex())
            size += 1
            if offset > 0:
                value += (int.from_bytes(b, 'big') & MASK_01111111) << offset
            else:
                value += int.from_bytes(b, 'big') & MASK_01111111
            offset += CHUNCK_BIT_SIZE
            if not (int.from_bytes(b, 'big') & MASK_10000000) == MASK_10000000:
                return value

    def read_var_short(self):
        value = offset = 0
        while offset < SHORT_SIZE:
            b = self.read_byte()
            has_next = (int.from_bytes(b, 'big') & MASK_10000000) == MASK_10000000;
            if offset > 0:
                value = value + ((int.from_bytes(b, 'big') & MASK_01111111) << offset)
            else:
                value = value + (int.from_bytes(b, 'big') & MASK_01111111)
            offset += CHUNCK_BIT_SIZE
            if not has_next:
                if value > SHORT_MAX_VALUE:
                    value = value - UNSIGNED_SHORT_MAX_VALUE
                return value

    def read_read_var_uh_short(self):
        return self.read_var_short()

    def unpack(self, fmt, length=1):
        return unpack(fmt, self.read(length))[0]
 
Dernière édition:
Inscrit
10 Mai 2015
Messages
357
Reactions
55
#9
Tu sais indiquer toutes les valeurs que tu obtiens si tu laisses tel quel ? Exemple, la valeur du ServerId SessionOptionnalSalt etc etc,
 
Inscrit
28 Avril 2019
Messages
9
Reactions
2
#10
Mes valeurs ressemblent a ca:
[{'version': {'type': 'Version', 'value': Major: 2, Minor: 57, Code: 10, Build: 15, buildType: 0}}, {'lang': 'fr'}, {'credentials': {'type': 'Vector.<int>', 'value': [112, 46, 249, 170, 122, 141, 160, 135, 86, 194, 163, 203, 184, 36, 149, 164, 232, 127, 47, 91, 85, 103, 239, 85, 225, 240, 124, 186, 52, 226, 24, 94, 243, 214, 170, 8, 113, 196, 137, 236, 151, 63, 225, 112, 164, 152, 223, 76, 110, 49, 81, 238, 184, 113, 252, 111, 57, 6, 93, 225, 90, 168, 36, 140, 83, 243, 247, 80, 192, 222, 198, 188, 230, 220, 116, 65, 103, 47, 125, 146, 143, 198, 219, 194, 129, 112, 73, 153, 237, 136, 184, 22, 134, 85, 201, 236, 234, 229, 194, 207, 105, 175, 199, 237, 251, 74, 184, 20, 99, 213, 41, 231, 158, 52, 48, 219, 223, 234, 205, 196, 97, 182, 214, 165, 122, 230, 73, 196, 14, 100, 192, 204, 90, 249, 76, 147, 221, 122, 104, 66, 29, 218, 52, 114, 153, 129, 121, 202, 57, 151, 75, 199, 43, 247, 204, 122, 30, 83, 209, 94, 146, 35, 188, 100, 57, 26, 218, 146, 218, 48, 244, 126, 151, 107, 59, 244, 208, 49, 134, 16, 77, 210, 18, 204, 204, 234, 130, 121, 63, 185, 181, 158, 46, 248, 26, 96, 70, 144, 95, 95, 198, 164, 99, 166, 172, 76, 247, 50, 100, 85, 94, 118, 37, 205, 84, 92, 177, 45, 120, 236, 139, 31, 177, 143, 12, 171, 95, 82, 191, 178, 94, 250, 174, 122, 50, 167, 109, 2, 154, 141, 170, 159, 120, 196, 227, 150, 138, 220, 54, 1, 245, 217, 236, 10, 173, 201]}}, {'serverId': 0}, {'autoconnect': {'type': 'Boolean', 'value': True}}, {'useCertificate': {'type': 'Boolean', 'value': False}}, {'useLoginToken': {'type': 'Boolean', 'value': False}}, {'sessionOptionalSalt': {'type': 'Number', 'value': ''}}, {'failedAttempts': {'type': 'Vector.<uint>', 'value': []}}]

A ce stade on est juste avant l'exception (avant de lire le sessionOptionalSalt sur 8 octets) et dans le buffer il reste 3 octets 00 00 00.

Buffer de base:
5b260000000301140102390a0000000f00000266728002702ef9aa7a8da08756c2a3cbb82495a4e87f2f5b5567ef55e1f07cba34e2185ef3d6aa0871c489ec973fe170a498df4c6e3151eeb871fc6f39065de15aa8248c53f3f750c0dec6bce6dc7441672f7d928fc6dbc281704999ed88b8168655c9eceae5c2cf69afc7edfb4ab81463d529e79e3430dbdfeacdc461b6d6a57ae649c40e64c0cc5af94c93dd7a68421dda3472998179ca39974bc72bf7cc7a1e53d15e9223bc64391ada92da30f47e976b3bf4d03186104dd212ccccea82793fb9b59e2ef81a6046905f5fc6a463a6ac4cf73264555e7625cd545cb12d78ec8b1fb18f0cab5f52bfb25efaae7a32a76d029a8daa9f78c4e3968adc3601f5d9ec0aadc90000000000

Pour info revoila ma fonction:
Code:
def deserialize(self):
    box = int.from_bytes(self.buffer_reader.read_byte(), "big")
    self.autoconnect["value"] = BooleanByteWrapper.get_flag(box, 0)
    self.useCertificate["value"] = BooleanByteWrapper.get_flag(box, 1)
    self.useLoginToken["value"] = BooleanByteWrapper.get_flag(box, 2)
    self.version["value"] = Version()
    self.version["value"].deserialize(self.buffer_reader)
    self.lang = self.buffer_reader.read_utf()
    credentials_length = self.buffer_reader.read_var_int()
    for i in range(credentials_length):
        self.credentials["value"].append(int.from_bytes(self.buffer_reader.read_byte(), "big"))
    self.serverId = self.buffer_reader.read_short()
    self.sessionOptionalSalt = self.buffer_reader.read_var_long()
    failed_attempts_length = self.buffer_reader.read_ushort()
    for i in range(failed_attempts_length):
        self.failedAttempts["value"].append(self.buffer_reader.read_read_var_uh_short())
Donc on arrive a self.lang = self.buffer_reader.read_utf() qui renvoit "fr" donc jusque la on est bon. Le fichier as:
Code:
package com.ankamagames.dofus.network.messages.connection
{
   import com.ankamagames.dofus.network.types.version.Version;
   import com.ankamagames.jerakine.network.CustomDataWrapper;
   import com.ankamagames.jerakine.network.ICustomDataInput;
   import com.ankamagames.jerakine.network.ICustomDataOutput;
   import com.ankamagames.jerakine.network.INetworkMessage;
   import com.ankamagames.jerakine.network.NetworkMessage;
   import com.ankamagames.jerakine.network.utils.BooleanByteWrapper;
   import com.ankamagames.jerakine.network.utils.FuncTree;
   import flash.utils.ByteArray;
   
   public class IdentificationMessage extends NetworkMessage implements INetworkMessage
   {
      
      public static const protocolId:uint = 5833;
       
      
      private var _isInitialized:Boolean = false;
      
      public var version:Version;
      
      public var lang:String = "";
      
      public var credentials:Vector.<int>;
      
      public var serverId:int = 0;
      
      public var autoconnect:Boolean = false;
      
      public var useCertificate:Boolean = false;
      
      public var useLoginToken:Boolean = false;
      
      public var sessionOptionalSalt:Number = 0;
      
      public var failedAttempts:Vector.<uint>;
      
      private var _versiontree:FuncTree;
      
      private var _credentialstree:FuncTree;
      
      private var _failedAttemptstree:FuncTree;
      
      public function IdentificationMessage()
      {
         this.version = new Version();
         this.credentials = new Vector.<int>();
         this.failedAttempts = new Vector.<uint>();
         super();
      }
      
      override public function get isInitialized() : Boolean
      {
         return this._isInitialized;
      }
      
      override public function getMessageId() : uint
      {
         return 5833;
      }
      
      public function initIdentificationMessage(version:Version = null, lang:String = "", credentials:Vector.<int> = null, serverId:int = 0, autoconnect:Boolean = false, useCertificate:Boolean = false, useLoginToken:Boolean = false, sessionOptionalSalt:Number = 0, failedAttempts:Vector.<uint> = null) : IdentificationMessage
      {
         this.version = version;
         this.lang = lang;
         this.credentials = credentials;
         this.serverId = serverId;
         this.autoconnect = autoconnect;
         this.useCertificate = useCertificate;
         this.useLoginToken = useLoginToken;
         this.sessionOptionalSalt = sessionOptionalSalt;
         this.failedAttempts = failedAttempts;
         this._isInitialized = true;
         return this;
      }
      
      override public function reset() : void
      {
         this.version = new Version();
         this.credentials = new Vector.<int>();
         this.serverId = 0;
         this.autoconnect = false;
         this.useCertificate = false;
         this.useLoginToken = false;
         this.sessionOptionalSalt = 0;
         this.failedAttempts = new Vector.<uint>();
         this._isInitialized = false;
      }
      
      override public function pack(output:ICustomDataOutput) : void
      {
         var data:ByteArray = new ByteArray();
         this.serialize(new CustomDataWrapper(data));
         writePacket(output,this.getMessageId(),data);
      }
      
      override public function unpack(input:ICustomDataInput, length:uint) : void
      {
         this.deserialize(input);
      }
      
      override public function unpackAsync(input:ICustomDataInput, length:uint) : FuncTree
      {
         var tree:FuncTree = new FuncTree();
         tree.setRoot(input);
         this.deserializeAsync(tree);
         return tree;
      }
      
      public function serialize(output:ICustomDataOutput) : void
      {
         this.serializeAs_IdentificationMessage(output);
      }
      
      public function serializeAs_IdentificationMessage(output:ICustomDataOutput) : void
      {
         var _box0:uint = 0;
         _box0 = BooleanByteWrapper.setFlag(_box0,0,this.autoconnect);
         _box0 = BooleanByteWrapper.setFlag(_box0,1,this.useCertificate);
         _box0 = BooleanByteWrapper.setFlag(_box0,2,this.useLoginToken);
         output.writeByte(_box0);
         this.version.serializeAs_Version(output);
         output.writeUTF(this.lang);
         output.writeVarInt(this.credentials.length);
         for(var _i3:uint = 0; _i3 < this.credentials.length; _i3++)
         {
            output.writeByte(this.credentials[_i3]);
         }
         output.writeShort(this.serverId);
         if(this.sessionOptionalSalt < -9007199254740990 || this.sessionOptionalSalt > 9007199254740990)
         {
            throw new Error("Forbidden value (" + this.sessionOptionalSalt + ") on element sessionOptionalSalt.");
         }
         output.writeVarLong(this.sessionOptionalSalt);
         output.writeShort(this.failedAttempts.length);
         for(var _i9:uint = 0; _i9 < this.failedAttempts.length; _i9++)
         {
            if(this.failedAttempts[_i9] < 0)
            {
               throw new Error("Forbidden value (" + this.failedAttempts[_i9] + ") on element 9 (starting at 1) of failedAttempts.");
            }
            output.writeVarShort(this.failedAttempts[_i9]);
         }
      }
      
      public function deserialize(input:ICustomDataInput) : void
      {
         this.deserializeAs_IdentificationMessage(input);
      }
      
      public function deserializeAs_IdentificationMessage(input:ICustomDataInput) : void
      {
         var _val3:int = 0;
         var _val9:uint = 0;
         this.deserializeByteBoxes(input);
         this.version = new Version();
         this.version.deserialize(input);
         this._langFunc(input);
         var _credentialsLen:uint = input.readVarInt();
         for(var _i3:uint = 0; _i3 < _credentialsLen; _i3++)
         {
            _val3 = input.readByte();
            this.credentials.push(_val3);
         }
         this._serverIdFunc(input);
         this._sessionOptionalSaltFunc(input);
         var _failedAttemptsLen:uint = input.readUnsignedShort();
         for(var _i9:uint = 0; _i9 < _failedAttemptsLen; _i9++)
         {
            _val9 = input.readVarUhShort();
            if(_val9 < 0)
            {
               throw new Error("Forbidden value (" + _val9 + ") on elements of failedAttempts.");
            }
            this.failedAttempts.push(_val9);
         }
      }
      
      public function deserializeAsync(tree:FuncTree) : void
      {
         this.deserializeAsyncAs_IdentificationMessage(tree);
      }
      
      public function deserializeAsyncAs_IdentificationMessage(tree:FuncTree) : void
      {
         tree.addChild(this.deserializeByteBoxes);
         this._versiontree = tree.addChild(this._versiontreeFunc);
         tree.addChild(this._langFunc);
         this._credentialstree = tree.addChild(this._credentialstreeFunc);
         tree.addChild(this._serverIdFunc);
         tree.addChild(this._sessionOptionalSaltFunc);
         this._failedAttemptstree = tree.addChild(this._failedAttemptstreeFunc);
      }
      
      private function deserializeByteBoxes(input:ICustomDataInput) : void
      {
         var _box0:uint = input.readByte();
         this.autoconnect = BooleanByteWrapper.getFlag(_box0,0);
         this.useCertificate = BooleanByteWrapper.getFlag(_box0,1);
         this.useLoginToken = BooleanByteWrapper.getFlag(_box0,2);
      }
      
      private function _versiontreeFunc(input:ICustomDataInput) : void
      {
         this.version = new Version();
         this.version.deserializeAsync(this._versiontree);
      }
      
      private function _langFunc(input:ICustomDataInput) : void
      {
         this.lang = input.readUTF();
      }
      
      private function _credentialstreeFunc(input:ICustomDataInput) : void
      {
         var length:uint = input.readVarInt();
         for(var i:uint = 0; i < length; i++)
         {
            this._credentialstree.addChild(this._credentialsFunc);
         }
      }
      
      private function _credentialsFunc(input:ICustomDataInput) : void
      {
         var _val:int = input.readByte();
         this.credentials.push(_val);
      }
      
      private function _serverIdFunc(input:ICustomDataInput) : void
      {
         this.serverId = input.readShort();
      }
      
      private function _sessionOptionalSaltFunc(input:ICustomDataInput) : void
      {
         this.sessionOptionalSalt = input.readVarLong();
         if(this.sessionOptionalSalt < -9007199254740990 || this.sessionOptionalSalt > 9007199254740990)
         {
            throw new Error("Forbidden value (" + this.sessionOptionalSalt + ") on element of IdentificationMessage.sessionOptionalSalt.");
         }
      }
      
      private function _failedAttemptstreeFunc(input:ICustomDataInput) : void
      {
         var length:uint = input.readUnsignedShort();
         for(var i:uint = 0; i < length; i++)
         {
            this._failedAttemptstree.addChild(this._failedAttemptsFunc);
         }
      }
      
      private function _failedAttemptsFunc(input:ICustomDataInput) : void
      {
         var _val:uint = input.readVarUhShort();
         if(_val < 0)
         {
            throw new Error("Forbidden value (" + _val + ") on elements of failedAttempts.");
         }
         this.failedAttempts.push(_val);
      }
   }
}
 
Dernière édition:
Inscrit
28 Avril 2019
Messages
9
Reactions
2
#12
J'suis pas sur mais ta fonction pour lire un VarLong est fausse.
Essaye de copié/collé le VarLong de https://github.com/louisabraham/LaBot/blob/master/labot/data/binrw.py
( Il me semble que la taille du VarLong n'est pas toujours de 8 octets, et que ça peut être moins )
C'etait le probleme, en effet la fonction readInt64 n'est pas un simple readInt64, j'aurais du regarder plus loin j'etais juste débile x)
Code:
private function readInt64(input:IDataInput) : Int64
{
   var b:uint = 0;
   var result:Int64 = new Int64();
   var i:uint = 0;
   while(true)
   {
      b = input.readUnsignedByte();
      if(i == 28)
      {
         break;
      }
      if(b >= 128)
      {
         result.low = result.low | (b & 127) << i;
         i = i + 7;
         continue;
      }
      result.low = result.low | b << i;
      return result;
   }
   if(b >= 128)
   {
      b = b & 127;
      result.low = result.low | b << i;
      result.high = b >>> 4;
      i = 3;
      while(true)
      {
         b = input.readUnsignedByte();
         if(i < 32)
         {
            if(b >= 128)
            {
               result.high = result.high | (b & 127) << i;
            }
            else
            {
               break;
            }
         }
         i = i + 7;
      }
      result.high = result.high | b << i;
      return result;
   }
   result.low = result.low | b << i;
   result.high = b >>> 4;
   return result;
}
Tout beigne! Merci :)
 
Dernière édition:
Haut Bas