Récupération et réencodage de packet d'un serveur

Signaler
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010
-
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Tout d'abord bonjour à la communauté ! Donc j'explique ma venu ici.

En gros, je cherche à récupéré les paquet envoyer par mon serveur de jeu qui sont pour un certain client, la version 1.25 pour qu'un client 1.61 puisse les lire. Des gens qui on beaucoup bosser sur le sujet on mit l'objet de leur travaux sur un wiki:

http://www.serveur-aegir.com/techwiki/index.php?title=Accueil

Il explique comment lire les paquets envoyer par le serveur et quel type de cryptage est utilisé.
Je cherche donc à créé une sorte de proxy qui change les paquet d'un serveur 1.25 en paquet pour client 1.61.

Voila, je tient a préciser que mes connaissances en C sont très faible, je sais que se projet ne sera surement pas à ma porter, je sais juste programmer sous flash donc j'ai juste les bases de la programmation.

15 réponses

Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut,
Bon courage à toi, c'est du sacré boulot


Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Enfaite si on pourrai juste me dire comment récupéré et renvoyer des paquet pour le reste je me débrouillerai, je sais qu'il faut un port d'écoute mais par où commencer je ne vois pas.

Merci D'avance,
Cordialement.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Tu peux utiliser la bibliothèque winsowk pour les sockets (elle est inclue de base dans Windows). Elles fonctionnent comme sous Linux (en gros).


Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Ok merci de m'indiquer une piste ^^. Si quelqu'un d'autre possède des infos qu'il m'en fasse par .

Merci,
Cordialement.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
J'ai pas tout saisi le problème en fait, mais pour récupérer des infos d'un serveur en C sous Windows, tu as des libs haut niveau sans doute (que je ne connais pas) ou cette fameuse bibliothèque windosk.
Un code a été déposé sur ce même site il n'y a pas si longtemps : http://www.cppfrance.com/codes/ETRE-AVERTIS-LORS-NOUVEL-ARTICLE-SUR-BLOG-TYPE_51443.aspx


Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

J'arrive a récupéré les paquets voila le code:
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define TAILLETAMPON 1024
int main()
{
//On crée nos variables
SOCKET mon_socket;
SOCKADDR_IN sin;
int mtampon = 4;


//On initialise Winsock
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

//On défini nos paramètres
sin.sin_addr.s_addr = inet_addr("ip_serveur");
sin.sin_family = AF_INET;
sin.sin_port = htons(port_serveur);

//On crée le socket !
mon_socket = socket(AF_INET,SOCK_STREAM,0);
bind(mon_socket, (SOCKADDR *)&sin, sizeof(sin));

//On connecte notre socket
connect(mon_socket, (SOCKADDR *)&sin, sizeof(sin));

int i;
for (i=0 ; i < TAILLETAMPON ; i+=1) {
char tampon[i];
recv(mon_socket, tampon, sizeof(tampon),0);
printf("%d \n", tampon);
}

}


