/* Name: PacketSniffer Author: dew Date: 09/05/03 23:49 Description: Yet another Packet Sniffer */ #include #include #include #include #include "main.h" FILE *f; /* Fonctions d'analyse */ /* Analyse du type ethernet */ char *analyze_ether_type(u_short type) { switch(type) { case ETHERTYPE_IP: return "(IPv4) "; break; case ETHERTYPE_ARP: return "(ARP) "; break; case ETHERTYPE_RARP: return "(RARP) "; break; default: return "(Unknown)"; } } /* Analyse du type de protocole IP */ char *analyze_ip_proto(u_char type) { switch(type) { case 1: return " ICMP"; break; case 2: return " IGMP"; break; case 6: return " TCP"; break; case 17: return " UDP"; break; case 37: return " RDP"; break; case 41: return " IPv6"; break; default: return " ?"; } } /* Analyse du type de message ICMP */ char *analyze_icmp_type(u_char type,u_char code) { switch(type) { case 0: return "Echo Reply "; break; case 3: switch(code) { case 0: return "Net unreachable "; break; case 1: return "Host unreachable "; break; case 2: return "Protocol unreachable "; break; case 3: return "Port unreachable "; break; case 4: return "Fragmentation needed "; break; case 5: return "Source route failed "; break; default: return "Destination unreachable"; } break; case 4: return "Source quench "; break; case 5: return "Redirect "; break; case 8: return "Echo "; break; case 11: return "Time exceeded "; break; case 12: return "Parameter problem "; break; case 13: return "Timestamp "; break; case 14: return "Timestamp reply "; break; case 15: return "Information request "; break; case 16: return "Information reply "; break; default: return "? "; } } /* Analyse du type d'opération ARP */ char *analyze_arp_op(u_short op) { switch(op) { case 1: return "(ARP Request) "; break; case 2: return "(ARP Response) "; break; case 3: return "(RARP Request) "; break; case 4: return "(RARP Response) "; break; case 5: return "(Dyn RARP request)"; break; case 6: return "(Dyn RARP reply) "; break; case 7: return "(Dyn RARP error) "; break; case 8: return "(InARP request) "; break; case 9: return "(InARP reply) "; break; default: return "(?) "; } } /* Analyse du type d'opération BOOTP */ char *analyze_bootp_op(u_char op) { switch(op) { case 1: return "(Request)"; break; case 2: return "(Reply) "; break; default: return "(Unknown)"; } } /* Analyse du type hardware */ char *analyze_arp_ht(u_short ht) { switch(ht) { case 1: return "(10Mb Ethernet)"; break; default: return " "; } } /* Analyse du type de message DHCP */ char *analyze_dhcp_mt(u_char mt) { switch(mt) { case 1: return "(DHCP Discover)"; break; case 2: return "(DHCP Offer) "; break; case 3: return "(DHCP Request) "; break; case 4: return "(DHCP Decline) "; break; case 5: return "(DHCP Ack) "; break; case 6: return "(DHCP Nack) "; break; case 7: return "(DHCP Release) "; break; case 8: return "(DHCP Inform) "; break; default: return " "; } } /* Conversion IP u_long pour affichage */ char *iptos(u_long in) { static char output[IPTOSBUFFERS][16]; static short which; u_char *p; p = (u_char *)∈ which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } /* Conversion IP u_char pour affichage */ char *ipctos(u_char *ip) { static char output[15]; sprintf(output,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); return output; } /* Affichage + fichier log */ void echo(char *s) { if(f!=NULL) { fputs(s,f); } printf(s); } /* Affichage payload - hexa et char */ void print_payload(const u_char *payload,int len) { u_int s=0,i,j; char alpha[20]; char buffer[4]; if(len<1) return; echo("+..............................................................+\n"); echo("+ PAYLOAD +\n"); echo("+..............................................................+\n"); j=0; memset(alpha,0,20); for(i=0;i=32 && payload[i]<127) { alpha[j]=payload[i]; } else { alpha[j]='.'; } j++; if(j>15) { j=0; echo(alpha); memset(alpha,0,20); echo("\n"); } } if(j!=0) { for(i=16;i>j;i--) { echo(" "); } echo(alpha); echo("\n"); } } /* Analyse Ethernet */ void analyze_sniff_ether(const struct sniff_ethernet *ethernet, const struct pcap_pkthdr *header) { char buffer[66]; char timestr[16]; struct tm *ltime; ltime=localtime(&header->ts.tv_sec); strftime(timestr, sizeof timestr, "%H:%M:%S", ltime); sprintf(buffer,"| ETHERNET %s,%.6d %5d bytes |\n", timestr, (int)header->ts.tv_usec, header->len); echo(buffer); echo("+..............................................................+\n"); sprintf(buffer,"| MAC Source : %.2x %.2x %.2x %.2x %.2x %.2x -> Dest : %.2x %.2x %.2x %.2x %.2x %.2x |\n",ethernet->ether_shost[0],ethernet->ether_shost[1],ethernet->ether_shost[2],ethernet->ether_shost[3],ethernet->ether_shost[4],ethernet->ether_shost[5],ethernet->ether_dhost[0],ethernet->ether_dhost[1],ethernet->ether_dhost[2],ethernet->ether_dhost[3],ethernet->ether_dhost[4],ethernet->ether_dhost[5]); echo(buffer); sprintf(buffer,"| Ether Type : 0x%.4x %s |\n", ntohs(ethernet->ether_type),analyze_ether_type(ntohs(ethernet->ether_type))); echo(buffer); } /* Analyse IP */ void analyze_sniff_ip(const struct sniff_ip *ip) { char buffer[60]; echo("+..............................................................+\n"); echo("| IP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Version : %5d Header Length : %5d |\n",ip->ip_v,ip->ip_hl); echo(buffer); sprintf(buffer,"| Type of Service : %5x Total Length : %5d |\n",ip->ip_tos,ntohs(ip->ip_len)); echo(buffer); if(ntohs(ip->ip_tos)>0) { // Type of Service } sprintf(buffer,"| Identification : %5d Flags : %5x |\n",ntohs(ip->ip_id),ntohs(ip->ip_off)); echo(buffer); sprintf(buffer,"| Protocol %5x : %s TTL : %5d |\n",ip->ip_p,analyze_ip_proto(ip->ip_p),ip->ip_ttl); echo(buffer); sprintf(buffer,"| From : %15s To : %15s |\n",iptos(ip->ip_src.s_addr),iptos(ip->ip_dst.s_addr)); echo(buffer); } /* Analyse TCP */ void analyze_sniff_tcp(const struct sniff_tcp *tcp) { char buffer[66]; echo("+..............................................................+\n"); echo("| TCP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Source Port : %5d Destination Port : %5d |\n",htons(tcp->th_sport),htons(tcp->th_dport)); echo(buffer); sprintf(buffer,"| Sequence number : %5d Acknowledgement : %5d |\n",htons(tcp->th_seq),htons(tcp->th_ack)); echo(buffer); sprintf(buffer,"| Control bits : %1d....... FIN (No more data from sender) |\n",(tcp->th_flags & TH_FIN?1:0)); echo(buffer); sprintf(buffer,"| .%1d...... SYN (Synchronize sequence number) |\n",(tcp->th_flags & TH_SYN?1:0)); echo(buffer); sprintf(buffer,"| ..%1d..... RST (Reset the connection) |\n",(tcp->th_flags & TH_RST?1:0)); echo(buffer); sprintf(buffer,"| ...%1d.... PSH (Push function) |\n",(tcp->th_flags & TH_PUSH?1:0)); echo(buffer); sprintf(buffer,"| ....%1d... ACK (Acknowledgment field sign.) |\n",(tcp->th_flags & TH_ACK?1:0)); echo(buffer); sprintf(buffer,"| .....%1d.. URG (Urgent pointer field sign.) |\n",(tcp->th_flags & TH_URG?1:0)); echo(buffer); } /* Analyse ICMP */ void analyze_sniff_icmp(const struct sniff_icmp *icmp) { char buffer[66]; echo("+..............................................................+\n"); echo("| ICMP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Type %2d : %s |\n",icmp->icmp_type,analyze_icmp_type(icmp->icmp_type,icmp->icmp_code)); echo(buffer); sprintf(buffer,"+ Identifier : %5d Seq number : %5d |\n",icmp->icmp_id,icmp->icmp_seq); echo(buffer); } /* Analyse UDP */ void analyze_sniff_udp(const struct sniff_udp *udp) { char buffer[66]; echo("+..............................................................+\n"); echo("| UDP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Source Port : %5d Dest Port : %5d Length : %5d |\n",htons(udp->uh_sport),htons(udp->uh_dport),htons(udp->uh_len)); echo(buffer); } /* Analyse ARP */ void analyze_sniff_arp(const struct sniff_arp *arp) { char buffer[66]; echo("+..............................................................+\n"); echo("| ARP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Hardware Type : %5d %s |\n",htons(arp->arp_ht),analyze_arp_ht(htons(arp->arp_ht))); echo(buffer); sprintf(buffer,"| Protocol Type : %5d %s |\n",htons(arp->arp_pt),analyze_ether_type(htons(arp->arp_pt))); echo(buffer); sprintf(buffer,"| Hardware address length : %3d |\n",arp->arp_hlen); echo(buffer); sprintf(buffer,"| Protocol address length : %3d |\n",arp->arp_plen); echo(buffer); sprintf(buffer,"| Operation : %5d %s |\n",htons(arp->arp_op),analyze_arp_op(htons(arp->arp_op))); echo(buffer); sprintf(buffer,"| Sender Hardware Address : %.2x %.2x %.2x %.2x %.2x %.2x |\n",arp->arp_sha[0],arp->arp_sha[1],arp->arp_sha[2],arp->arp_sha[3],arp->arp_sha[4],arp->arp_sha[5]); echo(buffer); sprintf(buffer,"| Sender Protocol Address : %15s |\n",ipctos((u_char *)arp->arp_spa)); echo(buffer); sprintf(buffer,"| Target Hardware Address : %.2x %.2x %.2x %.2x %.2x %.2x |\n",arp->arp_tha[0],arp->arp_tha[1],arp->arp_tha[2],arp->arp_tha[3],arp->arp_tha[4],arp->arp_tha[5]); echo(buffer); sprintf(buffer,"| Target Protocol Address : %15s |\n",ipctos((u_char *)arp->arp_tpa)); echo(buffer); } /* Analyse BOOTP */ void analyze_sniff_bootp(const struct sniff_bootp *bootp) { char buffer[66]; echo("+..............................................................+\n"); echo("| BOOTP |\n"); echo("+..............................................................+\n"); sprintf(buffer,"| Op : %d %s Transaction : %10d |\n",bootp->bootp_op,analyze_bootp_op(bootp->bootp_op),htons(bootp->bootp_xid)); echo(buffer); sprintf(buffer,"| Hardware Address Type : %3d Hardware Address Length : %3d |\n",bootp->bootp_ht,bootp->bootp_hl); echo(buffer); sprintf(buffer,"| Hops : %3d Secs : %5d Flags : %5d |\n",bootp->bootp_hops,htons(bootp->bootp_secs),htons(bootp->bootp_flags)); echo(buffer); sprintf(buffer,"| Client IP Address : %15s |\n",iptos(bootp->bootp_ciaddr.s_addr)); echo(buffer); sprintf(buffer,"| 'your' (client) IP address : %15s |\n",iptos(bootp->bootp_yiaddr.s_addr)); echo(buffer); sprintf(buffer,"| Server IP address : %15s |\n",iptos(bootp->bootp_siaddr.s_addr)); echo(buffer); sprintf(buffer,"| Relay agent IP address : %15s |\n",iptos(bootp->bootp_giaddr.s_addr)); echo(buffer); sprintf(buffer,"| Client Hardware Address : %.2x %.2x %.2x %.2x %.2x %.2x |\n",bootp->bootp_chaddr[0],bootp->bootp_chaddr[1],bootp->bootp_chaddr[2],bootp->bootp_chaddr[3],bootp->bootp_chaddr[4],bootp->bootp_chaddr[5]); echo(buffer); sprintf(buffer,"| Server : %51s |\n",bootp->bootp_sname); echo(buffer); } /* Analyse DHCP */ void analyze_dhcp_options(const u_char *op, int size) { const u_char *p=op; char buffer[66]; u_char value[64]; u_char *v; u_char code,len; unsigned int i; echo("+..............................................................+\n"); echo("| DHCP |\n"); echo("+..............................................................+\n"); while(pether_type)==ETHERTYPE_IP) { ip = (struct sniff_ip*)(packet + size_ethernet); analyze_sniff_ip(ip); /* ICMP */ if(ip->ip_p==1) { icmp = (struct sniff_icmp*)(packet + size_ethernet + size_ip); analyze_sniff_icmp(icmp); payload = (u_char *)(packet + size_ethernet + size_ip + size_icmp); print_payload(payload,header->caplen-(size_ethernet + size_ip + size_icmp)); /* TCP */ } else if(ip->ip_p==6) { tcp = (struct sniff_tcp*)(packet + size_ethernet + size_ip); analyze_sniff_tcp(tcp); payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp + (tcp->th_off-5)*4); // ! offset print_payload(payload,header->caplen-(size_ethernet + size_ip + size_tcp)); /* UDP */ } else if(ip->ip_p==17) { udp = (struct sniff_udp*)(packet + size_ethernet + size_ip); analyze_sniff_udp(udp); /* BOOTP/DHCP */ if(htons(udp->uh_dport)==67 && htons(udp->uh_sport)==68 || htons(udp->uh_dport)==68 && htons(udp->uh_sport)==67) { bootp = (struct sniff_bootp*)(packet + size_ethernet + size_ip + size_udp); analyze_sniff_bootp(bootp); size_tmp = header->caplen-(size_ethernet + size_ip + size_udp + size_bootp); if(size_tmp>0) { payload = (u_char *)(packet + size_ethernet + size_ip + size_udp + size_bootp); /* DHCP Magic Cookie */ if(payload[0]==0x63 && payload[1]==0x82 && payload[2]==0x53 && payload[3]==0x63) { analyze_dhcp_options(payload+4,header->caplen-(size_ethernet + size_ip + size_udp + size_bootp + 4)); } } } else { payload = (u_char *)(packet + size_ethernet + size_ip + size_udp); print_payload(payload,header->caplen-(size_ethernet + size_ip + size_udp)); } } /* ARP */ } else if(ntohs(ethernet->ether_type)==ETHERTYPE_ARP) { arp = (struct sniff_arp*)(packet + size_ethernet); analyze_sniff_arp(arp); } echo("+--------------------------------------------------------------+\n"); } /* Informations relatives à l'interface */ void ifprint(pcap_if_t *d) { pcap_addr_t *a; printf("\n\t%s\n",d->name); if (d->description) printf("\tDescription: %s\n",d->description); printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); for(a=d->addresses;a;a=a->next) { printf("\tAddress family : #%d\n",a->addr->sa_family); switch(a->addr->sa_family) { case AF_INET: printf("\tAddress type : AF_INET\n"); if (a->addr) printf("\tAddress : %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr)); if (a->netmask) printf("\tNetmask : %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr)); if (a->broadaddr) printf("\tBroadcast address : %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr)); if (a->dstaddr) printf("\tDestination address : %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr)); break; default: printf("\tAddress type : Unknown\n"); break; } } printf("\n"); } /* main */ int main(int argc, char *argv[]) { /* Vars */ pcap_if_t *alldevs; pcap_if_t *d; pcap_t *fp; char c=0; char logfile[20]; char filter[256]=""; bpf_u_int32 netmask; struct bpf_program fcode; int inum; int i=0; char error[PCAP_ERRBUF_SIZE]; printf("---------------------------------\n"); printf("PacketSniffer 1.0 (by dew & manw)\n"); printf("---------------------------------\n"); /* Trouve toutes les interfaces */ pcap_findalldevs(&alldevs, error); // saisie de l'interface à capturer if(argc>1) { inum=atoi(argv[1]); } else { printf("Interfaces :\n"); i=1; for(d=alldevs;d!=NULL;d=d->next) { if(d->description!=NULL) { printf("%d : %s -> (%s)\n",i,d->name,d->description); } else { printf("%d : %s\n",i,d->name); } i++; } printf("Interface n0 ? "); scanf("%d",&inum); } fflush(stdin); // sélectionne l'interface i=1; for(d=alldevs;d!=NULL;d=d->next) { if(i==inum) break; i++; } // affichage des informations relatives à l'interface ifprint(d); fflush(stdin); // saisie du fichier de log if(argc>2) { strcpy(logfile,argv[2]); f=fopen(logfile,"w"); } else { c=0; while(c!='y' && c!='n' && c!='o') { printf("\nDo you want to log all (y/n) ? "); c=getchar(); } if(c=='y' || c=='o') { printf("Filename of the log ? "); scanf("%s",logfile); f=fopen(logfile,"w"); } } if(f!=NULL) { printf("Logging to : %s\n",logfile); } fflush(stdin); // saisie du filtre de capture if(argc>3) { strcpy(filter,argv[3]); printf("Using filter : %s\n",filter); } else { c=0; while(c!='y' && c!='n' && c!='o') { printf("Do you want to apply a filter rule (y/n) ? "); c=getchar(); } if(c=='y' || c=='o') { fflush(stdin); printf("Filter ? "); fgets(filter,4096,stdin); } } // écrit le filtre dans le fichier de log if(f!=NULL) { fputs("Filter : ",f); if(strlen(filter)>0) { fputs(filter,f); } else { fputs("*none*",f); } fputs("\n\n",f); } //if(d->addresses!=NULL) // netmask=((bpf_u_int32 *)(d->addresses->netmask))->sin_addr.s_addr; //else netmask=0xffffff; /* Ouvre */ fp = pcap_open_live(d->name, CAP_SNAPLEN, 1, CAP_TIMEOUT, error); if(fp==NULL) { fprintf(stderr,"Error : %s",error); exit(1); } /* Compile le filtre et l'active */ if(strlen(filter)>0) { if(pcap_compile(fp, &fcode, filter, 1, netmask)<0){ fprintf(stderr,"\nErreur de compilation du filtre: syntaxe incorrecte.\n"); exit(1); } if(pcap_setfilter(fp, &fcode)<0){ fprintf(stderr,"\nErreur de configuration du filtre\n"); exit(1); } } pcap_loop(fp, CAP_CNT, packet_handler, NULL); pcap_close(fp); if(f!=NULL) fclose(f); system("PAUSE"); return 0; }