/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Le Scanning d'IP par requête ICMP Echo /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// L'ICMP Echo ----------- L'ICMP (Internet Control Message Protocol) permet d'envoyer des messages de contrôles (notamment lorsqu'une route est fermée il nous le dit). Je pourrais m'étendre plus avant ici sur le protocole ICMP mais ce n'est pas le sujet de plus il y a de très bon articles dessus (notamment celui de feu CoD4 dans NoRoute 3). Je vais simplement expliquer ici le message echo et echo reply. 0 7|8 15|16 31 |------------------------------------------------------------------------------| | type (0 ou 8) | code (0) | checksum | |------------------------------------------------------------------------------| | identificateur | numéro de séquence | |------------------------------------------------------------------------------| | données optionnelles (s'il y en a) | |------------------------------------------------------------------------------| Donc un message ICMP Echo request est identifié par le type 8 et le code 0. L'identificateur est là pour identifier l'échange echo et le numéro de séquence pour dire à quel paquet on est (c'est le champ icmp_seq lors d'un ping). A un message echo est normalement renvoyé un message echo reply identifié par le type 0 et le code 0 avec les mêmes champs que le message echo (numéro d'identification et de séquence). Faire de l'ip scanning par message ICMP Echo -------------------------------------------- Le principe est simple pour chaque ip on envoie un paquet echo et on attend un paquet echo reply avec les mêmes champs. On récupèrera un paquet icmp unreacheable (destination indisponible) si l'hôte n'existe pas et un time out s'il est indisponible. Ainsi on peut scanner une série d'ip assez rapidement. Voilà le code des fonctions réalisant le ping dans l'IP-scan de la RtC : (le code entier est dispo sur le site de la RtC TecH) PS : au fait, pour ceux que cela interresse, j'ai intégré bd.c dans le prog ping (IDEM que le code de l'IP-Scan). <-- begin icmpping.c --> /****************************************************************************** * icmpping.c by S/asH (member of RtC) * * IP Scanning - ICMP Ping Request * * This is a tOOl of RtC TecH * ******************************************************************************/ #include "rtcipscan.h" /****************************************************************************** * in_chksum -- * * Checksum routine for Internet Protocol family headers (C Version) * ******************************************************************************/ unsigned short in_chksum(addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } /****************************************************************************** * send_icmp_echo -- Send an icmp echo request * * Input : sock : socket descriptor * * dest : destination address * * ident : icmp ident * * seq_nb : icmp sequence number * * data : optional data * * sdata : size of data * * Output : return : success or failed * ******************************************************************************/ int send_icmp_echo(int sock, struct sockaddr_in dest, u_short ident, u_short seq_nb, char *data, int sdata) { char packet[2048]; struct icmphdr *icmp = (struct icmphdr*)packet; unsigned char *datagram = (unsigned char*)(packet + 8); /* making the icmp header */ memcpy(datagram, data, sdata); memset(packet, 0, 8); icmp->type = ICMP_ECHO; icmp->code = 0; icmp->un.echo.id = ident; icmp->un.echo.sequence = seq_nb; /* calculate the checksum */ icmp->checksum = in_chksum((u_short*)packet, sdata+8); return sendto(sock, packet, 8+sdata, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr)); } /****************************************************************************** * ping -- Send an icmp echo request and stand the reply * * Input : sock : socket descriptor * * dest : destination address * * timeout : time out for echo request * * packsize : size of packet to send * * ident : icmp ident * * seq_nb : icmp sequence number * * Output : return : see section 'ping return values' in rtcipscan.h * ******************************************************************************/ int ping(int sock, struct sockaddr_in dest, int timeout, int packsize, u_short ident, u_short seq_nb) { int rc; fd_set rset; struct timeval cur_time, beg_time, tv; char buf[2048]; struct iphdr *ip = (struct iphdr *) (buf); struct icmphdr *icmp = (struct icmphdr*)(buf + sizeof(struct iphdr)); for(rc=0; rc DIFFTIME(beg_time, cur_time)) { if ((rc=select(sock + 1, &rset, NULL, NULL, &tv)) == 0) return HOST_TIMEDOUT; /* time out */ else if (rc < 0) return PING_ERROR; else { rc = read(sock,buf,2048); if(rc==-1) return PING_ERROR; /* error in reading */ else if(rc>0) { if (ip->saddr == dest.sin_addr.s_addr) /* got a reply */ { if((icmp->type == ICMP_ECHOREPLY) && (icmp->un.echo.id == ident) && (icmp->un.echo.sequence == seq_nb)) return HOST_ANSWER; } else if(icmp->type == ICMP_DEST_UNREACH) return HOST_UNREACHABLE; gettimeofday(&cur_time, NULL); } } } return HOST_TIMEDOUT; /* time out */ } <-- end icmpping.c --> <-- File by S/asH --> [EOF]