je constate que les paquet que je reçois mes paquets, les 2 première ligne sont des paquets identique, ils sont identique 16 par 16 je suppose que le premier paquet fait 2 octet et que tous les autres en font 16 (corriger moi si je me trompe). Donc maintenant si je comprend bien le wikia il faudrait que je les décryptes apparemment la méthode de cryptage s'appelle "XOR", je ne sais pas ce que c'est mais bon si ils le disent . Ils donnent un script pour décrypter (je pense) les paquets le problème c'est que ça ne met pas vraiment compréhensible, je comprendre les unsigned etc (truc de base) mais il y a pas mal d'erreurs. Donc voila qu'il nous donne:
signed short Pak_SwitchEncryptionOff_150 (pak_t *pak, unsigned long seed)
{
   // the 1.50 protocol cryptography uses extensively the standard C random number generator,
   // which is a VERY BAD idea, since its implementation may differ from system to system !!!

   char stack1[10];
   char stack2[10];
   unsigned char a;
   unsigned char c;
   char *edi;
   char *ebp;
   int index;
   unsigned int algo;
   signed short checksum;

   // initialize the system's pseudo-random number generator from the seed given in the datagram
   // (they apparently swapped the bytes in an attempt to confuse the reverse-engineerers)
   srand (  (int) (((unsigned char *) &seed)[0] << 24)
          | (int) (((unsigned char *) &seed)[3] << 16)
          | (int) (((unsigned char *) &seed)[1] << 8)
          | (int) (((unsigned char *) &seed)[2]));

   // now generate the crypto tables for the given datagram length

   // stack sequences
   for (index = 0; index < 10; index++)
   {
      stack1[index] = (char) rand ();
      stack2[index] = (char) rand ();
   }

   // xor table
   for (index = 0; index < pak->data_size; index++)
   {
      cryptotables_150.xor[index] = (unsigned char) stack2[rand () % 10];
      cryptotables_150.xor[index] *= (unsigned char) stack1[rand () % 10];
      cryptotables_150.xor[index] += rand ();
   }

   // offset & algo tables
   for (index = 0; index < pak->data_size; index++)
   {
      cryptotables_150.offsets[index] = rand () % pak->data_size;
      if (cryptotables_150.offsets[index] == (unsigned int) index)
         cryptotables_150.offsets[index] = (index == 0 ? 1 : 0);

      cryptotables_150.algo[index] = rand () % 21;
   }

   // cryptographic tables are generated, now apply the algorithm
   for (index = pak->data_size - 1; index >= 0; index--)
   {
      algo = cryptotables_150.algo[index];
      ebp = &pak->data[cryptotables_150.offsets[index]];
      edi = &pak->data[index];

      a = *ebp;
      c = *edi;

      if      (algo 0)  { *edi ((a ^ c) & 0x0F) ^ c;  *ebp = ((a ^ c) & 0x0F) ^ a;  }
      else if (algo 1)  { *edi ((a ^ c) & 0x0F) ^ c;  *ebp = (a >> 4) | (c << 4);   }
      else if (algo 2)  { *edi (c >> 4) | (c << 4);   *ebp = (a >> 4) | (a << 4);   }
      else if (algo 3)  { *edi (a >> 4) | (c << 4);   *ebp = ((a ^ c) & 0x0F) ^ c;  }
      else if (algo 4)  { *edi (a & 0x0F) | (c << 4); *ebp = (a & 0xF0) | (c >> 4); }
      else if (algo 5)  { *edi (c & 0xF0) | (a >> 4); *ebp = (a << 4) | (c & 0x0F); }
      else if (algo 6)  { *edi (a >> 4) | (c << 4);   *ebp = (a << 4) | (c >> 4);   }
      else if (algo 7)  { *edi (c & 0xF0) | (a >> 4); *ebp = (a & 0x0F) | (c << 4); }
      else if (algo 8)  { *edi (a & 0x0F) | (c << 4); *ebp = (c & 0xF0) | (a >> 4); }
      else if (algo 9)  { *edi (a & 0xF0) | (c >> 4); *ebp = (a & 0x0F) | (c << 4); }
      else if (algo 10) { *edi (a << 4) | (c & 0x0F); *ebp = (a & 0xF0) | (c >> 4); }
      else if (algo 11) { *edi (a << 4) | (c >> 4);   *ebp = ((a ^ c) & 0x0F) ^ a;  }
      else if (algo 12) { *edi (a >> 4) | (a << 4);   *ebp = (c >> 4) | (c << 4);   }
      else if (algo 13) { *edi a;                     *ebp = c;                     }
      else if (algo 14) { *edi (a & 0xF0) | (c >> 4); *ebp = (a << 4) | (c & 0x0F); }
      else if (algo 15) { *edi ((a ^ c) & 0x0F) ^ a;  *ebp = ((a ^ c) & 0x0F) ^ c;  }
      else if (algo 16) { *edi a;                     *ebp = (c >> 4) | (c << 4);   }
      else if (algo 17) { *edi (a << 4) | (c & 0x0F); *ebp = (c & 0xF0) | (a >> 4); }
      else if (algo 18) { *edi (a << 4) | (c >> 4);   *ebp = (a >> 4) | (c << 4);   }
      else if (algo 19) { *edi (a >> 4) | (a << 4);   *ebp = c;                     }
      else if (algo 20) { *edi ((a ^ c) & 0x0F) ^ a;  *ebp = (a << 4) | (c >> 4);   }
   }

   // and finally, quadruple-XOR the data out
   for (index = pak->data_size - 1; index >= 0; index--)
   {
      if (index <= pak->data_size - 4)
      {
         pak->data[index + 0] ^= (cryptotables_150.xor[index] & 0x000000FF); // we can XOR 4 bytes in a row
         pak->data[index + 1] ^= (cryptotables_150.xor[index] & 0x0000FF00) >> 8;
         pak->data[index + 2] ^= (cryptotables_150.xor[index] & 0x00FF0000) >> 16;
         pak->data[index + 3] ^= (cryptotables_150.xor[index] & 0xFF000000) >> 24;
      }
      else if (index == pak->data_size - 3)
      {
         pak->data[index + 0] ^= (cryptotables_150.xor[index] & 0x0000FF); // we can XOR 3 bytes in a row
         pak->data[index + 1] ^= (cryptotables_150.xor[index] & 0x00FF00) >> 8;
         pak->data[index + 2] ^= (cryptotables_150.xor[index] & 0xFF0000) >> 16;
      }
      else if (index == pak->data_size - 2)
      {
         pak->data[index + 0] ^= (cryptotables_150.xor[index] & 0x00FF); // we can XOR 2 bytes in a row
         pak->data[index + 1] ^= (cryptotables_150.xor[index] & 0xFF00) >> 8;
      }
      else if (index == pak->data_size - 1)
         pak->data[index] ^= (cryptotables_150.xor[index] & 0xFF); // end of stream
   }

   // in the 1.50 protocol, the checksum info is at the trailing end of the pak.
   checksum = *(unsigned short *) &pak->data[pak->data_size - 2]; // so get it from there...
   pak->data_size -= 2; // ...and correct the data size

   return (checksum); // finished, pak is decrypted
}


Si quelqu'un a une idée de comment s'en servir qu'il m'en fasse par (je cherche a apprendre car ça m'intéresse beaucoup je suis peut être totalement a coté de la plaque mais bon je met ce que je pense être bon).

Merci d'avance,
Cordialement.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Enfaite maintenant que j'ai rechercher pas mal de "truc" je peux surement mieux expliquer ce que je cherche a faire (j'espère être plus clair ^^):

Donc je possède un serveur, d'un vieux jeu pour ce qui connaisse c'est t4c (la quatrième prophétie un jeu en 2D précurseur de pas mal de mmo je pense..) il a été connu sur GOA un vieux site où on pouvait y retrouver pas mal de jeu en ligne.
Voila pour la petite anecdote de t4c.

En gros, il existe plusieurs version de ce jeu (la 1.25, la 1.50, la 1.61, la 1.63 et la 1.70) des développeurs très sympathique on permis a des gens comme moi de pouvoir créé un serveur de ce jeu. Mais ils on limiter les "T4C Server" a la 1.50, il faut un "proxy" qui récupère les paquet du serveur, les décrypte, le reencrypte et les renvoi au client et vice versa pour qu'un client 1.61 ou supérieur (suivant le reencyptage) puisse se connecter au serveur, alors ma venu ici consiste a essayer de comprendre comment faire. Petit problème, j'ai utiliser la lib winsock je récupère des paquets le problème c'est que je pense récupéré les paquets de mon réseau et non les paquets envoyer par mon serveur, j'ai tester cela en regardant comment était composer les paquets se sont les même que mon serveur soit allumer ou éteint . Donc si quelqu'un a une idée de comment récupéré ces fameux paquets serveur qu'il se manifeste !! ^^ Bien sur que toutes réponse même novice comme moi est la bienvenu .

Merci d'avance,
Cordialement.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut.
Si tu indiques l'IP du serveur, c'est sur le serveur que tu te connectes.
Les bind() sont facultatifs pour les clients.
N'oublie pas de fermer ta socket en fin de programme.
Tu fais une erreur : printf("%d \n", tampon);
tampon est un tableau de char, et non un entier. Donc : printf("%s \n", tampon);

Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Effectivement suis-je bête :P par contre j'ai fait un test, alors si je met mon ip je reçoit *C(+ un caractère bizarre) tout le temps si je met "youtube" se sera autre chose mais tout la même chose est-ce normal de recevoir la même chose ? Si c'est crypté je pense qu'il y aurait des caractère différent. (mon code est le même que celui d'au dessus avec le "%s" à la place du "%d")

Merci d'avance,
Cordialement.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut.
Tu ne fais aucune requête, donc effectivement, tu recevras un message incompréhensible du serveur (qui doit sans doute être sa demande de connexion).
Si tu te connectes sur youtube par exemple, tu peux faire un send() avec une requête du genre "GET index.php\r\nHost: www.youtube.com\r\n\r\n" et ensuite seulement, ton recv() devrait contenir sa réponse (header suivi du code source de la page index.php) si tout se passe bien.


Cordialement, uaip.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
GET /index.php pardon (avec le /).
Si tu étais allé voir le lien de la source que je t'ai montré, tu n'aurais pas posé ce genre de question.
Je t'invite une fois de plus à aller voir son code. Tout y est.

Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Coucou, alors je reviens car je souhaite utilisé ce bout de code mais impossible à le faire marcher ne pouvant pas poser la question a mon frère pour le moment je la pose ici pourquoi ais-je des erreurs sur ça (a par pak je veux dire):

