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 C Discussion :

[RAW SOCKET] Forger son propre packet ICMP (pour "pinge


Sujet :

Réseau C

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut [RAW SOCKET] Forger son propre packet ICMP (pour "pinge
    Bonjour à tous

    Je m'initie aux joies aux combien palpitantes des RAW SOCKET sous Linux (compilateur gcc). Comme exercice je me suis dis "Et si je recréait la fonction ping", alors ce fut le début de mes longues péripéties

    Vacant de site internet en forum je me décide à poster mon code -qui ne marche pas- ici.

    Voici mon zouli code :

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    #include <stdio.h>
     
    #include <linux/ip.h>
    #include <linux/icmp.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
     
     unsigned short in_cksum&#40;unsigned short *addr, int len&#41;
            &#123;
                register int sum = 0;
                u_short answer = 0;
                register u_short *w = addr;
                register int nleft = len;
     
                while &#40;nleft > 1&#41;
                  &#123;
                      sum += *w++;
                      nleft -= 2;
                  &#125;
     
                if &#40;nleft == 1&#41;
                  &#123;
                      *&#40;u_char *&#41; &#40;&answer&#41; = *&#40;u_char *&#41; w;
                      sum += answer;
                  &#125;
     
                sum = &#40;sum >> 16&#41; + &#40;sum & 0xffff&#41;;       
                sum += &#40;sum >> 16&#41;;         
                answer = ~sum;           
                return &#40;answer&#41;;
          &#125;
     
    int main&#40;&#41;&#123;
     
            int sock, optval;
            char *packet, *buffer;
     
            struct icmphdr *icmp;
     
            struct sockaddr_in peer;
            struct iphdr *ip;
     
     
            ip = &#40;struct iphdr *&#41; malloc&#40;sizeof&#40;struct iphdr&#41;&#41;;
            icmp     = &#40;struct icmphdr *&#41; malloc&#40;sizeof&#40;struct icmphdr&#41;&#41;;
            packet  = &#40;char *&#41; malloc&#40;sizeof&#40;struct iphdr&#41; + sizeof&#40;struct icmphdr&#41;
    &#41;;
            buffer  = &#40;char *&#41; malloc&#40;sizeof&#40;struct iphdr&#41; + sizeof&#40;struct icmphdr&#41;
    &#41;;
     
     
            ip = &#40;struct iphdr *&#41; packet;
            icmp = &#40;struct icmphdr *&#41; &#40;packet + sizeof&#40;struct iphdr&#41;&#41;;
     
     
            ip->ihl     = 5;
            ip->version = 4;
            ip->tos     = 0;
            ip->tot_len = sizeof&#40;struct iphdr&#41; + sizeof&#40;struct icmphdr&#41;;
            ip->id      = htons&#40;getuid&#40;&#41;&#41;;
            ip->ttl      = 255;
            ip->protocol = IPPROTO_ICMP;
            ip->saddr    = inet_addr&#40;"127.0.0.1"&#41;;
            ip->daddr    = inet_addr&#40;"127.0.0.1"&#41;;
     
     
            sock = socket&#40;AF_INET,SOCK_RAW,IPPROTO_ICMP&#41;;
            setsockopt&#40;sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof&#40;int&#41;&#41;;
     
            icmp->type = ICMP_ECHO;
            icmp->code = 0;
            icmp->un.echo.id = 0;
            icmp->un.echo.sequence = 0;
            icmp->checksum = 0;
     
            icmp->checksum = in_cksum&#40;&#40;unsigned short *&#41;icmp,sizeof&#40;struct icmphdr&#41;
    &#41;;
     
            ip->check    = in_cksum&#40;&#40;unsigned short *&#41;ip, sizeof&#40;struct iphdr&#41;&#41;;
     
     
     
            peer.sin_family = AF_INET;
            peer.sin_addr.s_addr = inet_addr&#40;"127.0.0.1"&#41;;
     
            sendto&#40;sock,packet,ip->tot_len,0,&#40;struct sockaddr *&#41;&peer,sizeof&#40;struct
     sockaddr&#41;&#41;;
     
            recv&#40;sock,buffer,sizeof&#40;struct iphdr&#41;+sizeof&#40;struct icmphdr&#41;,0&#41;;
            printf&#40;"Received the ECHO REPLY\n"&#41;;
     
            close&#40;sock&#41;;
            return 0;
    &#125;
    A la question "en quoi mon code plante" je répondrais que le packet icmp n'est pas correctement forgé.

    En effet en lançant le programme avec un tcpdump -i lo -X dans une autre console le packet forgé ne ressemble en rien à un packet classique de ping (il est même indiqué "h-len error" ou quelque'chose de similaire).

    Ou ais-je péché ?


    PS : je précise que ce n'est pas tout a fait mon code. Ce qui change dans le mien ce sont les ips qui ne sont pas des variables entre "" mais des variables à proprement parlé (char * IP).
    PS2 : comme ce code me fait l'erreur quand même je me dis que ca ne viens pas de moi


    Merci à toutes les âmes aventureuses qui oseront remonter des tréfonds de l'abysse des bugs de mon code les quelques monstres qui s'y cache

    PS 3: je prends tout ca avec humour parce'que je pense que la prochaine étape est la suppression physique du PC

  2. #2
    zul
    zul est déconnecté
    Membre éclairé Avatar de zul
    Profil pro
    Inscrit en
    juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2002
    Messages : 498
    Points : 697
    Points
    697
    Par défaut
    g pas verifié tout le code mais l'erreur me semble venir de la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     sock = socket&#40;AF_INET,SOCK_RAW,IPPROTO_ICMP&#41;;
    qui devrait plutot etre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sock = socket&#40;AF_INET,SOCK_RAW,IPPROTO_RAW&#41;;
    Il faudrait tester le retour de setsockopt aussi, ca peut venir de la .

    ZUL

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    setsockopt me renvoie 0 donc ca marche.
    J'ai changé ce que tu as dis mais le packet est inchangé.

    Je paste ici le résultats obtenus avec le sniff pour vous montrer la différence entre les 2 packets :

    Mon packet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    0x0000	 4000 001c b4b4 0000 ff01 4000 7f00 0001	@.........@.....
    0x0010	 7f00 0001 0800 f7ff 0000 0000          	............
    Un packet ICMP :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    0x0000	 4500 0054 0000 4000 4001 3ca7 7f00 0001	E..T..@.@.<.....
    0x0010	 7f00 0001 0800 bd0d 3e01 0000 51f0 383f	........>...Q.8?
    0x0020	 81be 0600 0809 0a0b 0c0d 0e0f 1011 1213	................
    0x0030	 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223	.............!"#
    0x0040	 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233	$%&'&#40;&#41;*+,-./0123
    0x0050	 3435                                   	45
    Grosse différence même si on détecte sur le début quelques points communs.

    Une idée ?


    Merci,

    Yabo.

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Bon il est 4h du mat je viens de passer toute ma journée à écumer le net à la recherche de docs sur le protocole ICMP et mon code pour moi est correct !


    J'en peux plus là

    Vais dodo

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    J'ai trouvé !!!!

    Je mets le code si ca interesse quelqu'un

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
     
    #include <stdio.h>
     
    #include <linux/ip.h>
    #include <linux/icmp.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
     
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
     
    extern int errno;
    extern int h_errno;
    extern int Verbose;
     
    struct ipheader
    &#123;
    	unsigned char ip_hl&#58;4,ip_v&#58;4;
    	unsigned char ip_tos;
    	unsigned short int ip_len;
    	unsigned short int ip_id;
    	unsigned short int ip_off;
    	unsigned char ip_ttl;
    	unsigned char ip_p;
    	unsigned short int ip_sum;
    	unsigned int ip_src;
    	unsigned int ip_dst;
    &#125;;
     
    struct icmpheader
    &#123;
    	unsigned char icmp_type;
    	unsigned char icmp_code;
    	unsigned short int icmp_cksum;
    	unsigned short int icmp_id;
    	unsigned short int icmp_seq;
    &#125;;
     
    unsigned short in_cksum&#40;unsigned short * addr,int len&#41;
    &#123;
    	register int sum     = 0;
    	u_short answer       = 0;
    	register u_short * w = addr;
    	register int nleft   = len;
     
    	while&#40;nleft > 1&#41;
    	&#123;
    		sum += *w++;
    		nleft -= 2;
    	&#125;
     
    	if&#40;nleft == 1&#41;
    	&#123;
    		*&#40;u_char *&#41;&#40;&answer&#41; = *&#40;u_char *&#41; w;
    		sum += answer;
    	&#125;
     
    	sum = &#40;sum >> 16&#41; + &#40;sum & 0xffff&#41;;
     
    	sum += &#40;sum >> 16&#41;;
    	answer = ~sum;
     
    	return answer;
    &#125;
     
    char *GetLocalIP&#40;&#41;
    &#123;
    	struct hostent * Host = gethostbyname&#40;&#40;char *&#41;getenv&#40;"HOSTNAME"&#41;&#41;;
    	if&#40;Host == NULL&#41;
    		return "0.0.0.0";
    	char ** adr = Host->h_addr_list;
    	return &#40;char *&#41;inet_ntoa&#40;*&#40;struct in_addr *&#41; *adr&#41;;
    &#125;
     
    int Ping&#40;char * IP&#41;
    &#123;
    	int sock,optval;
    	char *packet,*buffer;
     
    	struct icmpheader * icmp;
     
    	struct sockaddr_in peer;
    	struct ipheader * ip;
     
    	ip     = &#40;struct ipheader *&#41; malloc&#40;sizeof&#40;struct ipheader&#41;&#41;;
    	icmp = &#40;struct icmpheader *&#41; malloc&#40;sizeof&#40;struct icmpheader&#41;&#41;;
    	packet = &#40;char *&#41;	    malloc&#40;sizeof&#40;struct iphdr&#41; + sizeof&#40;struct icmphdr&#41;&#41;;
    	buffer = &#40;char *&#41;	    malloc&#40;sizeof&#40;struct iphdr&#41; + sizeof&#40;struct icmphdr&#41;&#41;;
     
    	ip   = &#40;struct ipheader *&#41; packet;
    	icmp = &#40;struct icmpheader *&#41; &#40;packet + sizeof&#40;struct ipheader&#41;&#41;;
     
    	if&#40;Verbose&#41;
    		printf&#40;"Creating IP header &#58; "&#41;;
     
    	ip->ip_hl = 5;
    	ip->ip_v  = 4;
    	ip->ip_tos = 0;
    	ip->ip_len = sizeof&#40;struct ipheader&#41; + sizeof&#40;struct icmpheader&#41;;
    	ip->ip_id = htonl&#40;54321&#41;;
    	ip->ip_off = 0;
    	ip->ip_ttl = 255;
    	ip->ip_p = IPPROTO_ICMP;
    	ip->ip_sum = 0;
    	char * IpSrc = &#40;char *&#41; malloc&#40;32*sizeof&#40;char&#41;&#41;;
    	strcpy&#40;IpSrc,&#40;char *&#41;GetLocalIP&#41;;
    	if&#40;strstr&#40;IpSrc,"0.0.0.0"&#41;&#41;
    	&#123;
    		if&#40;Verbose&#41;
    			printf&#40;"FAILED &#40;unable to resolve local IP&#41;\n"&#41;;
    		return -1;
    	&#125;
    	ip->ip_src = inet_addr&#40;IpSrc&#41;;
    	ip->ip_dst = inet_addr&#40;IP&#41;;
     
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK\n"&#41;;
    		printf&#40;"Creating socket &#58; "&#41;;
    	&#125;
    	sock = socket&#40;AF_INET,SOCK_RAW,IPPROTO_ICMP&#41;;
    	if&#40;sock == -1&#41;
    	&#123;
    		if&#40;Verbose&#41;
    			printf&#40;"FAILED &#40;%s&#41;\n",strerror&#40;errno&#41;&#41;;
    		return -1;
    	&#125;
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK\n"&#41;;
    		printf&#40;"Setting socket options &#58; "&#41;;
    	&#125;
    	int ret = setsockopt&#40;sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof&#40;int&#41;&#41;;
    	if&#40;ret != 0&#41;
    	&#123;
    		if&#40;Verbose&#41;
    			printf&#40;"FAILED &#40;%s&#41;\n",strerror&#40;errno&#41;&#41;;
    		return -1;
    	&#125;
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK\n"&#41;;
    		printf&#40;"Creating ICMP header &#58; "&#41;;
    	&#125;
     
    	icmp->icmp_type = 8;
    	icmp->icmp_code = 0;
    	icmp->icmp_cksum = 0;
    	icmp->icmp_cksum = in_cksum&#40;&#40;unsigned short *&#41;icmp,sizeof&#40;struct icmpheader&#41;&#41;;
    	icmp->icmp_id = 0;
    	icmp->icmp_seq = 0;
     
    	peer.sin_family = AF_INET;
    	peer.sin_addr.s_addr = inet_addr&#40;IP&#41;;
     
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK\n"&#41;;
    		printf&#40;"Sending ICMP packet &#58; "&#41;;
    	&#125;
     
    	int j = 0;
     
    	int Start = clock&#40;&#41;/1000;
    	ret = sendto&#40;sock,packet,ip->ip_len,0,&#40;struct sockaddr *&#41;&peer,sizeof&#40;struct sockaddr&#41;&#41;;
    	if&#40;ret != ip->ip_len&#41;
    	&#123;
    		if&#40;Verbose&#41;
    			printf&#40;"FAILED &#40;not all packet sent&#41;\n"&#41;;
    		return -1;
    	&#125;
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK\n"&#41;;
    		printf&#40;"Waiting for ICMP reply &#58; "&#41;;
    	&#125;
    	ret = recv&#40;sock,buffer,sizeof&#40;struct ipheader&#41;+sizeof&#40;struct icmpheader&#41;,0&#41;;
    	if&#40;ret != &#40;sizeof&#40;struct ipheader&#41;+sizeof&#40;struct icmpheader&#41;&#41;&#41;
    	&#123;
    		if&#40;Verbose&#41;
    		&#123;
    			printf&#40;"FAILED &#40;ICMP packet received but may be corrupted &#40;didn't receive expected size&#41;&#41;\n"&#41;;
    			printf&#40;"Just going on ...\n"&#41;;
    		&#125;
    	&#125;
    	int End = clock&#40;&#41;/1000;
     
    	if&#40;Verbose&#41;
    	&#123;
    		printf&#40;"OK &#40;%d ms&#41;\n",End-Start&#41;;
    	&#125;
    	close&#40;sock&#41;;
     
    	return End-Start;
    &#125;

    Bon mais pour l'utiliser sous linux il faut absolument être root pour les raw socket.

    Y-a-t-il un moyen de faire une requète ICMP sans être root ???

    Merci à tous

    Yabo.

  6. #6
    Membre émérite

    Homme Profil pro
    Inscrit en
    juillet 2003
    Messages
    2 075
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations forums :
    Inscription : juillet 2003
    Messages : 2 075
    Points : 2 797
    Points
    2 797
    Par défaut
    Pardon Yabo tu peux indiquer les docs que
    tu as lues ou suivies?
    Merci

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Pour pondre le dernier code j'ai utilisé :
    man ip
    man icmp
    man socket

    Et j'ai passé beaucoup beaucoup d'heures à essaier différents trucs tout seul le soir dans ma chambre sur mon portable et j'y suis arrivé

    Et comme tu vois j'ai en fait redéfini les structures d'entète IP et ICMP ce qui fait que maintenant ca marche à merveille

  8. #8
    zul
    zul est déconnecté
    Membre éclairé Avatar de zul
    Profil pro
    Inscrit en
    juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2002
    Messages : 498
    Points : 697
    Points
    697
    Par défaut
    Reste que c'est pas normal . Il est en effet anormal de devoir redefinir les structures rezo pour que le code marche. Enfin je dis pas parce que g un bleme avec mes includes aussi .

    Autre question, normalement tu devrais plutot utiliser recvfrom plutot que recv()

    Enfin tu peux utiliser ping en simple utilisateur si tu lui met le flag setuid. Un utilisateur normal pourra le lancer mais le programme aura les droits roots, dc pourra utiliser les raw sock. Attention, c tres gentil mais si le programme a une faille, c root assuré pour l'aggresseur . Il convient dc d'utiliser le moins possible ce flag et d'auditer tous les codes l'utilisant.

    ZUL

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Ben oui je suis tout a fait d'accord. En fait je crois que les vrais structures sont bonnes seulement je n'ai trouvé nul part leur définition donc je n'ai pas pu avoir le nom de tout les membres. Car je ne sais pas si vous avez vu mais entre les 2 codes j'ai quelques champs en plus dans le 2nd et l'ordre de remplissage n'est pas le même.

    Mais bon tant que ca marche ...


    Et pour le flag setuid oki je vais me renseigner. Et pour la faille de sécurité euh comme c'est une appli de type scanner/sniffer réseau elles n'est pas lancée en permanence donc ca va


    Bon allez je me tente une dernière chtite question

    Il faut que je me fasse un timeout sur le recv car ousinon il peut attendre indéfiniment si l'ip n'est pas joignable. Donc j'ai d'abord pensé à un
    setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,
    sizeof(timeout));
    avec int timeout = 5; //5 secondes ?

    Mais apparemment il ne veux pas prendre 2 setsockopt à la suite. A la compilation ca marche bien mais j'ai une erreur sur le setsockopt.
    Donc en cherchant sur le forum j'ai vu que souvent a ce type de question on avait répondu "il faut utiliser select" mais je vois pas trop comment

    Donc si quelqu'un à un exemple tout simple (en socket normal) avec utilisation d'un select style pour attendre 5 secondes je lui en serait gré

    Merci à tous,

    Yabo.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    juin 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2003
    Messages : 71
    Points : 78
    Points
    78
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    fd_set socks;
    FD_ZERO&#40;&socks&#41;;
    FD_SET&#40;sRecvSock, &socks&#41;; //sRecvSock &#58; le socket dont tu attends les infos
    timeval tv = &#123;5, 0&#125;; //5 secondes
    select&#40;0, &socks, NULL, NULL, &tv&#41;; //blocking call, 5 secondes
    if  &#40; FD_ISSET&#40;sRecvSock, &socks&#41; &#41;
    &#123;
    //le client a répondu sous 5 secondes
    &#125;
    else
    &#123;
    //le client n'a pas répondu sous 5 secs
    &#125;

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Merci c'est exactement ce que je cherchais !

    Topic résolu,

    merci beaucoup à tous ceux qui y ont participé

    Yabo.

  12. #12
    zul
    zul est déconnecté
    Membre éclairé Avatar de zul
    Profil pro
    Inscrit en
    juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2002
    Messages : 498
    Points : 697
    Points
    697
    Par défaut
    Bon desolé de bumper un sujet resolu mais
    1/ recvfrom ca marche mieux
    2/ pas bien tu libére pas ta memoire
    3/ ton premier code marche chez moi (apres trifatouillage pour passer de linux a netbsd .

    JE te donne le code qui marche chez moi ( il ya quelque modif quand meme)

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
     
    #include <stdio.h>
    #include <errno.h> 
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/in_systm.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    #include <netinet/ip.h> 
    #include <netinet/ip_icmp.h> 
     
     unsigned short in_cksum&#40;unsigned short *addr, int len&#41; 
            &#123; 
                register int sum = 0; 
                u_short answer = 0; 
                register u_short *w = addr; 
                register int nleft = len; 
     
                while &#40;nleft > 1&#41; 
                  &#123; 
                      sum += *w++; 
                      nleft -= 2; 
                  &#125; 
     
                if &#40;nleft == 1&#41; 
                  &#123; 
                      *&#40;u_char *&#41; &#40;&answer&#41; = *&#40;u_char *&#41; w; 
                      sum += answer; 
                  &#125; 
     
                sum = &#40;sum >> 16&#41; + &#40;sum & 0xffff&#41;;        
                sum += &#40;sum >> 16&#41;;          
                answer = ~sum;            
                return &#40;answer&#41;; 
          &#125; 
     
    int main&#40;&#41;&#123; 
     
            int sock, optval,test; 
            int i;
            char *packet, *buffer; 
     
            struct ip *hip; 
            struct icmp * hicmp;
     
            struct sockaddr_in peer;
            struct sockaddr_in mine;
     
            packet  = &#40;char *&#41; malloc&#40;sizeof&#40;struct ip&#41; + sizeof&#40;struct icmp&#41; 
    &#41;; 
            buffer  = &#40;char *&#41; malloc&#40;sizeof&#40;struct ip&#41; + sizeof&#40;struct icmp&#41; 
    &#41;; 
     
            hip = &#40;struct ip *&#41; packet; 
            hicmp = &#40;struct icmp *&#41; &#40;packet + sizeof&#40;struct ip&#41;&#41;; 
     
            peer.sin_family = AF_INET; 
            peer.sin_addr.s_addr = inet_addr&#40;"19.54.154.14"&#41;; 
     
            mine.sin_family=AF_INET;
            mine.sin_addr.s_addr = inet_addr&#40;GetMyIp&#40;&#41;&#41;;
            hip->ip_hl   = 5; 
            hip->ip_v = 4; 
            hip->ip_tos   = 0; 
            hip->ip_len = sizeof&#40;struct ip&#41; + sizeof&#40;struct icmp&#41;; 
            hip->ip_id      = htons&#40;getuid&#40;&#41;&#41;; 
            hip->ip_ttl      = 255;
            hip->ip_src    = peer.sin_addr;
            hip->ip_dst    = mine.sin_addr;
     
            printf&#40;"len &#58; %d\n",hip->ip_len&#41;;
     
            sock = socket&#40;AF_INET,SOCK_RAW,IPPROTO_ICMP&#41;; 
            setsockopt&#40;sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof&#40;int&#41;&#41;; 
     
            hicmp->icmp_type = ICMP_ECHO; 
            hicmp->icmp_code = 0; 
            hicmp->icmp_cksum = 0; 
     
            hicmp->icmp_cksum = in_cksum&#40;&#40;unsigned short *&#41;hicmp,sizeof&#40;struct icmp&#41; 
    &#41;; 
     
            hip->ip_sum    = in_cksum&#40;&#40;unsigned short *&#41;hip, sizeof&#40;struct ip&#41;&#41;; 
     
            for &#40; i=0; i < hip->ip_len;i++&#41;
             printf&#40;"%.2X ",*&#40;packet+i&#41;&#41;;
     
           test=sendto&#40;sock,packet,hip->ip_len,0,&#40;struct sockaddr *&#41;&peer,sizeof&#40;struct  sockaddr&#41;&#41;;
            if &#40;test != hip->ip_len&#41;
                printf&#40;"A envoyé %d octets au lieu de %d octects
    \n",test,hip->ip_len&#41;; 
            if &#40;test <= 0&#41;
                perror&#40;"Erreur sendto&#40;&#41;"&#41;;
     
          test= recvfrom&#40;sock,buffer,sizeof&#40;struct ip&#41;+sizeof&#40;struct icmp&#41;,0,&#40;struct sockaddr *&#41;&peer,sizeof&#40;struct  sockaddr&#41;&#41;; 
        if &#40;test == &#40;sizeof&#40;struct ip&#41;+sizeof&#40;struct icmp&#41;&#41;&#41;    
        printf&#40;"Received the ECHO REPLY\n"&#41;; 
     
        for &#40;i = 0; i <=  &#40;sizeof&#40;struct ip&#41;+sizeof&#40;struct icmp&#41;&#41;;i++&#41;
              printf&#40;"%.2X ",*&#40;packet+i&#41;&#41;;
             printf&#40;"\n"&#41;;
     
            close&#40;sock&#41;;
            free&#40;packet&#41;;
            free&#40;buffer&#41;;
            return 0;
    &#125;
    ZUL

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Ben oui je sais c'était un code un peu brouillon j'ai pas mal retravaillé dessus.

    Ben c'est cool je vais regarder ton code mais à première vue je vois pas les gros changements hormis le recvfrom() (que j'ai intégré moi aussi :p)

  14. #14
    Membre du Club
    Inscrit en
    juillet 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : juillet 2006
    Messages : 113
    Points : 65
    Points
    65
    Par défaut ping avec les socket raw
    bonjour,

    en effet mon projet est de crée des socket raw ou je vais mettre les donnees dans les chanp de numero de sequence (donnee caches) avec des paquet "TCP SYN). mais d'apres ce que j'ai trouve sur internet; Avec freeBSD on ne peut pas recevoire des socket raw en TCP. Mais avec ICMP on peut (ou plutôt seulement les echo request ,si je me rappel bien). j'ai testé votre programe sa compile mais avec ethereal sa envoie aucun paquets . c'est bizar car vous avez dit que ça marche chez toi (dans un des sujet de forum
    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
     
    #include <stdio.h>
    #include <errno.h> 
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/in_systm.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    #include <netinet/ip.h> 
    #include <netinet/ip_icmp.h> 
     
     unsigned short in_cksum(unsigned short *addr, int len) 
            { 
                register int sum = 0; 
                u_short answer = 0; 
                register u_short *w = addr; 
                register int nleft = len; 
     
                while (nleft > 1) 
                  { 
                      sum += *w++; 
                      nleft -= 2; 
                  } 
     
                if (nleft == 1) 
                  { 
                      *(u_char *) (&answer) = *(u_char *) w; 
                      sum += answer; 
                  } 
     
                sum = (sum >> 16) + (sum & 0xffff);        
                sum += (sum >> 16);          
                answer = ~sum;            
                return (answer); 
          } 
     
    int main(){ 
     
            int sock, optval,test; 
            int i;
            char *packet, *buffer; 
     
            struct ip *hip; 
            struct icmp * hicmp;
     
            struct sockaddr_in peer;
            struct sockaddr_in mine;
     
            packet  = (char *) malloc(sizeof(struct ip) + sizeof(struct icmp) 
    ); 
            buffer  = (char *) malloc(sizeof(struct ip) + sizeof(struct icmp) 
    ); 
     
            hip = (struct ip *) packet; 
            hicmp = (struct icmp *) (packet + sizeof(struct ip)); 
     
            peer.sin_family = AF_INET; 
            peer.sin_addr.s_addr = inet_addr("19.54.154.14"); 
     
            mine.sin_family=AF_INET;
            mine.sin_addr.s_addr = inet_addr(GetMyIp());
            hip->ip_hl   = 5; 
            hip->ip_v = 4; 
            hip->ip_tos   = 0; 
            hip->ip_len = sizeof(struct ip) + sizeof(struct icmp); 
            hip->ip_id      = htons(getuid()); 
            hip->ip_ttl      = 255;
            hip->ip_src    = peer.sin_addr;
            hip->ip_dst    = mine.sin_addr;
     
            printf("len : %d\n",hip->ip_len);
     
            sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); 
            setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); 
     
            hicmp->icmp_type = ICMP_ECHO; 
            hicmp->icmp_code = 0; 
            hicmp->icmp_cksum = 0; 
     
            hicmp->icmp_cksum = in_cksum((unsigned short *)hicmp,sizeof(struct icmp) 
    ); 
     
            hip->ip_sum    = in_cksum((unsigned short *)hip, sizeof(struct ip)); 
     
            for ( i=0; i < hip->ip_len;i++)
             printf("%.2X ",*(packet+i));
     
           test=sendto(sock,packet,hip->ip_len,0,(struct sockaddr *)&peer,sizeof(struct  sockaddr));
            if (test != hip->ip_len)
                printf("A envoyé %d octets au lieu de %d octects
    \n",test,hip->ip_len); 
            if (test <= 0)
                perror("Erreur sendto()");
     
          test= recvfrom(sock,buffer,sizeof(struct ip)+sizeof(struct icmp),0,(struct sockaddr *)&peer,sizeof(struct  sockaddr)); 
        if (test == (sizeof(struct ip)+sizeof(struct icmp)))    
        printf("Received the ECHO REPLY\n"); 
     
        for (i = 0; i <=  (sizeof(struct ip)+sizeof(struct icmp));i++)
              printf("%.2X ",*(packet+i));
             printf("\n");
     
            close(sock);
            free(packet);
            free(buffer);
            return 0;
    }
     
    ZUL
    je ne sait pas ça peut etre quoi le probleme?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     mine.sin_addr.s_addr = inet_addr(GetMyIp());
    peer.sin_addr.s_addr = inet_addr("19.54.154.14");
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mine.sin_addr.s_addr = inet_addr("b.a.f.e);
    peer.sin_addr.s_addr = inet_addr("w.F.T.E");
    comme address destination et source.

  15. #15
    Futur Membre du Club
    Inscrit en
    septembre 2006
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : septembre 2006
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Bonjour

    Je me permets de poster dans ce sujet pour demander s'il existe une alternative aux paquets RAW pour faire des pings sous Linux?

    En effet mon programme sous Windows utilise l'API ICMP de Microsoft pour envoyer les pings, ça fonctionne aussi en mode utilisateur. Sous linux je vais devoir refaire le même soft mais qui tourne aussi uniquement en mode utilisateur sans intervention d'admin (setuid), je cherche donc une méthode pour me passer des paquets RAW...

    Merci

  16. #16
    Futur Membre du Club
    Inscrit en
    septembre 2006
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : septembre 2006
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Vu que je n'ai pas eu de réponse, je voulais quand même vous demander si à votre avis la réception de la réponse à une requête ARP a la même importance que la réponse à un paquet ICMP, sachant que c'est pour tester la connectivité d'une machine distante?
    Merci

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

Discussions similaires

  1. Créer son propre serveur http pour JWS
    Par romain.barraud dans le forum JWS
    Réponses: 0
    Dernier message: 10/06/2009, 09h45
  2. sendto + création de paquet pour les raw socket
    Par poporiding dans le forum C++
    Réponses: 1
    Dernier message: 28/07/2006, 13h19
  3. Outil pour construire son propre framework
    Par maximenet dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 5
    Dernier message: 08/06/2006, 14h02
  4. Créer son propre éditeur pour un descendant de tpopupmenu
    Par sfpx dans le forum Composants VCL
    Réponses: 1
    Dernier message: 04/10/2005, 12h21

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