Algo Lecture du HelloConnectMessage

Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#1
Bonjour tout le monde,

Je débute dans l'écriture d'un bot socket pour la dernière version de D2.

Je m'attaque donc à l'authentification.

Si j'ai bien compris le serveur nous envoie dans le message "HelloConnectMessage" une clé crypté qu'il faut décrypter avec la fameuse clé connus :
Code:
MIIBUzANBgkqhkiG9w0BAQEFAAOCAUAAMIIBOwKCATIAqpzRrvO3We7EMi9cWYqdfb3rbdinTay+hxQ6t3dOiJLY4NITxyeIuy97yZYOojOlXS2SuJ4cCHjCeLCQO1FwOz+nynQWcBWecz2QdbHD2Kz7mNLd2qtZyEDO76rd7LaDOxRvgs9DsH9sfnCuKLKbd725xTLc7wRfJzOH9v9rTTYVXssXe7JUpTx8nV8yKnTiq3WpzBeZT4C3ZCR18GBBCh3NmSTbze9i2KipgZnOwBvhskVlweuqZ1KNIKsQgipBFuyww68RGNYaAKofMVVio4amrGpCT5MM852jpHsgJJfOUHu6md1CnvdwDPbo/PKQUI0RLb0ezE5gsPmas39QBw+DiaibUkk1aCkBxTOFqpIbjfLM2/4qA6GPcWUJxP3vmGoeCTMBLNEiPfLqVm86QzUCAwEAAQ==
Une fois cette clé décryptée, elle donne une clé au format X509 qu'il faut convertir au format PEM.
Cette clef décryptée permettra de crypter la concaténation du nom de l'utilisateur avec le mot de passe et le salt.
Cela donne le credentials a envoyer dans l'IndentificationMessage.

Pour le moment je suis en train d'essayer de lire manuellement le paquet HelloConnectMessage, mais je rencontre un petit soucis pour lire la clé cryptée.

Je me suis beaucoup aidé du code officiel du jeu :
Code:
public function deserializeAs_HelloConnectMessage(param1:ICustomDataInput) : void
{ 
   var _loc4_:int = 0;
   this._saltFunc(param1);
   var _loc2_:uint = param1.readVarInt();
   var _loc3_:uint = 0;
   while(_loc3_ < _loc2_)
   {
      _loc4_ = param1.readByte();
      this.key.push(_loc4_);
      _loc3_++;
   }
}

Voici ce que j'ai commencé a faire (HelloConnectMessage parsé manuellement) :
Code:
// ID du paquet et nombre d'octets de la taille du paquet (id = 3, nombre d'octets de la taille = 2)
00 0E

// Taille du paquet (sans l'en-tête) = 341
01 55

// Taille du salt (32 octets) :
00 20

// Salt :
6A 62 77 75 70 69 38 30 40 67 4E 4E 75 4A 3D 3D 22 61 65 79 39 4B 25 76 6A 5E 48 51 48 48 29 42

// Octets a fournir à la fonction readVarInt (49 octets) pour obtenir la taille de la clef.
B1 02 7B DF

// Clé a décrypter ?
5C B1 33 C8 74 CF 2C 51 8F 4F A0 9B 8C 6B B0 D5 81 55 F5 50 F3 41 42 67 A1 EC 1F 3E 24 CB 03 49 46 E7 85 06 DE E0 C3 C4 7E A8 DE B7 16 19 FA 68 F6

// ???
89 30 0F AB 42 2E D0 E3 66 5F D2 C1 42 DB D1 7E 74 6A AD 97 88 E7 07 55 99 0D 21 40 F5 85 A9 C5 BE F7 81 96 4B 64 09 70 9B 4A 64 5D 29 5D 02 24 8F 54 61 9C 3A 91 B4 0D 9A AF A2 E7 1B 05 3A 5C 72 1F F9 83 C0 F8 6F 7F 48 37 5B C2 78 BA D3 E3 D4 1B 10 E9 79 95 E4 1D D8 5C E6 42 47 A8 33 A9 86 AC F0 5E 40 9A 9B 1F D6 5F 4C 62 1D 83 B5 B0 42 30 40 0B DA 2E BA D2 4D 7C 67 AD 72 6B E1 BB BA 73 19 29 9F DA F9 87 14 85 23 4F B1 EC 6B 6A DB 6A B9 C8 4C 93 2D BC EF F9 FC 33 DF 87 58 0A F1 E1 6F 30 84 9C 21 CE F1 38 EF 3A CF 72 B5 86 E8 15 96 17 D7 ED 96 D7 10 69 8E 9A 07 E3 1D 78 B0 E1 16 9F A4 67 37 BD C5 64 94 AB A3 58 AB 6F 90 0A DA 61 86 02 72 61 05 F1 CF 3D 11 E5 23 56 F3 0D 63 14 7C 3D FA C7 7D 93 E5 46 37 FA B3 E8 33 52 DD BD 9D 14 4F B8 66 7C 17 04 A6 BE
Voici mon code permettant de simuler readVarInt pour ce paquet :
C:
// gcc ./readVarInt.c -o ./readVarInt.out && ./readVarInt.out
#include <stdlib.h>
#include <stdio.h>

