IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème Nullchars. Eviter l'interpretation des \0


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut Problème Nullchars. Eviter l'interpretation des \0
    [MOD : Cette discussion dévie rapidement sur le C++, d'où le déplacement]

    Bonjour.

    Voilà, j'ai un gros problème avec l'interprétation du \0 en C.
    Alors je vous explique :

    Tout d'abord je fais un client en C/C++ avec winsock2 et socket.h sous linux (pour que le client soit portable. Le protocol du serveur est aussi écrit en C, mais je ne peux pas le modifier. Alors, le protocol a pour format @auth.pseudo.pass pour la connexion. Donc, la chaine a envoyer à la connexion est @auth\0pseudo\0pass, parce que le serveur se sert de nullchars comme séparateur entre les différentes choses à envoyer.

    Le problème est que, quand j'envoie la chaine en C, le \0 est interprété et la chaine que je récupère au sniff c'est @authpseudopass et non pas @auth.pseudo.pass comme je devrais. La standard de nullchars en C empêche l'envoie de la chaine en tronquant les séparateurs

    1. A partir de là, j'aimerais savoir si il y a une façon de faire que les \0 ne soient pas interprétés et soient envoyés directement au serveur à partir du client.

    2. Si non, j'aimerais savoir comment je peux convertir la chaine en hexadecimal et l'envoyer par la socket.

    3. Si quelqu'un a une idée, je suis prenneur ^^

    En gros, le client doit envoyer @auth.pseudo.pass (@auth\0pseudo\0pass), mais en C le \0 est interprété comme nullchar. Il faut que en sniffant le client, je puisse récupérer @auth.pseudo.pass et les "." ou "\0" en hexa me donne "00" comme valeur.

    J'espère avoir été assez clair et que vous pourrez m'aider parce que je sèche vraiment ^^''

  2. #2
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    c'est parce que l'écriture ou la lecture sur le socket se fait via un fprintf ou un fscanf..

    Si tu remplaces par un read ou write ça marchera et ça n'interpétera pas les '\0'...

  3. #3
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Citation Envoyé par souviron34
    c'est parce que l'écriture ou la lecture sur le socket se fait via un fprintf ou un fscanf..

    Si tu remplaces par un read ou write ça marchera et ça n'interpétera pas les '\0'...

    Euh, tu pourrais me donner un exemple s'il te plait ? Je vois pas comment remplacer par un read ou write. En fait les \0 sont interprétés dans les standards du C non ?

    C'est au niveau de la variable que ça cloche. En fait, j'ai une variable string sep = "\0" et en console le \0 vaut une fin, et n'est pas écrite.

    Enfin ce serait gentil si tu me donnais un exemple parce que je sèche

    Merci de ta réponse

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par JackStrieger
    En fait, j'ai une variable string sep = "\0"
    C'est du C, ça ?

    Ce qu'il faut savoir, c'est que ce n'est pas le type qui interprète \0 comme fin de chaîne, mais les fonctions, notamment strlen().
    Si tu connais la longueur des données par un autre moyen, tu peux très bien faire tes propres fonctions d'affichage...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Non, c'est pas du C. En fait je le fais avec un compilateur C++ pour certains avantages comme les strings là. Mais c'est sans poo. Je voulais juste montrer le principe pour la variable. Sinon, désolé si je me suis trompé de forum Je savais pas si je devais poster ici ou là bas.

    Ce qu'il faut savoir, c'est que ce n'est pas le type qui interprète \0 comme fin de chaîne, mais les fonctions, notamment strlen().
    Merci ^^ Mais donc, si dans ma variable je place \0, elle vaut toujours \0 ? c'est les fonctions qui l'interprètent comme une fin de chaine ? Parce que je ne passe par aucune fonction là, je ne fais qu'envoyer ma chaine, par la socket.
    Par exemple @auth\0pseudo\0pass, il n'envoie pas ça, mais les \0 sont bien interprétés. Et au sniff je récupère @autpseudopass.

    Si tu connais la longueur des données par un autre moyen, tu peux très bien faire tes propres fonctions d'affichage...
    Euh, j'ai pas trop besoin d'afficher ma chaine. J'ai surtout besoin de pouvoir l'authentifier pour avoir une connexion au serveur. Donc aucune autre fonction que cette de winsock dans un premier temps.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    1. Tu ne détailles pas assez comment tu l'envoies, ni comment tu construits tes strings.
      Tu peux essayer le constructeur de string qui prend en paramètre un const char * et une longueur:
      Ce code fonctionne correctement sous Visual Studio 2005 :
      Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      std::string str3("Hello\0World", 8);
      std::cout << "Longueur de string avec \\0 : " << str3.length() << std::endl;
      std::cout << "La string : \"" << str3 << "\"" << std::endl;
      Ce code affiche 8 comme longueur, et affiche bien le début de la string en remplaçant le caractère nul par un espace. Tu peux remarquer qu'à tout moment c'est string qui est utilisé, et nulle part char* (sauf au constructeur) : En effet, sous VS2005, la classe string supporte les caractères nuls.
    2. Vérifies que ce n'est pas le sniff qui buggue. Plutôt que d'afficher les données en tant que test, regarde si tu ne peux pas afficher tout en hexa. Ainsi, tu verras bien si tu as plusieurs octets nuls dans les données...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    1. Mon code fait environ ça :

    string separateur = "\0"; (ce que je devrais faire normalement)

    string conn = "@auth";
    conn += separateur + pseudo;
    conn += separateur + motdepasse;

    send(sock, conn.c_str(), conn.size(), 0);

    C'est ça pour l'auth, et la construction de la chaine.

    2. J'ai essayé déjà de faire un "\\0" mais ça ne renvoie pas la même chose, que j'expliquerai plus bas après le sniff. Donc ça ne marche pas.

    3. Au sniff j'ai effectivement regardé ce que donne l'hexa et non pas seulement la chaine "convertie". Avec un autre langage, quand j'envoie \0, ça affiche un "." et avec la valeur 00 en hexa.
    Ce que je sniff "normalement" : @auth.pseudo.pass ET à la place des ".", je reçois "00" en hexadecimal. Ce qui est tout à fait normal donc.

    Mais quand je fais un \\0 en, ça m'affiche bien un "\0", mais c'est pas ce que je dois avoir. Tout simplement parce que le \ donne une valeur hexa et le 0 donne une autre valeur hexa, ce qui n'est pas le "00" que je devrais avoir.

    4. Donc, suite à cela, ce serait génial si j'ai la solution de vraiment pouvoir envoyer un \0 normal, sans que ça soit interprété.
    Mais sinon, je voudrais savoir si je peux envoyer directement la chaine en hexadecimal, et comment faire.

    Merci beaucoup

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par JackStrieger
    1. Mon code fait environ ça :

    string separateur = "\0"; (ce que je devrais faire normalement)

    string conn = "@auth";
    conn += separateur + pseudo;
    conn += separateur + motdepasse;

    send(sock, conn.c_str(), conn.size(), 0);

    C'est ça pour l'auth, et la construction de la chaine.
    Deja ca ce n'est pas du C.

    Ensuite si tu souhaites pouvoir envoyer le caractere \0, il ne faut pas travailler avec des chaines de caracteres (ni des fonctions de manipulation de chaines str...) pour lesquelles \0 represente la fin de chaine (et qui est donc
    ecrase lors de la concatenation d'une seconde chaine. Tu vas devoir travailler avec un "simple" tableau de char et les fonctions de manipulation de memoire (memcpy et autre) et/ou acces direct au caractere voulu.

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par JackStrieger
    string separateur = "\0"; (ce que je devrais faire normalement)
    Mauvais. Le constructeur string(char const*) ne connait pas le nombre de caractères, donc il fait un strlen() (ou l'équivalent) --> Ta chaîne séparateur à une longueur nulle au lieu de faire un seul caractère.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Citation Envoyé par gl
    Deja ca ce n'est pas du C.
    Non, c'est pas du C. En fait je le fais avec un compilateur C++ pour certains avantages comme les strings là. Mais c'est sans poo. Je voulais juste montrer le principe pour la variable. Sinon, désolé si je me suis trompé de forum Je savais pas si je devais poster ici ou là bas.
    Donc, je fais un const char[3] = "\0"'

    Et est-ce que vous pourriez me donner un exemple concret de ce que ça donnerait s'il vous plait ?

    Mauvais. Le constructeur string(char const*) ne connait pas le nombre de caractères, donc il fait un strlen() (ou l'équivalent) --> Ta chaîne séparateur à une longueur nulle au lieu de faire un seul caractère.
    Edit: Donc je peux faire quoi d'autre ?
    Est-ce que quelqu'un saurait comment envoyer directement en hexa par winsock2 et socket.h ?
    Merci en tout cas.

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ce que tu peux faire, c'est essayer avec le bon constructeur de std::string :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string separateur("\0", 1);
    Et aussi, lors de l'envoi, afficher la longueur pour être sûr que c'est bien celle attendue.

    Ensuite, vérifier avec le sniffer que tout a bien été envoyé, caractères nuls compris, puis on bossera sur la réception.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Merci beaucoup Ca marche très bien maintenant pour la connexion, et au sniff je récupère bien la valeur NULL.
    Cependant j'ai un problème(mineur), mais je ne vois pas trop d'ou vient le problème.
    recv(sock,r.c_str(),r.size(),0);

    Et ça me donne une erreur : invalid conversion from `const char*' to `char*'

    Je ne comprends pas très bien, parce que je me sers de la même conversion string-char pour le send, et ça marche.

  13. #13
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Si il y a un problème de conversion, je pense que je vais faire mes propres fonctions de gestion de chaines, mais ce serait sympa si je peux trouver l'erreur là.
    Merci.

    Edit : Avec un char, bien sur, je peux recevoir.

  14. #14
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    recv() a besoin d'un accès direct en écriture sur la mémoire, ce que std::string ne donne pas (sauf avec un hack affreux).
    Tu dois donc utiliser un tableau de char dans cette circonstance.
    Crées un tableau de char de taille suffisante, et passe cette taille en paramètre de recv()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Merci beaucoup

  16. #16
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    (Désolé d'avoir posté dans le mauvais forum)

    Maintenant j'ai le même problème à la reception J'ai des retours comme ceux de l'envoi, et je ne peux afficher que la première partie du proto, donc tout ce qui se trouve après le nullchar n'est pas affiché.

    Est-ce que vous auriez une idée comme traiter ça ?

    Merci bien

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu reçois tout dans un tableau de char suffisament grand, puis tu l'utilises pour construire une string avec le bon constructeur et la taille retournée par recv().
    Là, tu pourras afficher la string.

    Ou bien, tu lis directement les trois chaînes dans le buffer, l'une à la suite de l'autre...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    Re,

    Alors, j'ai un autre problème. Je reçois les réponses du serveur dans un tableau de char, et toujours avec les caractères "\0". Donc, je ne peux pas travailler dessus. Puis, avant d'envoyer le tableau dans un string(parce que j'ai besoin de formater le texte avant l'affichage), j'essaie de remplacer les \0 par un autre caractère. Je pensais à un "~" ou "\1". Pendant la petite fonction qui lit caractère par caractère, je fais une comparaison à chaque fois à \0 et quand il en trouve, il le remplace. Le problème est que, :

    if (Tampon[i] == '\0')
    quand je mets '\0' la fenêtre se ferme tout de suite. Alors qu'avec un autre caractère ça marche très bien.

    Est-ce que vous sauriez d'ou vient le problème ?

  19. #19
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pour commencer, tu vérifies bien que tu ne sors pas du tampon ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Membre confirmé
    Inscrit en
    Avril 2007
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 115
    Par défaut
    int main(int argc, char *argv[])
    {
    char Tampon[30] = "Salut, \0 tu vas bien ?";
    int i = 0;
    int Coupure = 15;
    char MotCopie[30];
    char val = '\0';

    cout << Tampon << endl << endl;


    for (i = 0 ; Tampon[i] != Coupure ; i++)
    {
    if (Tampon[i] != val)
    {
    Tampon[i] = '~';

    }
    }
    cout << "Phrase : " << Tampon << endl;

    return EXIT_SUCCESS;
    }

    Voilà, je ne sors pas du Tampon, ça marche avec un autre caractère. C'est le \0 qui fait tout fermer tout de suite.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. problème d'interpretation des makefile Photran/ubuntu
    Par frabrovitch dans le forum Eclipse
    Réponses: 0
    Dernier message: 01/10/2007, 09h55
  2. Réponses: 5
    Dernier message: 24/10/2005, 15h11
  3. [JAXB][XSD] Problème lors de la génération des classes
    Par charlot44 dans le forum Persistance des données
    Réponses: 4
    Dernier message: 22/06/2005, 16h10
  4. Réponses: 2
    Dernier message: 20/08/2004, 17h10
  5. Réponses: 9
    Dernier message: 17/01/2004, 10h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo