/* Children 0f Decadence Sniffer. Coded by target0 Compilation : gcc -o sniffer sniffer.c -lpcap Exemple d'utilisation : ./sniffer -f "host 10.0.1.3 and port 6667" ceci "sniffera" tout les paquet en provenance ou en destination de 10.0.1.3 avec comme port 6667 ./sniffer -i ppp0 cela va ecouter sur l'interface ppp0 en capturant tous les paquets */ #include #include #include #include #include #include #define __FAVOR_BSD // on utilise les flags type BSD #include #include #include #define INTERFACE_DEFAUT "eth0" #define TAILLE_PAQUETS 1500 // taille normale d'un paquet ethernet #define RTN_OK 0 #define RTN_ERR 1 #define IP_LEN 17 #define MAC_LEN 18 #define IP_ENTETE_LEN(ip) ((ip)->ip_vhl & 0x0f) char erreur_pcap[PCAP_ERRBUF_SIZE]; void callback(u_char *, const struct pcap_pkthdr *,const u_char *); void usage (char *prog) { fprintf(stderr,"Usage: %s [-i interface] [-f \"filtre a appliquer\"]\n\n",prog); exit(RTN_ERR); } int main (int argc, char *argv[]) { u_long src_ip=0; u_long dst_ip=0; char option=0; char *interface = NULL; char *filtre = NULL; pcap_t *desc_pqt; struct bpf_program st_bpf; while((option = getopt(argc,argv,"i:f:")) != EOF) { switch(option) { case 'i': interface = strdup((const char *)optarg); break; case 'f': filtre = strdup((const char *)optarg); break; default: usage(argv[0]); break; } } // on essaye de trouver l'interface choisie if (!interface && !(interface = pcap_lookupdev(erreur_pcap))) { fprintf(stderr,"%s\n",erreur_pcap); exit(RTN_ERR); } fprintf(stdout,"Interface: %s\nFiltre: %s\n\n",interface,filtre); // on met l'interface choisie en mode PROMISCUOUS (mode écoute) if ((desc_pqt = pcap_open_live(interface,TAILLE_PAQUETS,IFF_PROMISC,1000,erreur_pcap)) == NULL) { fprintf(stderr,"%s: %s\n",interface,erreur_pcap); exit(RTN_ERR); } fprintf(stdout," > En ecoute sur l'interface %s\n",interface); // on compile le filtre if (filtre) { if (pcap_compile(desc_pqt,&st_bpf,filtre,0x100,0) < 0) { fprintf(stderr,"\"%s\" : %s\n",filtre,pcap_geterr(desc_pqt)); exit(RTN_ERR); } // on "active" le filtre if (pcap_setfilter(desc_pqt,&st_bpf) < 0) { printf("%s\n",pcap_geterr(desc_pqt)); return RTN_ERR; } fprintf(stdout," > Filtre actif\n"); } // on lance la boucle principale en utilisant la fonction callback pour le traitement des paquets if (pcap_loop(desc_pqt, -1, callback, NULL) < 0) { fprintf(stderr,"%s\n",pcap_geterr(desc_pqt)); return RTN_ERR; } return RTN_OK; } void callback(u_char *mon_param, const struct pcap_pkthdr *entete,const u_char *data) { const struct ip *paquet_ip = NULL; const struct tcphdr *paquet_tcp = NULL; const char *tcp_data = NULL; const mac_src[MAC_LEN], mac_dst[MAC_LEN]; char ip_src[IP_LEN], ip_dst[IP_LEN]; int port_src, port_dst; int rst,syn,ack,fin; u_int ip_head_len=0, tcp_head_len=0, tcp_data_len=0, tcp_data_len_reel=0; u_int taille=0; u_int off=0; // on traite la partie ETHERNET struct ether_header *entete_ethernet = (struct ether_header *)data; // on vérifie que cest bien un paquet ethernet if (!(ntohs(entete_ethernet->ether_type) == ETHERTYPE_IP)) return; // on prend les adresses mac de source et de destination strncpy ((char *)mac_src,(char *)ether_ntoa(entete_ethernet->ether_shost),MAC_LEN); strncpy ((char *)mac_dst,(char *)ether_ntoa(entete_ethernet->ether_dhost),MAC_LEN); fprintf(stdout,"\nMac_Src : %s\nMac_Dst : %s\n",mac_src,mac_dst); // on traite la partie IP taille = (entete->caplen - sizeof(struct ether_header)); if (taille < sizeof(struct ip)) { fprintf(stderr,"Erreur paquet tronque, partie IP incomplete\n"); return; } paquet_ip = (struct ip *)(data + sizeof(struct ether_header)); // on prend les adresses IP de source et de destination strncpy(ip_src,(char *)inet_ntoa(paquet_ip->ip_src),IP_LEN); strncpy(ip_dst,(char *)inet_ntoa(paquet_ip->ip_dst),IP_LEN); fprintf(stdout,"Ip_Src : %s\nIp_Dst : %s\n",ip_src,ip_dst); ip_head_len = paquet_ip->ip_hl * 4; if (ip_head_len < sizeof(struct ip)) { fprintf(stderr,"Erreur longueur entete ip\n"); return; } // on traite la partie TCP off = ntohs(paquet_ip->ip_off); // si c'est bien un paquet TCP on continue if(!(off & 0x1fff) && (paquet_ip->ip_p == IPPROTO_TCP)) { taille = (entete->caplen - sizeof(struct ether_header) - ip_head_len); if (taille < sizeof(struct tcphdr)) { fprintf(stderr,"Erreur paquet tronque, partie TCP incomplete\n"); return; } paquet_tcp = (const struct tcphdr *)(data + sizeof(struct ether_header) + ip_head_len); // on prend les ports de source et de destination port_src = ntohs(paquet_tcp->th_sport); port_dst = ntohs(paquet_tcp->th_dport); tcp_head_len = paquet_tcp->th_off*4; fprintf(stdout,"Src_Port : %d\nDst_Port : %d\n",port_src,port_dst); // on prend les flags activé sur le paquet if (paquet_tcp->th_flags & TH_RST) rst=1; else rst=0; if (paquet_tcp->th_flags & TH_FIN) fin=1; else fin=0; if (paquet_tcp->th_flags & TH_SYN) syn=1; else syn=0; if (paquet_tcp->th_flags & TH_ACK) ack=1; else ack=0; // oui je sais c'est mal codé :) fprintf(stdout,"Flags: "); if (rst) { fprintf(stdout,"RST "); } if (fin) { fprintf(stdout,"FIN "); } if (syn) { fprintf(stdout,"SYN "); } if (ack) { fprintf(stdout,"ACK "); } fprintf(stdout,"\n"); tcp_data_len = entete->caplen - (sizeof(struct ether_header) + ip_head_len + tcp_head_len); tcp_data_len_reel = entete->len - (sizeof(struct ether_header) + ip_head_len + tcp_head_len); if (tcp_data_len>0) { fprintf(stdout,"TOTAL DATA : %u\n",tcp_data_len); // on prend les données du paquet tcp_data = (const char *)(data + sizeof(struct ether_header) + ip_head_len + tcp_head_len); } fprintf(stdout,"%s\n",tcp_data); } else if (!(off & 0x1fff) && (paquet_ip->ip_p == IPPROTO_UDP)) { // quelle bete idée d'utiliser UDP... fprintf(stdout,"Protocole UDP non pris en charge\n"); fflush(stdout); } else { // c'est quoi ce protocole ?? :/ fprintf(stdout,"Protocole inconnu\n"); fflush(stdout); } }