/* Copyright (C) 2002 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define FINGERPRINTING 1 #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include /* the L2 protocols */ #include int decode_honeypot(const unsigned char *buff,const int lu); int aff_nmap(const unsigned char *ip,const int lu, const int port_base) { static unsigned int table_seq[10]; const unsigned int len=(ip[0]&0x0F)<<2; const unsigned int df=ip[6]&0x40; const unsigned char*tcp=ip+len; const unsigned int sport=tcp[0]<<8|tcp[1]; const unsigned int dport=tcp[2]<<8|tcp[3]; const unsigned int tcp_seq=tcp[0x04]<<24|tcp[0x05]<<16|tcp[0x06]<<8|tcp[0x07]; const unsigned int tcp_ack=tcp[0x08]<<24|tcp[0x09]<<16|tcp[0x0A]<<8|tcp[0x0B]; const unsigned int tcp_flags=tcp[0x0D]; const unsigned int tcp_window=tcp[15]|(tcp[14]<<8); const unsigned char *tcp_options=tcp+20; unsigned char *pos_options; const int test_no=dport-port_base+1; const int test_noreq=sport-port_base+1; if(test_noreq>=1 && test_noreq <= 7) { printf("T%d request ",test_noreq); printf("ack=%d seq=%d\n",tcp_ack,tcp_seq); table_seq[test_noreq]=tcp_seq; return 0; } else if(test_no>=1 && test_no <= 7) { printf("ack=%d seq=%d\n",tcp_ack,table_seq[test_no]); printf("T%d(",test_no); } else return 0; // Resp=Y% // df=ip[6]&40 // tcp_options=tcp[0x0D] printf("Resp=Y%%DF=%c%%",df?'Y':'N'); printf("W=%X%%",tcp_window); if(tcp_ack==table_seq[test_no]) printf("ACK=S%%"); else if(tcp_ack==table_seq[test_no]+1) printf("ACK=S++%%"); else printf("ACK=O%%"); printf("Flags="); if(tcp_flags&0x10) printf("A"); if(tcp_flags&0x04) printf("R"); if(tcp_flags&0x02) printf("S"); printf("%%"); printf("Ops="); for(pos_options=tcp_options;pos_options0;i--) dst[i]=src[i]-src[i-1]-0x17; dst[0]=src[0]-0x17; } enum {LEVEL_RAW, LEVEL_DGRAM, LEVEL_ETH, LEVEL_IP, LEVEL_UDP, LEVEL_ICMP, LEVEL_TCP, LEVEL_ARP}; typedef struct s_mac t_mac; struct s_mac { unsigned char mac[6]; t_mac *next; }; t_mac *mac_list=NULL; void add_mac(const char *mac) { t_mac *element; for(element=mac_list;element;element=element->next) { if(memcmp(mac,element->mac,6)==0) return ; } { t_mac *new_element=(t_mac*)malloc(sizeof(*new_element)); memcpy(new_element->mac,mac,6); new_element->next=mac_list; mac_list=new_element; } } int decode(const int level,const unsigned char *buffer,const int len) { static int current_port=0; switch(level) { case LEVEL_ETH: { unsigned int ethertype; if (len < ETH_HLEN) { printf("ETH: Incomplete header, packet corrupt\n"); return 1; } #ifndef FINGERPRINTING printf( "%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x ", buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); #endif add_mac(&buffer[6]); add_mac(&buffer[0]); ethertype=buffer[12]<<8|buffer[13]; switch(ethertype) { case ETHERTYPE_IP: return decode(LEVEL_IP,buffer+ETH_HLEN,len-ETH_HLEN); // ETH_HLEN=14 case ETHERTYPE_ARP: /* 0x0806 */ return decode(LEVEL_ARP,buffer+ETH_HLEN,len-ETH_HLEN); case 0x809B: printf("Appletalk\n"); break; case 0x8018: printf("DOMAIN\n"); break; case 0x0835: printf("RARP\n"); break; default: printf("Type %04X\n",ethertype); break; } } return 0; case LEVEL_ARP: printf("Arp\n"); return 0; case LEVEL_IP: { if(len<20) { printf("IP: Incomplete header, packet corrupt\n"); return 1; } { unsigned int proto=buffer[0x09]; unsigned int offset=(buffer[0]&0x0F)<<2; unsigned int lenip=(buffer[0x02]>>8|buffer[0x3]); unsigned int new_size=len-offset; if(len %d.%d.%d.%d\n", buffer[0x0C], buffer[0x0D], buffer[0x0E], buffer[0x0F], buffer[0x10], buffer[0x11], buffer[0x12], buffer[0x13]); if(lenip%u ",buffer[0]<<8|buffer[1],buffer[2]<<8|buffer[3]); switch(buffer[0x0D]) { case 0x00: printf("NULL SCAN"); break; case 0x01: printf("FIN SCAN"); break; case 0x02: printf("SYN"); break; case 0x04: printf("ACK"); break; case 0x08: printf("PUSH"); break; case 0x10: printf("ACK"); break; case 0x11: printf("FIN ACK"); break; case 0x12: /* SYN ACK */ printf("SYN ACK"); break; case 0x14: printf("RST ACK"); /* Reponse à un NULL/XMAS scan */ break; case 0x18: printf("PSH ACK"); break; case 0x29: printf("XMAS SCAN"); break; case 0x42: printf("ECN-echo SYN"); current_port=(buffer[0]<<8|buffer[1]); break; case 0x2B: printf("SCAN nmap fingerprint attempt"); /* URG PSH SYN FIN */ current_port=(buffer[0]<<8|buffer[1])-2; break; default: printf("flags=0x%02x",buffer[0x0D]); break; } printf("\n"); return 0; case LEVEL_UDP: printf("UDP %u->%u\n",buffer[0]<<8|buffer[1],buffer[2]<<8|buffer[3]); return 0; case LEVEL_ICMP: printf("ICMP type=%u, code=%u ", buffer[0],buffer[1]); switch(buffer[0]) { case 0: printf("Echo reply"); break; case 3: printf("Destination unreachable"); break; case 8: printf("Echo request"); printf(" len=%u",len); if(len==8) { printf(" NMAP"); } break; case 11: printf("Time exceeded"); break; case 30: printf("Traceroute"); break; } printf("\n"); return 0; } return 1; } int decode_honeypot(const unsigned char *buff,const int lu) { unsigned char data[2048]; if((buff[9]!=0xb) || (lu<200)) return 0; /* printf(" ======== Packet size=%d\n",lu); printf("%d.%d.%d.%d->%d.%d.%d.%d\n",buff[0xc],buff[0xd],buff[0xe],buff[0xf], buff[0x10],buff[0x11],buff[0x12],buff[0x13]); */ printf("the-binary "); decrypt(&buff[22],data,lu-22); switch(buff[20]) { case 2: { printf("client->server\n"); data[lu-22]=0; switch(data[1]) { case 1: printf("ask status\n"); break; case 2: printf("set hacker address %d.%d.%d.%d\n",data[3],data[4],data[5],data[6]); printf("use fake address %d\n",data[2]); break; case 3: printf("cmd=%s\n",&data[2]); break; case 4: if(data[8]==0) printf("send_dns from %d.%d.%d.%d",data[2],data[3],data[4],data[5]); else printf("send_dns from %s",&data[9]); printf(":%d\n",data[6]<<8|data[7]); break; case 5: printf("%s flood from %d.%d.%d.%d to ", data[2]==0?"ICMP":"UDP", data[4],data[5],data[6],data[7]); if(data[12]==0) printf("%d.%d.%d.%d",data[8],data[9],data[10],data[11]); else printf("%s",&data[13]); if(data[2]) printf(":%d",data[3]); printf("\n"); break; case 6: printf("remote shell\n"); break; case 7: printf("blind cmd=%s\n",&data[2]); break; case 8: printf("kill\n"); break; case 9: if(data[9]==0) printf("send_dns from %d.%d.%d.%d",data[2],data[3],data[4],data[5]); else printf("send_dns from %s",&data[10]); printf(":%d nbr=%d\n",data[7]<<8|data[8],data[6]); break; case 10: printf("TCP Syn flood from "); if(data[8]) printf("%d.%d.%d.%d",data[9],data[10],data[11],data[12]); else printf("random IP"); if(data[13]) printf(" to %s",&data[14]); else printf(" to %d.%d.%d.%d",data[2],data[3],data[4],data[5]); printf(":%u\n",data[6]<<8|data[7]); break; case 11: printf("TCP Syn flood from "); if(data[8]) printf("%d.%d.%d.%d",data[9],data[10],data[11],data[12]); else printf("random IP"); if(data[14]) printf(" to %s",&data[15]); else printf(" to %d.%d.%d.%d",data[2],data[3],data[4],data[5]); printf(":%u foo=%d\n",data[6]<<8|data[7],data[13]); break; case 12: if(data[13]==0) printf("send_dns from %d.%d.%d.%d", data[6],data[7],data[8],data[9]); else printf("send_dns from %s",&data[14]); printf(":%d to %d.%d.%d.%d foo=%d\n", data[11]<<8|data[12], data[2],data[3],data[4],data[5], data[10]); break; default: printf("cmd=%d %s\n",data[1],&data[2]); break; } } break; case 3: { printf("client<-server\n"); data[lu-22]=0; data[0x190]=0; switch(data[1]) { case 1: printf("status response\n"); if(data[3]) printf("working cmd=%d\n",data[4]); else printf("non working\n"); break; default: printf("cmd=%d %d %s\n",data[1],strlen(&data[2]),&data[2]); break; } } break; } return 0; } int datalinkoffset(int type) { switch (type) { case DLT_EN10MB: return 14; case DLT_PPP: return 4; case DLT_PPP_BSDOS: return 24; case DLT_SLIP: return 16; case DLT_SLIP_BSDOS: return 24; case DLT_FDDI: return 21; case DLT_IEEE802: return 22; case DLT_RAW: return 0; case DLT_LINUX_SLL: return 16; default: printf("type=%d(0x%x)",type,type); return -1; } } struct singleton { struct pcap_pkthdr *hdr; const u_char *pkt; }; static void pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) { struct singleton *sp = (struct singleton *)userData; *sp->hdr = *h; sp->pkt = pkt; } struct s_user { int datalink; int offset; pcap_t *handle; }; /* * * Called by pcap_loop upon reciept of each packet * */ void callback(unsigned char *user, const struct pcap_pkthdr *header, const unsigned char *packet) { static int nbr=1; struct s_user *my_data=(struct s_user*)user; char buffer[40]; struct pcap_stat ps; struct tm *my_gmtime=gmtime(&header->ts.tv_sec); if(pcap_stats(my_data->handle, &ps)) { perror("pcap_stats error:"); } strftime(buffer,sizeof(buffer)-1,"%d/%m/%Y %H:%M:%S",my_gmtime); printf("=====> %d %d %s Packet intercepted, %d bytes sniffed <=====\n", nbr++,ps.ps_recv,buffer,header->len); switch(my_data->datalink) { case DLT_EN10MB: decode(LEVEL_ETH,packet,header->caplen); break; case DLT_LINUX_SLL: switch(packet[14]<<8|packet[15]) { case ETHERTYPE_ARP: decode(LEVEL_ARP,packet+my_data->offset,header->caplen-my_data->offset); break; case ETHERTYPE_IP: decode(LEVEL_IP,packet+my_data->offset,header->caplen-my_data->offset); break; } break; } } int main(int argc, char **argv) { pcap_t *handle; /* Session handle */ char *dev="any"; /* The device to sniff on */ char *filter_app = ""; /* The filter expression */ struct bpf_program filter; /* The compiled filter */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ bpf_u_int32 mask; /* Our netmask */ bpf_u_int32 net; /* Our IP */ struct pcap_pkthdr header; /* The header that pcap gives us */ const u_char *packet; /* The actual packet */ int datalink; int offset; // struct singleton s; struct s_user user_data; #ifdef OLD /* Define the device */ printf("device %s\n",dev); /* Open the session in promiscuous mode */ handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); #else if(argc>1) handle=pcap_open_offline(argv[1],errbuf); else handle= pcap_open_offline("snort.log", errbuf); #endif if(!handle) { perror("pcap_open_live failed "); return 1; } printf("PCAP %d.%d", pcap_major_version(handle), pcap_minor_version(handle)); if(pcap_is_swapped(handle)) { printf(" (data in swapped order)"); } /* Grab a packet */ user_data.datalink = pcap_datalink(handle); user_data.offset = datalinkoffset(user_data.datalink); user_data.handle=handle; if(argc>2) filter_app=argv[2]; /* Compile and apply the filter */ if(pcap_compile(handle, &filter, filter_app, 0, mask)<0) { printf("pcap_compile error: %s\n",pcap_geterr(handle)); return 1; } pcap_setfilter(handle, &filter); if(pcap_loop(handle,-1,(pcap_handler)callback,(u_char *)&user_data)<0) { fprintf(stderr, "%s: pcap_loop: %s\n", argv[0], pcap_geterr(handle)); } /* And close the session */ printf("pcap_close\n"); pcap_close(handle); { t_mac *element; for(element=mac_list;element;element=element->next) { printf( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", element->mac[0], element->mac[1], element->mac[2], element->mac[3], element->mac[4], element->mac[5]); } } return(0); }