C/C++ [Résolu] [C] Comment faire son reader/writer ?

Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#1
Bonjour à tous,
Depuis quelques jours j'ai voulu commencer un petit bot en langage C, j'ai suivi donc les nombreux tutoriels.. jusqu'à l'étape du reader, ça fait 1 semaine que je bloque dessus, j'ai bien compris ce qu'il fallait faire, j'ai décompilé les sources et y ait retrouvé les étapes (id 1, id 3 ..) mais je n'arrive vraiment pas à faire un reader fonctionnel en C, vu que les Class n'existent pas en C j'ai essayé de tout faire sous forme de petite fonction mais rien n'y fait, sois j'obtiens des nombres gigantesques, sois 5, sois -1, sois 0 pour requiredversion & currentversion..
Est-ce que quelqu'un ici est déjà parvenu à faire un reader en C ?
Svp pas de "traduit cette source" etc..
 

Sparkdaemon

Staff
Membre du personnel
Inscrit
7 Avril 2009
Messages
556
Reactions
3
#2
Re: [C] Comment faire son reader/writer ?

Je connaissant absolument pas le C/C++, Je ne peux que te dire de.. Traduire une source. C'est la seule solution.
De plus, Il vaux mieux que tu la traduise, étant donné que tu es censé apprendre, Tu pourrais en apprendre sur deux langages de programmation à la fois.

https://cadernis.fr/index.php?threads/[tuto]-bot-socket-les-fondamentaux.491/
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#3
Re: [C] Comment faire son reader/writer ?

J'ai eu le même problème que toi et pas moyen d'en trouver de simple, de plus le problème de big et little endian.
J'ai donc réaliser mes propre classes, je me suis inspiré du code d'un membre du forum (désolé je ne me souviens plus de qui :x) pour le reader.
Ce n'est qu'un début, si cela t'intéresse je pourrais faire part des évolutions ;)

http://www.yann.cx/uploads/BinaryReadWrite.rar

Tu y trouvera BinaryReader et BinaryWriter (source et header) ainsi qu'un fichier de teste (que je n'est pas testé ^_^').

PS: Parcontre c'est du C++ (les classes)
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#4
Re: [C] Comment faire son reader/writer ?

Spark, je n'ai fait que ça, de traduire, mais il n'y a pas moyen d'arriver à quelques choses à chaque fois.. Pourtant je comprend très bien C# & VB.NET mais là dessus ...
Sorrow, merci je vais regarder ça de plus près, j'espère ne pas être embêter par le fait que ce soit des Class vu que les Class n'existent pas en C, je regarde ça dans l'après midi merci ! :)

Ps : En fait je viens de regarder et c'est déjà ce que je faisais, donc j'ai toujours mon problème.. je commence à me demander si cela ne viendrait pas de mon parser parce que je ne sais pas comment faire ceci en C :
Code:
// Récupération du contenu du paquet
packet_content = new byte[(int)packet_lenght];
Array.Copy(DataToParse, index + packet_lenght_type, packet_content, 0, packet_lenght);
J'ai essayé avec memcpy mais peut être que mon erreur vient d'ici :x
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#5
Re: [C] Comment faire son reader/writer ?

Moi j'ai pas fait comme sa, je trouver pas comment parser facilement les packets, j'ai donc fait quelques chose de simple, mais je ne sais pas si c'est une bonne technique:

