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

Réseau Discussion :

Création d'un sniffer


Sujet :

Réseau

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 51
    Points : 55
    Points
    55
    Par défaut Création d'un sniffer
    Bonjour à tous,

    Afin de réviser mes cours de réseau et histoire de coder un peu par passion, j'ai fais des recherches et ai commencé à coder un petit sniffer de réseau (à la wireshark mais en plus simple^^).
    Cependant, il y a quelques détails que je ne comprend pas...

    Au départ, à l'aide du man et des quelques exemples trouvés sur internet, j'ai décidé de créer ma socket de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock = socket(AF_PACKET, RAW_SOCKET, htons(ETH_P_ALL));
    En effet, d'après le man (socket2), le 'type' de socket SOCK_PACKET est obselète. Il me propose donc de m'orienter sur 'packet(7)'. C'est pourquoi j'ai créé la socket de cette manière, du moins c'est ce qui m'a parru logique...

    J'ai essayé de récupérer les données avec les structures suivantes : ethhdr, iphdr, tcphdr. Mais les données n'étaient pas correctes.

    J'ai ensuite trouvé un exemple qui créé la socket de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
    Ici, j'arrive à avoir les donnes des datagrammes IP et TCP sans problème. Cependant, SOCK_PACKET est obselète d'après la doc, et ensuite, je n'arrive toujours pas à avoir les données de la tram ethernet, par exemple le protocole utilisé : IP ou ARP par exemple. Il semble que je ne recoive que les packets TCP...

    Si j'ai bien compris, créer la socket de cette manière me permet d'avoir accès à la couche TRANSPORT du modèle OSI non ?
    Du coup, si je veux avoir les données de la tram Ethernet, je devrais être à la couche RESEAU non ?

    Si quelqu'un pouvait m'éclairer sur le sujet pour mieux comprendre, ça m'intéresserait beaucoup !

    Bonne journée,

    Guidono

  2. #2
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    Bonjour,

    Il semblerait qu'un raw socket se crée via sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); et c'est SOCK_RAW et non RAW_SOCKET (d'après le man).

    Sinon serait-il possible de voir la tête d'un paquet capturé ? (par exemple avec un dump hexadécimal du paquet )
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 51
    Points : 55
    Points
    55
    Par défaut
    Merci pour ta réponse,

    Alors concernant l'hex dump ça donne ça (hexdump de la structure 'packet_t' donc ethhdr+iphdr+tcphdr SANS les 'data' de tcp) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    0x000000: 00 00 00 00 00 00 00 00 ........
    0x000008: 00 00 00 00 08 00 45 00 ......E.
    0x000010: 00 3c de f3 40 00 40 06 .<..@.@.
    0x000018: 5d c6 7f 00 00 01 7f 00 ].......
    0x000020: 00 01 d4 a9 1a c5 90 a3 ........
    0x000028: 76 94 00 00 00 00 a0 02 v.......
    0x000030: aa aa fe 30 00 00 02 04 ...0....
    0x000038: ff d7 04 02 08 0a 00 00 ........
    Pour la récupération de la tram éthernet, au départ j'ai utilisé struct ethhdr (linux/if_ether.h), ensuite j'ai testé la structure ether_header dans net/ethernet.h, mais rien de cool non plus...

  4. #4
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    dans l'exemple de code que tu as cité et les adresses ethernet seront bien récupérées, ce qui n'est pas le cas dans ton dump.
    ɹǝsn *sıɹɐlos*

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 51
    Points : 55
    Points
    55
    Par défaut
    Merci pour vos réponses,

    J'avais déjà testé cette manière de créer la socket, mais sans succès... Voici le code testé avec un exemple d'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <linux/if_ether.h>
    #include <linux/ip.h>
    #include <linux/tcp.h>
    #include <net/ethernet.h>
    #include <errno.h>
    #include <stdio.h>
     
    #include "hexadump.h"
     
    #define SOCKET_ERROR -1
     
    struct packet_t {
    	struct ethhdr eth; /* entete d une tram ethernet voir linux/if_ether.h */
    	//struct ether_header eth;
    	struct iphdr ip;   /* entete d un datagramme ip voir linux/ip.h */
    	struct tcphdr tcp; /* entete d un paquet tcp voir linux/tcp.h */
    	char * data;       /* données */
    };
     
    int main() {
     
    	int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    	//int sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); 
     
    	if ( sock == SOCKET_ERROR ) {
    		perror("Socket error");
    		return -1;
    	}
     
    	struct packet_t buffer;
    	struct ethhdr   *eth_ptr;
    	//struct ether_header   *eth_ptr;
    	struct iphdr    *ip_ptr;
    	struct tcphdr   *tcp_ptr;
    	unsigned char *src, *dst;
    	int octets_recus;
     
    	eth_ptr = &buffer.eth;
    	ip_ptr  = (struct iphdr *)(((unsigned long)&buffer.ip)-2);
    	tcp_ptr = (struct tcphdr *)(((unsigned long)&buffer.tcp)-2);
     
    	src = (unsigned char *)&(ip_ptr->saddr);
    	dst = (unsigned char *)&(ip_ptr->daddr);
     
    	//while (1) {
    		printf("Wait...\n");
     
    		octets_recus = read(sock, (struct packet_t*)&buffer, sizeof(struct packet_t));
     
    		hexdump(&buffer, octets_recus);
     
    		printf("===> Packet intercepted, %d bytes sniffed <===\n", (octets_recus));
    		printf("Ethernet - proto ::: ");
    		if (eth_ptr->h_proto == ETHERTYPE_IP) {
    			printf("IP\n");
    		} else if (eth_ptr->h_proto == ETHERTYPE_ARP) { //ether_type avec ether_header
    			printf("ARP\n");
    		}
    		printf("other (%d)\n", eth_ptr->h_proto);
    		printf("IP version ::: %d\n", ip_ptr->version);
    		printf("IP proto   ::: %d\n", ip_ptr->protocol); //protocole utilisé ? (TCP, UDP...)
    		printf("Adress     ::: %u.%u.%u.%u -------> %u.%u.%u.%u\n", src[0], src[1], src[2], src[3], dst[0], dst[1], dst[2], dst[3]);
    		printf("Port       ::: %d  -------> %d\n",ntohs(tcp_ptr->source), ntohs(tcp_ptr->dest));
    		printf("Flags      ::: SYN=%d | ACK=%d | RST=%d | FIN=%d\n", tcp_ptr->syn, tcp_ptr->ack, tcp_ptr->rst, tcp_ptr->fin);
     
    		printf("\n\n");
     
    	//}
     
    	return 0;
    }
    Et voici l'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    0x000000: 52 54 00 12 35 02 08 00 RT..5...
    0x000008: 27 cd 79 47 08 00 45 00 '.yG..E.
    0x000010: 00 28 ef 70 40 00 40 06 .(.p@.@.
    0x000018: 69 0a 0a 00 02 0f ad c2 i.......
    0x000020: 28 84 b6 82 00 50 f5 6f (....P.o
    0x000028: 4a a7 00 41 76 59 50 10 J..AvYP.
    0x000030: 8a 30 e2 6f 00 00       .0.o..  
    ===> Packet intercepted, 54 bytes sniffed <===
    Ethernet - proto ::: 
    other (8)
    IP version ::: 4
    IP proto   ::: 6
    Adress     ::: 10.0.2.15 -------> 173.194.40.132
    Port       ::: 46722  -------> 80
    Flags      ::: SYN=0 | ACK=1 | RST=0 | FIN=0

  6. #6
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Le code posté est incomplet, il manque hexdump (pas grave) mais il manque surtout le choix de l'interface réseau et son passage en mode promiscuous.

    Cela dit, le paquet reçu est correct car il contient bien une en-tête valide.

    Qu'est ce qui ne te conviens pas pour que tu considère la capture "sans succès" ?
    ɹǝsn *sıɹɐlos*

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 51
    Points : 55
    Points
    55
    Par défaut
    D'après la doc, je ne suis pas obligé de 'binder' une interface en particulier, mais c'est sans doute ce que je ferais par la suite.
    By default, all packets of the specified protocol type are passed to
    a packet socket. To get packets only from a specific interface use
    bind(2) specifying an address in a struct sockaddr_ll to bind the
    packet socket to an interface.
    Pour le passage en mode promiscuous, c'est prévu aussi mais pas pressé (c'est pour voir les paquets qui ne me sont pas destinés dans mon souvenir...).

    Sinon le problème vient de cette partie du code : (code modifié par rapport au post précédent, je n'avais pas changé les constantes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    printf("Ethernet - proto ::: ");
    if (eth_ptr->h_proto == ETH_P_IP) {
    	printf("IP\n");
    } else if (eth_ptr->h_proto == ETH_P_ARP) { 
    	printf("ARP\n");
    }
    printf("other (%d)\n", eth_ptr->h_proto);
    A priori je devrais surtout voir apparaître IP, mais là rien... Du coup j'affiche la valeur de h_proto (de la structure ethhdr), et la valeur 8 apparaît. Je suis allé voir le if_ether.h en question et j'utilise pourtant les bons define donc je vois pas où est le problème...

  8. #8
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Le problème, c'est que tu es sur une machine en little-endian mais Ethernet est en big-endian.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    unsigned short protocol=ntohs(eth_ptr->h_proto);
     
    if (protocol == ETH_P_IP) {
    	printf("IP\n");
    } else if (protocol == ETH_P_ARP) { 
    	printf("ARP\n");
    } else {
            printf("other (%d)\n", protocol);
    }
    ɹǝsn *sıɹɐlos*

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 51
    Points : 55
    Points
    55
    Par défaut
    Nickel !!! Un grand merci, j'ai appris quelque chose de nouveau aujourd'hui (ou alors j'avais bien bien oublié ce détail...), en tout cas ça fait plaisir.

    Bonne journée !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Classe pour la création d'un graphe xy
    Par Bob dans le forum MFC
    Réponses: 24
    Dernier message: 03/12/2009, 17h20
  2. Création dynamique de TImages
    Par Dric dans le forum C++Builder
    Réponses: 10
    Dernier message: 08/07/2002, 12h36
  3. [Kylix] Création d'un fichier lien
    Par DrQ dans le forum EDI
    Réponses: 2
    Dernier message: 14/05/2002, 21h30
  4. Création image BMP
    Par Anonymous dans le forum C
    Réponses: 2
    Dernier message: 25/04/2002, 16h04

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