void main(void) {
  unsigned char datas[4];
  int i = 0;
  datas[0] = 0xb1;
  datas[1] = 0x02;
  datas[2] = 0x7b;
  datas[3] = 0xdf;

  int b = 0;
  int value = 0;
  int offset = 0;
  int hasNext = 0;
  while (offset < 32) {
    b = datas[i];
    ++i;
    hasNext = ((b & 128) == 127);
    if (offset > 0) {
      value = (value + ((b & 127) << offset));
    } else {
      value = (value + (b & 127));
    }
    if (!hasNext) {
      printf("taille=%d\n", value);
      return;
    }
  }
}
Ce code me retourne 49.

La clé a décrypter serait donc contenu dans les 49 prochains octets ?
Cela me paraît bizarre, j'ai dus me tromper quelque pars...

Si c'est bien 49 octets, a quoi correspondent les octets contenu dans le reste du message ?

Merci d'avance pour votre aide.
 
Dernière édition:
Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#2
Je viens de me rendre compte que j'ai fais une erreur dans mon code *-*, voici le code corrigé :

C:
// gcc ./readVarInt.c -o ./readVarInt.out && ./readVarInt.out
#include <stdlib.h>
#include <stdio.h>

void main(void) {
  unsigned char datas[2];
  int i = 0;
  datas[0] = 0xb1;
  datas[1] = 0x02;

  int b = 0;
  int value = 0;
  int offset = 0;
  int hasNext = 0;
  while (offset < 32) {
    b = datas[i];
    ++i;
    hasNext = ((b & 128) == 128) ? 1 : 0;
    if (offset > 0) {
      value = (value + ((b & 127) << offset));
    } else {
      value = (value + (b & 127));
    } 
    offset += 7;
    if (!hasNext) {
      printf("taille=%d\n", value);
      return;
    } 
  }
}
Maintenant, j'obtiens une taille de 305 octets.

Cela donne donc :

Code:
// ID du paquet et nombre d'octets de la taille du paquet (id = 3, nombre d'octets de la taille = 2)
00 0E

// Taille du paquet (sans l'en-tête) = 341
01 55

// Taille du salt (32 octets) :
00 20

// Salt :
6A 62 77 75 70 69 38 30 40 67 4E 4E 75 4A 3D 3D 22 61 65 79 39 4B 25 76 6A 5E 48 51 48 48 29 42

// Octets a fournir à la fonction readVarInt (305 octets) pour obtenir la taille de la clé.
B1 02

// La clé a décrypter qui fait 305 octets
7B DF 5C B1 33 C8 74 CF 2C 51 8F 4F A0 9B 8C 6B B0 D5 81 55 F5 50 F3 41 42 67 A1 EC 1F 3E 24 CB 03 49 46 E7 85 06 DE E0 C3 C4 7E A8 DE B7 16 19 FA 68 F6 89 30 0F AB 42 2E D0 E3 66 5F D2 C1 42 DB D1 7E 74 6A AD 97 88 E7 07 55 99 0D 21 40 F5 85 A9 C5 BE F7 81 96 4B 64 09 70 9B 4A 64 5D 29 5D 02 24 8F 54 61 9C 3A 91 B4 0D 9A AF A2 E7 1B 05 3A 5C 72 1F F9 83 C0 F8 6F 7F 48 37 5B C2 78 BA D3 E3 D4 1B 10 E9 79 95 E4 1D D8 5C E6 42 47 A8 33 A9 86 AC F0 5E 40 9A 9B 1F D6 5F 4C 62 1D 83 B5 B0 42 30 40 0B DA 2E BA D2 4D 7C 67 AD 72 6B E1 BB BA 73 19 29 9F DA F9 87 14 85 23 4F B1 EC 6B 6A DB 6A B9 C8 4C 93 2D BC EF F9 FC 33 DF 87 58 0A F1 E1 6F 30 84 9C 21 CE F1 38 EF 3A CF 72 B5 86 E8 15 96 17 D7 ED 96 D7 10 69 8E 9A 07 E3 1D 78 B0 E1 16 9F A4 67 37 BD C5 64 94 AB A3 58 AB 6F 90 0A DA 61 86 02 72 61 05 F1 CF 3D 11 E5 23 56 F3 0D 63 14 7C 3D FA C7 7D 93 E5 46 37 FA B3 E8 33 52 DD BD 9D 14 4F B8 66 7C 17 04 A6 BE
Je vais tenter de faire le décryptage de cette clé, je reviendrai vers vous si jamais j'ai un soucis. :)
 