void Pak_ToggleEncryption_125 (pak_t *pak, unsigned short first_seed)
{
   // this function toggles Vircom's encryption on/off on the pak data. Note that the checksum
   // must be computed on the decrypted data, so it has to be done before calling this function.

   unsigned short seed;
   unsigned long index;

   seed = first_seed;

   // for each byte of data...
   for (index = 0; index < pak->data_size; index++)
   {
      seed = seed * 145 + 1; // apply an infinite suite to seed
      pak->data[index] ^= (char) seed; // use it to mask the data (XOR)
   }

   return; // finished
}
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut,
Syntaxiquement, il n'y a pas d'erreurs (il suffit de compiler pour voir les erreurs syntaxiques).
En supposant que data_size soit un int avec une valeur correcte, la boucle est bonne.
Le return est inutile.
Après, pour savoir si la fonction fait bien ce que tu veux... il faudrait déjà qu'on sache ce que tu veux, et ce n'est pas dit.


Cordialement, uaip.
Messages postés
31
Date d'inscription
samedi 22 avril 2006
Statut
Membre
Dernière intervention
24 août 2010

Dsl je n'ai pas expliquer en quoi ce code devait consister.. Il sert a crypter et décrypter les paquets de mon serveur donc si je comprend les paquet sont recueilli dans "pak". Je vous donne ce qu'ils disent:

Méthode de cryptage

Seules les données du pak sont cryptées, c'est-à-dire tout ce qui se situe au-delà du header, de la clé de cryptage et du checksum.

void Pak_ToggleEncryption_125 (pak_t *pak, unsigned short first_seed)
{
   // this function toggles Vircom's encryption on/off on the pak data. Note that the checksum
   // must be computed on the decrypted data, so it has to be done before calling this function.

   unsigned short seed;
   unsigned long index;

   seed = first_seed;

   // for each byte of data...
   for (index = 0; index < pak->data_size; index++)
   {
      seed = seed * 145 + 1; // apply an infinite suite to seed
      pak->data[index] ^= (char) seed; // use it to mask the data (XOR)
   }

   return; // finished
}

NOTE: La même fonction sert à la fois pour le cryptage et le décryptage.




Ensuite il donne la structure d'un pack:
Pak non fragmenté

Taille Type Description
=============================================================================
1 unsigned char 0
1 unsigned char Type de datagramme (tableau de bits)
2 unsigned short Longueur du datagramme
4 unsigned long ID du datagramme
4 unsigned long 0

2 unsigned short Clé de cryptage du pak
2 signed short Somme de contrôle des données du pak NON CRYPTEES (checksum)

* char * Données du pak (cryptées), encodées en "big endian"

il y a aussi les pack fragmenté qui sont composés de plusieurs parties..


Et voila les infos générale du netcode 1.25:
Le protocole réseau utilisé par T4C est du type non-connecté. Ce sont des datagrammes UDP.

Les données de ce datagramme comprennent un en-tête sur 12 octets, éventuellement suivis d'une clé de cryptage, d'une somme de contrôle ainsi que d'une chaîne de données cryptées (le pak).

Le cryptage est une série mathématique qui porte sur les octets 16 du datagramme et suivants, dont la clé est donnée à l'octet 12 sur 2 octets.

Le checksum (somme de contrôle) est donné sur 2 octets à l'octet 14 et porte sur les octets 16 du datagramme et suivants, avant encryption.

Les datagrammes de taille supérieure à 1024 octets sont systématiquement fragmentés (c'est-à-dire, envoyés en plusieurs parties de sorte que chaque partie envoyée ne fasse pas plus de 1024 octets).

Schéma canonique d'un datagramme du protocole 1.25 :

[HEADER][seed][checksum][DATA.........................]
[.......partie encryptée......]

ATTENTION: toutes les valeurs de l'en-tête, la clé de cryptage et la somme de contrôle sont en LITTLE ENDIAN (format de représentation des types de données Intel), mais les données du pak sont en BIG ENDIAN (format de représentation des types de données données Motorola). En lisant les données du pak sur un ordinateur de type x86, le programmeur doit penser à INVERSER l'ordre des octets. Les chaînes de caractères, étant considérées comme des tableaux d'octets, ne sont pas affectées.

Merci d'avance,
Cordialement.
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut,
Ok, ben j'ai répondu plus haut, dans ce cas.
En plus la fonction est apparemment déjà donnée, alors elle n'est pas censée contenir d'erreurs.
Ca ne sert à rien de balancer toute la doc, je suppose que c'est pas la doc qui ne fonctionne pas.
Donc je répète : dans tout ce que tu montres ici, aucune erreur apparente.

Cordialement, uaip.