(Par-contre c'est dans le cas de W. (proxy MITM), mais facilement adaptable)

- Je sais que les packets Client -> Serveur ont une entête de 5 octects
- Je sais que les packets Serveur -> Client ont une entête de 4 octects

Donc je lis (avec recv) 5 octects dans le sens client -> serveur, je découpe :

- 2 octets pour la taille du packet total
- 1 octet dont je ne connais pas l'utilité
- 2 octets pour l'opcode

Puis je récupère (avec recv) la taille du packet total - 5 (moins la taille de l'entête déjà lu)

Pareil pour le sens serveur -> client, sauf que cette fois si l'entête ne fait que 4 octets (il n'y a pas l'octet inconnu).
(Quand je reconstitue le packet avec le writer il est envoyer en un seul morceaux, contrairement au fait de le lire en deux morceaux)

Si j'ai le temps dans la journée, je vais essayer de développer ta technique ;)
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#6
Re: [C] Comment faire son reader/writer ?

Mh ouais, tu as l'air de plus te compliquer la vie qu'autres choses je trouve.. Moi ça va je récupère l'ID, la taille, la taille de taille là dessus aucun problème mais c'est pour la suite que ça bloque, puis vu qu'il n'y a aucun tuto pour le C ça aide pas vraiment..
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#7
Re: [C] Comment faire son reader/writer ?

Qu'entend tu par "ça bloque" ? Tu ne reçois plus de packets ?
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#8
Re: [C] Comment faire son reader/writer ?

Non non, je veux dire par là, ça bloque, j'avance plus quoi, je reçois le paquet avec l'id 1, celui avec l'id 3, avec les bonnes tailles mais pour la suite, le reader ne fonctionne pas, ça fait 1 semaine que je retourne le problème dans tous les sens sans trouver de solutions..
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#9
Re: [C] Comment faire son reader/writer ?

Salut , pour le reader ca marche pareil que pour trouver l'id (juste le nombre de bytes qui change en fonction de int , double , utf ...)

par exemple pour lire un INT (donc 4 byte) dans le tableau de chars "data" avec "offset" la position de la "tete de lecture" :
integer_a_lire =
data[offset] * 16777216 + //* 256 ^ 3
data[offset + 1] * 65536 + //* 256 ^ 2
data[offset + 2] * 256 + //* 256 ^ 1
data[offset + 3] ; //* 256 ^ 0
offset=offset+4;

pour le writer c'est pareil
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#10
Re: [C] Comment faire son reader/writer ?

Radhan a dit:
Ps : En fait je viens de regarder et c'est déjà ce que je faisais, donc j'ai toujours mon problème.. je commence à me demander si cela ne viendrait pas de mon parser parce que je ne sais pas comment faire ceci en C :
Code:
// Récupération du contenu du paquet
packet_content = new byte[(int)packet_lenght];
Array.Copy(DataToParse, index + packet_lenght_type, packet_content, 0, packet_lenght);
J'ai essayé avec memcpy mais peut être que mon erreur vient d'ici :x
Code:
packet_content = new byte[(int)packet_lenght];
par
Code:
char *packet_content = (char*)malloc(sizeof(char)*packet_lenght);
(pense à inclure malloc.h)

Code:
Array.Copy(DataToParse, index + packet_lenght_type, packet_content, 0, packet_lenght);
par
Code:
for(i = 0; i < packet_lenght; i++)
        packet_content[i] = DataToParse[position + i];  // position = l'index du prochain octect non lu.

position += packet_lenght;
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#11
Re: [C] Comment faire son reader/writer ?

ToOnS, c'est déjà ce que je faisais, par exemple ma fonction pour lire un Int :
Code:
//Reader Int
int ReadInt (char *Data)
{
    int s = (Data [pos] << 24) + (Data [pos + 1] << 16) + (Data [pos + 2] << 8) + Data [pos + 3];
    pos += 4;
    return s;
}
Sorrow, merci mais je ne sais pas ce qu'il ne va pas.. j'obtiens ceci :
Code:
[+] Connexion a 213.248.126.39 sur le port 5555
[+] Connexion au serveur dofus reussi.

[ID] : 1  [Taille] : 8
RequiredVersion : 329728
CurrentVersion : 314368
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#12
Re: [C] Comment faire son reader/writer ?

Effectivement il y a un problème, pour ma part, voici mon ReadInt()

Code:
signed int BinaryReader::ReadInt()
{
    signed int i =
    this->buffer[this->position] * 16777216 +
    this->buffer[this->position+1] * 65536 +
    this->buffer[this->position+2] * 256 +
    this->buffer[this->position+3];

    this->position += 4;
    return i;
}
Et voila ce que donne le résulta avec le packet d'ID 1, en lisant 2 int j’obtiens :

Code:
Packet #1 from SERVER, size: 8
required: 1236
current: 1228
(Attention, c'est les versions de la beta 2.10)
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#13
Re: [C] Comment faire son reader/writer ?

Mon ReadInt() revient au même que le tient.. mon problème doit venir d'ailleurs mais j'ai beau chercher je vois pas, je retourne mon code dans tous les sens mais je trouve pas ce qu'il bloque, pourtant je lis bien les 2 Int sur le packet_content..
Mon fichier source du parser :
Code:
#include "parse.h"


//Parse le buffer
void Parse (char *Data)
{
    //Déclaration des variables utilisés
    int Index = 0;
    short Header, ID, TailleDeTaille;
    int Taille;
    int i;
    int Position = 0;

    while (Index != sizeof(Data))
    {
        Header = GetHeader (Index, Data); //On prend les 2 premiers octets
        ID = GetID (Header); //On récupère l'ID
        TailleDeTaille = GetLenghtSize (Header); //On récupère la taille de la taille du Header

        Index += 2; //On déplace le curseur de 2 octets plus loin

        Taille = GetSize (TailleDeTaille, Taille, Index, Data); //On récupère la taille du paquet

        char Donnees [Taille];

        for(i = 0; i < Taille; i++)
        {
            Donnees[i] = Data [Position + i];
        }
        Position += Taille; //On se positionne pour le prochain paquet

        if (ID != 0 && Taille != 0)
        {
            printf ("[ID] : %d  [Taille] : %d \n", ID, Taille);
        }

        TraitementPaquet (ID, Donnees);
    }


}


//On prend les 2 premiers octets
short GetHeader (int Index, char *Data)
{
    return (Data [Index] << 8) + (Data [Index + 1]);
}

//On prend l'ID du paquet
short GetID (short Data)
{
    return Data >> 2;
}

//On récupère la taille de la taille du Header
short GetLenghtSize (short Data)
{
    return Data & 3;
}

//On récupère la taille
short GetSize (short TailleDeTaille, short Taille, short Index, char *Data)
{
    switch(TailleDeTaille)
    {
        case 0:
            Taille = 0;
        break;

        case 1:
            Taille = Data [Index];
        break;

        case 2:
            Taille = (Data [Index] << 8) + Data [Index + 1];
        break;

        case 3:
            Taille = (Data [Index] << 16) + (Data [Index + 1] << 8) + Data [Index + 2];
        break;
    }
    return Taille;
}



//Reader Short
short ReadShort(char *Data)
{
    short s = (Data [pos] << 8) + Data [pos + 1];
    pos += 2;
    return s;
}


//Reader Int
int ReadInt (char *Data)
{
    int s = (Data [pos] << 24) + (Data [pos + 1] << 16) + (Data [pos + 2] << 8) + Data [pos + 3];
    pos += 4;
    return s;
}

//Reader Byte
char ReadByte (char *Data)
{
    char s = Data [pos];
    pos += 1;
    return s;
}

Ps : Si j'ai tout mis sous forme de petite fonction c'est pour pouvoir m'organiser plus tard, enfin si je parviens à régler ce problème :x
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#14
Re: [C] Comment faire son reader/writer ?

J'ai des doute sur la portabilité de ta variable "pos", la position est bien la même entre toutes tes fonction read ?
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#15
Re: [C] Comment faire son reader/writer ?

Ma variable est défini dans le fichier Parse.h en tant que variable globale, ma fonction "TraitementPaquet()" :
Code:
#include "traitement.h"

void TraitementPaquet (int ID, char *Donnees)
{
    pos = 0;
    int RequiredVersion, CurrentVersion; //ID 1

    switch (ID)
    {
        //Traitement de l'ID 1
        case 1:
            RequiredVersion = ReadInt (Donnees);
            CurrentVersion = ReadInt (Donnees);
            printf ("RequiredVersion : %d \nCurrentVersion : %d \n\n", RequiredVersion, CurrentVersion);
        break;

        //Traitement de l'ID 3
        case 3:

        break;

        //Traitement de l'ID 4
        case 4:

        break;
    }

}
 
Inscrit
29 Septembre 2011
Messages
393
Reactions
3
#16
Re: [C] Comment faire son reader/writer ?

Salut, moi en c++ je fait comme ça :

Code:
#ifndef READERWRITER_H
#define READERWRITER_H

#include <QObject>
#include <QVector>
#include <QTextCodec>
class ReaderWriter : public QObject
{
    Q_OBJECT
public:
    explicit ReaderWriter(QObject *parent = 0);
    explicit ReaderWriter(QByteArray bytes, QObject *parent = 0);
    void fromBytes(QByteArray bytes);
    QByteArray getBytes();
    void setPos(int pos);
    int getPos();
    // ===== READER ====
    int readInt();
protected:
    int _pos;
    QByteArray _buffer;

};

#endif // READERWRITER_H
Code:
#include "readerwriter.h"

ReaderWriter::ReaderWriter(QObject *parent):
    QObject(parent)
{
    _pos = 0;
}

ReaderWriter::ReaderWriter(QByteArray bytes, QObject *parent):
    QObject(parent)
{
    _pos = 0;
    _buffer = bytes;
}

void ReaderWriter::fromBytes(QByteArray bytes)
{
    _pos = 0;
    _buffer = bytes;
}

QByteArray ReaderWriter::getBytes()
{
    return _buffer;
}

void ReaderWriter::setPos(int pos)
{
    _pos = pos;
}

int ReaderWriter::getPos()
{
    return _pos;
}

int ReaderWriter::readInt()
{
    return uint(readByte() << 24) + (readByte() << 16) + (readByte() << 8) + (readByte() << 0);
}
et puis pour le parser tu peut tous simplement faire ça :

Code:
  m_reader = new ReaderWriter(bytes);
    m_header = m_reader->readShort();
    protocolID = m_header >> 2;
    m_len = (uint)m_header & 3;
    packetLen();
j'espère que cela pourra t'aider.

Cordialement Tifoux.
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#17
Re: [C] Comment faire son reader/writer ?

Radhan a dit:
[code
while (Index != sizeof(Data))
{
...}
ca ca va pas etre genant pour la connexion mais plus tard ca va poser probleme si tu recois un message de plus de 8ko (en ouvrant une grosse banque par exemple) car a plus de 8ko par message ca sera etallé sur 2 packets et index sera jamais = a sizeof(Data) , il faudra gerer plusieurs packets pour un seul message
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#18
Re: [C] Comment faire son reader/writer ?

Tifoux, merci mais ça ne m'aide pas vraiment je pense que mon problème vient d'ailleurs :/
Toons, merci tu avais raisons à ce propos, c'est pour ça que lorsque je mettais
Code:
Index += Taille + TailleDeTaille
à la fin de ma boucle ça faisait freeze mon programme, j'ai corrigé cela et j'en ai profité pour ré-organiser :

Connexion.c
Code:
#include "connexion.h"

void Connexion ()
{
    WSADATA WSAData;
    WSAStartup (MAKEWORD (2, 2), &WSAData);

    //Socket Client -> Serveur
    SOCKET Sock;
    Sock = socket (AF_INET, SOCK_STREAM, 0);

    if (Sock == INVALID_SOCKET)
    {
        printf ("Erreur : Socket invalide \n");
        exit (0);
    }

    //On configure la connexion Client vers Serveur
    SOCKADDR_IN Sin;
    Sin.sin_addr.s_addr = inet_addr ("213.248.126.39");
    Sin.sin_family = AF_INET;
    Sin.sin_port = htons (5555);

    printf("[+] Connexion a %s sur le port %d\n", inet_ntoa(Sin.sin_addr), htons(Sin.sin_port));

    if (connect (Sock, (SOCKADDR *)&Sin, sizeof(Sin)) == (signed)INVALID_SOCKET)
    {
        printf ("[-] Erreur : Connexion \n");
        exit (0);
    }

    printf("[+] Connexion au serveur dofus reussi. \n\n");

    char *Buffer = NULL;

    while (Sock != (unsigned)SOCKET_ERROR)
    {
        Buffer = calloc (8192, sizeof (char));
        if (Buffer == NULL) { exit (0); }

        //On réceptionne les données
        recv (Sock, Buffer, 8192, 0);

        if (Buffer != NULL)
        {
            //On Parse le buffer
            Parse (Buffer);
        }

        free (Buffer);
        Buffer = NULL;
    }

    closesocket (Sock);
    WSACleanup ();
}

Parse.c
Code:
#include "parse.h"


//Parse le buffer
void Parse (char *Data)
{
    //Déclaration des variables utilisés
    int Index = 0;
    short Header, ID, TailleDeTaille;
    int Taille;
    int i;
    int Position = 0;
    char *Donnees = NULL;

    //On parcours tout le buffer
    while (Index < sizeof(Data))
    {
        //On prend les 2 premiers octets
        Header = GetHeader (Index, Data);

        //On récupère l'ID
        ID = GetID (Header);

        //On récupère la taille de la taille du Header
        TailleDeTaille = GetLenghtSize (Header);

        //On déplace le curseur de 2 octets plus loin
        Index += 2;

        //On récupère la taille du paquet
        Taille = GetSize (TailleDeTaille, Taille, Index, Data);

        //Allocation de mémoire de taille de la variable Taille
        Donnees = calloc (1, Taille);
        if (Donnees == NULL) { exit (0); }

        //On copie le contenu du 1er paquet dans Donnees
        for(i = 0; i < Taille; i++)
        {
            Donnees[i] = Data [Position + i];
        }
        //On se positionne pour le prochain paquet
        Position += Taille;

        //On affiche les ID & leur taille si > 0
        if (ID != 0 && Taille != 0)
        {
            printf ("[ID] : %d  [Taille] : %d \n", ID, Taille);
        }

        //On traîte les paquets
        TraitementPaquet (ID, Donnees);

        //On se positionne pour le paquet suivant
        Index += Taille + TailleDeTaille;

        //On libère la mémoire et on la remet à NULL
        free (Donnees);
        Donnees = NULL;
    }


}


//On prend les 2 premiers octets
short GetHeader (int Index, char *Data)
{
    return (Data [Index] << 8) + (Data [Index + 1]);
}

//On prend l'ID du paquet
short GetID (short Data)
{
    return Data >> 2;
}

//On récupère la taille de la taille du Header
short GetLenghtSize (short Data)
{
    return Data & 3;
}

//On récupère la taille
short GetSize (short TailleDeTaille, short Taille, short Index, char *Data)
{
    switch(TailleDeTaille)
    {
        case 0:
            Taille = 0;
        break;

        case 1:
            Taille = Data [Index];
        break;

        case 2:
            Taille = (Data [Index] << 8) + Data [Index + 1];
        break;

        case 3:
            Taille = (Data [Index] << 16) + (Data [Index + 1] << 8) + Data [Index + 2];
        break;
    }
    return Taille;
}

Traitement.c
Code:
#include "traitement.h"

void TraitementPaquet (int ID, char *Donnees)
{
    int RequiredVersion, CurrentVersion; //ID 1

    switch (ID)
    {
        //Traitement de l'ID 1
        case 1:
            pos = 0;
            RequiredVersion = ReadInt (Donnees);
            CurrentVersion = ReadInt (Donnees);
            printf ("RequiredVersion : %d \nCurrentVersion : %d \n\n", RequiredVersion, CurrentVersion);
        break;

        //Traitement de l'ID 3
        case 3:

        break;

        //Traitement de l'ID 4
        case 4:

        break;
    }

}

//Reader Short
short ReadShort(char *Data)
{
    short s = (Data [pos] << 8) + Data [pos + 1];
    pos += 2;
    return s;
}


//Reader Int
int ReadInt (char *Data)
{
    int s = (Data [pos] << 24) + (Data [pos + 1] << 16) + (Data [pos + 2] << 8) + Data [pos + 3];
    pos += 4;
    return s;
}

//Reader Byte
char ReadByte (char *Data)
{
    char s = Data [pos];
    pos += 1;
    return s;
}

Traitement.h
Code:
#ifndef TRAITEMENT_H_INCLUDED
#define TRAITEMENT_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "parse.h"

int pos;

void TraitementPaquet (int ID, char *Donnees);

//Fonctions pour décryptage des paquets
short ReadShort (char *Data);
int ReadInt (char *Data);
char ReadByte (char *Data);

#endif // TRAITEMENT_H_INCLUDED

Merci de votre aide en tout cas, j'espère résoudre ce problème qui m'empêche d'avancer :(
 
Inscrit
21 Octobre 2012
Messages
21
Reactions
0
#19
Re: [C] Comment faire son reader/writer ?

Personne aurait une idée d'où mon problème pourrait venir ? :/
J'arrive jamais à obtenir les bonnes valeurs qui devrait être :
RequiredVersion = 1484 & CurrentVersion = 1492
 
Inscrit
29 Septembre 2011
Messages
393
Reactions
3
#20
Re: [C] Comment faire son reader/writer ?

Salut ayant bien regarder ton code j'ai trouver ton erreur :
Code:
   //Traitement de l'ID 1
        case 1:
            pos = 0;
            RequiredVersion = ReadInt (Donnees);
            CurrentVersion = ReadInt (Donnees);
            printf ("RequiredVersion : %d \nCurrentVersion : %d \n\n", RequiredVersion, CurrentVersion);
        break;
donc tu devrais faire comme ça :
Code:
   //Traitement de l'ID 1
        case 1:
            RequiredVersion = ReadInt (Donnees);
            CurrentVersion = ReadInt (Donnees);
            printf ("RequiredVersion : %d \nCurrentVersion : %d \n\n", RequiredVersion, CurrentVersion);
        break;
la tu a
car tu met remet ta position a 0 or après avoir lus le header etc ta position doit être egals a 3.


Cordialement tifoux.
 
Haut Bas