Dernière édition:
Inscrit
18 Février 2015
Messages
228
Reactions
7
#3
Tu es motivé à vouloir faire ça en C, un grand bravo et continue comme ça ^^
 

DevChris

Membre Actif
Inscrit
12 Avril 2017
Messages
138
Reactions
24
#4
Motivé ou alors il ne sait pas tout ce qu'il devras faire encore après ^^ mais tout est possible continue comme ça ! :)
 
Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#5
Motivé ou alors il ne sait pas tout ce qu'il devras faire encore après ^^ mais tout est possible continue comme ça ! :)
Je ne compte pas développer un bot entièrement en C. :p
C'est un code qui m'a permis de faire l'équivalent du readVarInt rapidement.

Si je développe un bot, je le ferrai probablement en Java pour rester dans le paradigme objet et pour la portabilité. ^^

J'ai quelques questions :

Je suis parvenu a faire les étapes de ce topic (message de @Arth ) : https://cadernis.fr/index.php?threads/procédure-dauthentification-et-rsa.1704/#post-19189

J'arrive bien a avoir la clé publique en base 64, j'ajoute le header et le footer.
Et je crypte ensuite de cette façon :

Code:
openssl rsautl -encrypt -inkey publickey.pem -pubin -in credential.txt -out credential.bin
  • publickey.pem étant la clé que je reçois du serveur dans le HelloConnectMessage (Après avoir appliqué la signature avec la clé statique présente dans les sources du jeu).
  • credential.txt étant la chaîne contenant le salt, pseudo, et password :
    Code:
    <salt><size pseudo sur un octet><pseudo><password>
  • credential.bin : Le fichier credential.txt crypté.
Cela vous semble bon ?
Quand je tente d'envoyer cela au serveur, je reçois un paquet de type 20 avec comme raison : "WRONG_CREDENTIAL".

J'ai une autre question, voici un IdentificationMessage envoyé par le client :

Code:
// ID du paquet et nombre d'octets de la taille du paquet (id = 4, nombre d'octets de la taille = 2)
00 12

// Taille du paquet à 0 ??
00 00

00 16 01 17 00 02 2D 08 00 DC BC C3 00 00 01 01 00 02 66 72 80 02 92 03 56 D6 34 6C F3 51 5A FE 4B C3 4E 7E AA 1C D0 F8 96 C5 21 19 A1 39 34 10 17 E5 6B EF 21 19 37 E8 C3 1C 18 1B 7C 16 D5 5F 50 C3 CF 43 4A 62 91 43 54 13 78 08 80 65 6A 47 D2 59 FB E8 78 EF 94 2E 15 CA 3E CD 5D DF 82 41 F6 EE A2 FB D8 5D 87 73 AA 88 F9 C0 30 BD 40 DB 12 ED 48 9D C2 59 E3 23 80 A9 76 AE 51 00 87 7F 82 E1 1B F3 86 81 90 F0 D4 E4 49 8A F3 AF 8F A0 54 B7 F4 7C FC 61 40 B3 D3 23 51 00 B1 F8 9E 0D DB 7B D8 D5 F3 F2 84 30 04 0B 07 3A 41 47 BF 9D 63 11 AD F2 85 31 17 D1 C1 41 70 DF A4 72 07 BC EC F2 D1 E0 4D 06 E6 4A EB 64 AB 38 65 73 85 29 BC C9 04 EE 56 C4 32 71 28 2B C6 85 32 71 EE EA 3F 56 FC F8 C8 3B 98 5C 2E FC 0A 2F 65 96 2F A5 07 58 B9 2E C0 FA EE EF EE 2D E1 22 9C 0D D4 6C CF 03 CB 6C 2B 63 C4 76 05 68 1A 5B B2 6D C9 1D E5 EF 58 D0 C6 24 00 00 00 00 00
La taille total du paquet me paraît bizarre.

J'ai essayé de passer par le sniffer de @BlueDream (https://cadernis.fr/index.php?threads/amaknacore-sniffer-dofus-2-45-6-1.1334/) qui injecte une dll dans le client du jeu, afin de tenter de mieux comprendre, mais celui ci ne m'a trouvé aucun paquet (malgré les droits administrateur).

Si j'arrive a comprendre la génération de ce credential, je ferrai peut-être un tuto clair qui pourra servir à d'autres personnes qui passeront sur ce forum. (Je ne dois pas être le seul a avoir des difficultés sur cette partie ^^)

PS: La clé statique du jeu n'est pas celle que j'ai mis dans mon précédent poste, j'ai récupéré la nouvelle dans le client, il s'agit de celle ci :

Code:
-----BEGIN PUBLIC KEY-----
MIIBUzANBgkqhkiG9w0BAQEFAAOCAUAAMIIBOwKCATIAgucoka9J2PXcNdjcu6CuDmgteIMB+rih
2UZJIuSoNT/0J/lEKL/W4UYbDA4U/6TDS0dkMhOpDsSCIDpO1gPG6+6JfhADRfIJItyHZflyXNUj
WOBG4zuxc/L6wldgX24jKo+iCvlDTNUedE553lrfSU23Hwwzt3+doEfgkgAf0l4ZBez5Z/ldp9it
2NH6/2/7spHm0Hsvt/YPrJ+EK8ly5fdLk9cvB4QIQel9SQ3JE8UQrxOAx2wrivc6P0gXp5Q6bHQo
ad1aUp81Ox77l5e8KBJXHzYhdeXaM91wnHTZNhuWmFS3snUHRCBpjDBCkZZ+CxPnKMtm2qJIi57R
slALQVTykEZoAETKWpLBlSm92X/eXY2DdGf+a7vju9EigYbX0aXxQy2Ln2ZBWmUJyZE8B58CAwEA
AQ==
-----END PUBLIC KEY-----
 
Dernière édition:
Inscrit
29 Octobre 2016
Messages
65
Reactions
2
#6
Personnellement rien qu'après avoir vu ton message, je me suis dis, je vais arrêté de travailler sur un bot, quand j'ai pas compris la lecture des paquets, ça semble simple sur quelques exemples basiques, mais je pensais que les messages n'avait pas la taille à l'entrée, de cette façon je sais même pas comme on est sensé savoir combien on doit lire de tailles :X

Le faite que les tailles s'enchaîne ça me perd de fou ... Donc autant que je fasse rien et que j'évite de passer pour un assisté, par contre je t'ai envoyer un MP pour essayer de t'aider ^^ si ça t'aide, n'oublie pas de dire ici comment tu as résolut pour que les autres qui ont besoin d'aide sachent :D
 
Inscrit
3 Janvier 2017
Messages
32
Reactions
1
#7
Comme me l'a indiqué @IceRhal sur la ShoutBox, les données que je crypte avec la clé publique ne sont pas bonne.

En effet, il manque une clé AES qui doit obligatoirement avoir une taille de 32 octets (comme le salt).
Cette clé AES est généré aléatoirement par le client du jeu.

Voici donc ce qu'il faut crypter (a mettre dans le credential.txt) :

Code:
<salt (32 octets)><clé AES aléatoire (32 octets)><size pseudo sur un octet><pseudo><password>
J'aurais bien fais un tuto pour mettre ça au clair, mais je n'ai pas les droits pour écrire dans la section qui va bien.

En ce qui concerne la taille du IdentificationMessage, je n'avais pas pris en compte le sequence_id (https://cadernis.fr/index.php?threads/tuto-bot-socket-les-fondamentaux.491/page-2#post-21856).

Les octets 00 00 00 16 doivent donc correspondre a ce sequence_id, et le 01 17 à la taille.

0x0117 = 279
C'est donc la bonne taille.
 
Dernière édition:
Haut Bas