|
/* * G o r k - U n i x P a c k e t L o g g e r * * v e r s i o n 2.0b - bugs fixed * * Questo sorgente non e' coperto da nessun copyright e come tale potete farci * quello che volete... visto che non arrichisce le mie tasche potete * tranquillamente rubarlo all'autore che tanto a lui non gliene frega un * cazzo... ne' io, ne' il ladro ci possiamo ritenere responsabili di quello * che fate con questo sorgente... * * Compile with: gcc gork.c -Wall -lpcap * * Tested on: * Linux RedHat 6.X ( mail.cameretta.pig ) * Linux Debian 2.0r3 ( porcellino.cameretta.pig ) * FreeBSD 4.0 ( sp00f.y0ur.life.cameretta.pig ) * * - Now it logs correctly * * pIGpEN [pigpen@s0ftpj.org] */ /* * Questa e' la versione che permette di loggare i pacchetti rispetto alla * versione pubblicata su bfi 7: * * - e' stata corretta la hostLookup() * - HST_FOUND viene inizializzata dentro il ciclo in modo da permettere di * loggare solo sui files giusti * - il codice e' stato identato come dio bit comanda e sono state tolte * alcune parti superflue tra cui una variabile in piu' utilizzata per * leggere l'header pcap c'e' ancora una che non serve un cazzo ma che * viene passata come parametro alla funzione pcap_next() */ // CONFIGURATION /* * DONT_LOOKUP -> if you have problems with gork & your dns * SYSTEM_LOG -> Log gork msg via syslog warning this can give problems * PROMISC -> 1 to activate it 0 if you wanna see only your box pkts */ #define PROMISC 1 /* * * G o R K a porting of Timothy Leary on your Box ... ;) * */ #include <stdio.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/time.h> #include <sys/signal.h> #include <sys/socket.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <pcap.h> #if (linux) #define __FAVOR_BSD #endif #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <arpa/inet.h> #include <arpa/nameser.h> #ifdef SYSTEM_LOG #include <syslog.h> #endif #define CONF "gork.conf" #define LOG_TYPE 4 //syslog #define SYSLOG_PORT 514 #define MTU 1500 #define URG 32 #define ACK_PSH 24 #define SYN_ACK 18 #define FIN_ACK 17 #define ACK 16 #define PSH 8 #define RST 4 #define SYN 2 #define FIN 1 #define WHITE printf("\033[0;29m") #define RED printf("\033[1;31m") #define GREEN printf("\033[1;32m") #define YELLOW printf("\033[1;33m") #define BLUE printf("\033[1;34m") #define MAGENTA printf("\033[1;35m") #define CYAN printf("\033[1;36m") #define RETURN printf("\n") #define CLEAR printf("\033[2J\033[1;1H") #define LINE printf("<\033[1;32m-----\033[1;34m>\n"); #define ADDR_DIM 255 #define LOG_ALL "all_g0rk.log" #define LOG_SL "gork.syslog" unsigned char s_addr[ADDR_DIM]; unsigned char d_addr[ADDR_DIM]; char *hst_saddr=NULL; char *hst_daddr=NULL; time_t now; char date[60]; int port=0; char *syslog_string; extern char *optarg; pcap_t *pcap_global_descriptor; char *deviceglobal=NULL; int offset; struct packet_info{ unsigned char ttl, protocol, version; unsigned char *saddr, *daddr; unsigned long seq, ack_seq; unsigned short source, dest, type, id, flags, window; char dataload[MTU]; }; struct DNSpkt { HEADER head; char query[255]; }; struct TCPhdr { u_short source, dest; u_int32_t seq, ack_seq; u_short offset_flag, window, checksum, urgent; }; int main __P((int, char **)); void usage __P((char *)); void scan __P((struct packet_info)); void fuckin_about_all_day __P((void)); void print_addr __P((struct packet_info)); void pcap_device_on __P((void)); void sniff_pk __P((struct packet_info *)); void ethclose __P(()); void dump_tcp __P((struct packet_info, int)); void dump_udp __P((struct packet_info)); void dump_icmp __P((struct packet_info)); #ifndef DONT_LOOKUP char *hostLookup __P((struct in_addr)); char *hostLookup(struct in_addr in) { struct hostent *hostEnt; if((hostEnt=gethostbyaddr((char *)&in, sizeof(struct in_addr), AF_INET))) return (strdup(hostEnt->h_name)); return NULL; } #endif void usage(char *arg) { YELLOW; printf("\t\t\t pIGpEN - diGiTaL dEAdhEAd -"); BLUE; printf("\n\n\nPut hostname/ip in gork.conf ... \nUse "); MAGENTA; printf("-p dest_port "); BLUE; printf("if you wanna log only packets to dest_port\n and with ip/hostname in"); MAGENTA; printf(" gork.conf\n"); BLUE; printf("To log all source ip put in gork.conf: "); MAGENTA; printf(".\n"); printf("-l string "); BLUE; printf("write in gork.syslog if <string> was found in syslog messages\n"); printf("Other options: \n"); printf(" -i interface\n"); printf(" -v verbose mode for tcp\n"); WHITE; } void fuckin_about_all_day(void) { CLEAR; fflush(stdout); sleep(1); printf("\033[1;35m .g#S$'$S#n.\n"); printf("\033[1;35m $$$$$ $$$$'\n"); printf("\033[1;35m $$$$$\n"); printf("\033[1;35m `$$$$$$$$$n\n"); printf("\033[1;34m $$$$$\n"); printf("\033[1;34m $$$$$ $$$$$\n"); printf("\033[1;34m `$$$$s$$$S'\n\n"); fflush(stdout); sleep(1); printf("\033[1;35m .g#S$'$S#n.\n"); printf("\033[1;35m $$$$$ $$$$$\n"); printf("\033[1;35m $$$$$ $$$$$\n"); printf("\033[1;35m $$$$$ $$$$$\n"); printf("\033[1;34m $$$$$s$$$$'\n"); printf("\033[1;34m $$$$$ \n"); printf("\033[1;34m $$$$ \n"); fflush(stdout); sleep(1); printf("\033[1;35m S#n.\n"); printf("\033[1;35m $$$$\n"); printf("\033[1;35m $$$$\n"); printf("\033[1;35m $$$$\n"); printf("\033[1;34m $$$$\n"); printf("\033[1;34m $$$$$ $$$$\n"); printf("\033[1;34m `$$$$s$$S'\n\n"); fflush(stdout); sleep(1); MAGENTA; printf("\033[15A\t\t\t\t _____________________\n"); fflush(stdout); sleep(1); printf("\033[01A\t\t\t\t s o f t p r o j e c t\n\n"); fflush(stdout); sleep(1); BLUE; printf("\t\t\t ____________________________________________\n\n"); fflush(stdout); sleep(1); printf("\t\t\t\033[02A d i g i t a l s e k u r i t y f o r y 2 k\n\n"); fflush(stdout); sleep(1); printf("\t\t\t\t ___________________________\n"); fflush(stdout); sleep(1); printf("\t\t\t\t\033[01A w w w . s 0 f t p j . o r g\n"); fflush(stdout); sleep(1); sleep(3); CLEAR; } void print_addr(struct packet_info infoz) { struct servent *service = NULL; struct protoent *proto = NULL; struct in_addr in_a; int yes_lookup=0; now=time(NULL); strftime(date,60,"%H:%M:%S %a %h %d", localtime(&now)); bzero(s_addr,sizeof(s_addr)); bzero(d_addr,sizeof(d_addr)); hst_daddr=NULL; hst_saddr=NULL; sprintf(s_addr,"%u.%u.%u.%u", infoz.saddr[0], infoz.saddr[1], infoz.saddr[2], infoz.saddr[3]); sprintf(d_addr,"%u.%u.%u.%u", infoz.daddr[0], infoz.daddr[1], infoz.daddr[2], infoz.daddr[3]); GREEN; printf("%s\n",date); BLUE; printf("%s",s_addr); GREEN; printf(" -> "); MAGENTA; printf("%s",d_addr); if(infoz.protocol!=IPPROTO_ICMP) { if((proto=getprotobynumber(infoz.protocol))) { BLUE; if((service=getservbyport(infoz.source,proto->p_name))) printf(" %s",service->s_name); else printf(" %d",infoz.source); YELLOW; printf(" / "); MAGENTA; if((service=getservbyport(infoz.dest,proto->p_name))) printf("%s",service->s_name); else printf("%d",infoz.dest); } } #ifndef DONT_LOOKUP BLUE; // limit shit for dns ... invoked with gethostbyaddr() // you can change it as you want ... switch(infoz.protocol) { case IPPROTO_TCP: if(infoz.flags==SYN) yes_lookup=1; break; case IPPROTO_UDP: if(infoz.source != NAMESERVER_PORT && infoz.dest != NAMESERVER_PORT) yes_lookup=1; break; case IPPROTO_ICMP: yes_lookup=1; break; } if(yes_lookup) { RETURN; inet_aton((char *)s_addr, &in_a); if(!(hst_saddr=hostLookup(in_a))) printf("none -> "); else printf("%s -> ",hst_saddr); MAGENTA; inet_aton((char *)d_addr, &in_a); if(!(hst_daddr=hostLookup(in_a))) printf("none"); else printf("%s",hst_daddr); } #endif MAGENTA; RETURN; scan(infoz); } void scan(struct packet_info infoz) { FILE *iff, *of; char buf[512]; char o[400],tmp_port[10]; char *flags=NULL; int HST_FOUND=0; if(!(iff=fopen(CONF,"r"))) return; while(fgets(buf,512,iff)) { if(buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]=0; HST_FOUND = 0; if(infoz.version!=4) { CLEAR; printf("Sorry this is only a ipv4 version. write to: pigpen@s0ftpj.org\n"); printf("if you wanna ipv6 support\n"); exit(-1); } if(port && infoz.dest!=port && infoz.source!=port) return; if(port && (infoz.protocol==IPPROTO_ICMP)) return; if(hst_saddr) { if(strstr(hst_saddr,buf)) HST_FOUND=1; } if(hst_daddr) { if(strstr(hst_daddr,buf)) HST_FOUND=1; } if( strstr(s_addr, buf) || strstr(d_addr, buf) || HST_FOUND ) { #ifdef SYSTEM_LOG syslog(LOG_TYPE,"G0RK: My lord %s is here ... I log it", s_addr); #endif if(buf[0]=='.' && buf[1]=='\0') of=fopen(LOG_ALL,"a"); else (buf[0]=='.') ? bcopy(buf+1,o,sizeof(o)) : bcopy(buf,o,sizeof(o)); if(port) { sprintf(tmp_port,":%d",port); strncat(o,tmp_port,sizeof(o)); } of=fopen(o,"a+"); if(!of) { CLEAR; printf("Can't open %s file\n\n\n",buf); return ; } fprintf(of,"<--->\n"); fprintf(of,"date: %s\n",date); fprintf(of,"src:%s (%s)\ndst:%s (%s)\n",s_addr,hst_saddr,d_addr,hst_daddr); if((infoz.protocol)!=IPPROTO_ICMP) fprintf(of,"port: %d:%d\n",infoz.source,infoz.dest); switch(infoz.protocol) { case IPPROTO_ICMP: fprintf(of,"type: "); switch((infoz.type)/256) { case 0: fprintf(of,"icmp echo reply\n"); break; case 3: fprintf(of,"icmp dest_unreach\n"); break; case 4: fprintf(of,"icmp source quench\n"); break; case 5: fprintf(of,"icmp redirect\n"); break; case 8: fprintf(of,"icmp echo\n"); break; case 11: fprintf(of,"icmp time exceeded\n"); break; case 12: fprintf(of,"icmp parameter problem\n"); break; case 13: fprintf(of,"icmp timestamp\n"); break; case 14: fprintf(of,"icmp timestamp reply\n"); break; case 15: fprintf(of,"icmp information\n"); break; case 16: fprintf(of,"icmp information reply\n"); break; case 17: fprintf(of,"icmp address mask\n"); break; case 18: fprintf(of,"icmp address mask reply\n"); break; default: fprintf(of,"icmp type %i\n", infoz.type); break; } break; case IPPROTO_TCP: fprintf(of,"seq #: %u\n",(unsigned int) infoz.seq); fprintf(of,"ack #: %u\n",(unsigned int) infoz.ack_seq); fprintf(of,"ttl: %i\n",infoz.ttl); fprintf(of,"win: %i\n",infoz.window); switch (infoz.flags) { case URG: flags="-----U"; break; case ACK_PSH: flags="---PA-"; break; case SYN_ACK: flags="-S--A-"; break; case FIN_ACK: flags="F---A-"; break; case ACK: flags="----A-"; break; case PSH: flags="---P--"; break; case RST: flags="--R---"; break; case SYN: flags="-S----"; break; case FIN: flags="F-----"; break; } fprintf(of,"flags %s\n",flags); break; case IPPROTO_UDP: if(infoz.dest==SYSLOG_PORT && port!=SYSLOG_PORT) fprintf(of,"SYSLOG DATA: %s\n",infoz.dataload); break; } buf[strlen(buf)+1]=0; buf[strlen(buf)]='\n'; fclose(of); } } fclose(iff); } void pcap_device_on(void) { char errbuf[400]; int datalink; if (!deviceglobal || !strcmp(deviceglobal, "default")) { deviceglobal=pcap_lookupdev(errbuf); printf("Device ->"); GREEN; printf(" %s.\n\n", deviceglobal); } if (!deviceglobal) { printf("Error getting device - %s\n", errbuf); exit(1); } pcap_global_descriptor = pcap_open_live(deviceglobal, 68, PROMISC, 1000, errbuf); if (!pcap_global_descriptor) { printf("error opening pcap: %s\n", errbuf); exit(1); } datalink = pcap_datalink(pcap_global_descriptor); switch (datalink) { case DLT_EN10MB: offset = 14; break; case DLT_NULL: case DLT_PPP: offset = 4; break; case DLT_SLIP: offset = 16; break; case DLT_RAW: offset = 0; break; case DLT_SLIP_BSDOS: case DLT_PPP_BSDOS: offset = 24; break; default: printf("unknown datalink type (%d)", datalink); exit(-1); } } void sniff_pk(struct packet_info *infoz) { struct ip *IP; struct TCPhdr *TCP; struct udphdr *UDP; struct icmp *ICMP; struct pcap_pkthdr lpcap_hdr; char *sniff_buff; bzero(s_addr, sizeof(s_addr)); bzero(d_addr, sizeof(d_addr)); if((sniff_buff=(char *) pcap_next(pcap_global_descriptor, &lpcap_hdr))){ (char *) sniff_buff+=offset; IP = (struct ip *) sniff_buff; infoz->ttl = IP->ip_ttl; infoz->protocol = (char)IP->ip_p; infoz->version = (char)IP->ip_v; infoz->saddr = (unsigned char *)&(IP->ip_src.s_addr); infoz->daddr = (unsigned char *)&(IP->ip_dst.s_addr); switch (infoz->protocol) { case IPPROTO_TCP: TCP = (struct TCPhdr *)(sniff_buff+sizeof(*IP)); infoz->seq = ntohl(TCP->seq); infoz->ack_seq = ntohl(TCP->ack_seq); infoz->source = ntohs(TCP->source); infoz->dest = ntohs(TCP->dest); infoz->window = ntohs(TCP->window); infoz->flags = ntohs(TCP->offset_flag)& (URG|ACK|PSH|FIN|RST|SYN); memcpy(infoz->dataload, sniff_buff + sizeof(struct ip) + sizeof(struct TCPhdr), ntohs(IP->ip_len)-sizeof(struct ip)-sizeof(struct TCPhdr)); break; case IPPROTO_UDP: UDP = (struct udphdr *)(sniff_buff+sizeof(*IP)); infoz->source = ntohs(UDP->uh_sport); infoz->dest = ntohs(UDP->uh_dport); memcpy(infoz->dataload, sniff_buff + sizeof(struct ip) + sizeof(struct udphdr), ntohs(IP->ip_len)-sizeof(struct ip)-sizeof(struct udphdr)); break; case IPPROTO_ICMP: ICMP = (struct icmp *)(sniff_buff+sizeof(*IP)); infoz->type = ntohs(ICMP->icmp_type); infoz->id = ntohs(ICMP->icmp_seq); break; } } } void ethclose() { if(pcap_global_descriptor) pcap_close(pcap_global_descriptor); MAGENTA; printf("I will getby ... I will survive...\n"); WHITE; exit(0); } void dump_tcp(struct packet_info info, int data) { char *flags=NULL; print_addr(info); MAGENTA; printf("TCP "); BLUE; printf("%u:", (unsigned int) info.seq); MAGENTA; printf("%u", (unsigned int) info.ack_seq); MAGENTA; printf("\tTTL: "); BLUE; printf("%i ", info.ttl); MAGENTA; printf("\tWin: "); BLUE; printf("%i", info.window); switch (info.flags) { case URG: flags="-----\033[1;32mU\033[1;34m"; break; case ACK_PSH: flags="---\033[1;32mPA\033[1;34m-"; break; case SYN_ACK: flags="-\033[1;32mS\033[0;34m--\033[1;32mA\033[1;34m-"; break; case FIN_ACK: flags="\033[1;32mF\033[1;34m---\033[1;32mA\033[1;34m-"; break; case ACK: flags="----\033[1;32mA\033[1;34m-"; break; case PSH: flags="---\033[1;32mP\033[1;34m--"; break; case RST: flags="--\033[1;32mR\033[1;34m---"; break; case SYN: flags="-\033[1;32mS\033[1;34m----"; break; case FIN: flags="\033[1;32mF\033[1;34m-----"; break; } MAGENTA; printf(" FLAGS: "); BLUE; printf("%s\n",flags); if(data && (info.flags==PSH || info.flags==ACK_PSH)) { BLUE; printf("-> "); GREEN; printf("%s\n",info.dataload); } LINE; } void dump_udp(struct packet_info info) { FILE *fp_sl; struct DNSpkt *dns_pkt; print_addr(info); printf("UDP "); if(info.dest==SYSLOG_PORT && port!=SYSLOG_PORT) { GREEN; printf("%s", info.dataload); if(syslog_string && info.dataload) { if(strstr(info.dataload,syslog_string)) { RED; printf("\tMSG LOGGED -> %s\n",LOG_SL); fp_sl=fopen(LOG_SL,"a"); now=time(NULL); strftime(date,60,"%H:%M:%S %a %h %d", localtime(&now)); fprintf(fp_sl,"\n%s --- str -> %s\n",date,syslog_string); fprintf(fp_sl,"%s -> %s == %s\n", s_addr, d_addr, info.dataload); fclose(fp_sl); } } } if(info.source==NAMESERVER_PORT || info.dest==NAMESERVER_PORT) { dns_pkt=(struct DNSpkt *) info.dataload; BLUE; printf("\tRD: "); MAGENTA; printf("%d ",dns_pkt->head.rd); BLUE; printf("AA: "); MAGENTA; printf("%d ",dns_pkt->head.aa); BLUE; printf("OPCODE: "); MAGENTA; switch(dns_pkt->head.opcode) { case QUERY: printf("QUERY "); break; case IQUERY: printf("IQUERY "); break; case STATUS: printf("STATUS "); break; default: printf("%d ",dns_pkt->head.opcode); } BLUE; printf("QR: "); MAGENTA; printf("%d ",dns_pkt->head.qr); BLUE; printf("RA: "); MAGENTA; printf("%d ",dns_pkt->head.ra); BLUE; printf("AD: "); MAGENTA; printf("%d ",dns_pkt->head.ad); BLUE; printf("CD: "); MAGENTA; printf("%d",dns_pkt->head.cd); BLUE; printf("\tDNSPKT ID: "); RED; printf("%d",dns_pkt->head.id); } RETURN; BLUE; LINE; } void dump_icmp(struct packet_info info) { print_addr(info); MAGENTA; printf("ICMP "); BLUE; printf("TYPE: "); RED; switch((info.type/256)) { case 0: printf("echo reply\t"); break; case 3: printf("dest_unreach\t"); break; case 4: printf("source quench\t"); break; case 5: printf("redirect\t"); break; case 8: printf("echo\t"); break; case 11: printf("time exceeded\t"); break; case 12: printf("parameter problem\t"); break; case 13: printf("timestamp\t"); break; case 14: printf("timestamp reply\t"); break; case 15: printf("information\t"); break; case 16: printf("information reply\t"); break; case 17: printf("address mask\t"); break; case 18: printf("address mask reply\t"); break; default: printf("%i\t", info.type); break; } BLUE; printf("(ttl:%i id:%i)\n", info.ttl, (info.id/256)); LINE; } int main(int argc, char **argv) { int snoop = 0, opt; struct packet_info pk_info; signal(SIGINT, ethclose); signal(SIGTERM, ethclose); signal(SIGKILL, ethclose); signal(SIGQUIT, ethclose); fuckin_about_all_day(); while ((opt = getopt(argc, (char **) argv, "vhp:l:i:")) != EOF) { switch(opt) { case 'v': snoop=1; break; case 'h': usage(argv[0]); exit(1); case 'p': if(syslog_string) { printf("Can't execute gork with -l & -p\n"); WHITE; exit(1); } port=atoi(optarg); break; case 'l': if(port) { printf("Can't execute gork with -p & -l\n"); WHITE; exit(1); } syslog_string=optarg; break; case 'i': deviceglobal=optarg; break; default: exit(1); } } pcap_device_on(); while(1) { bzero(&pk_info,sizeof(pk_info)); sniff_pk(&pk_info); // add here other protocol implementations with their functions switch(pk_info.protocol) { case IPPROTO_TCP: dump_tcp(pk_info, snoop); break; case IPPROTO_UDP: dump_udp(pk_info); break; case IPPROTO_ICMP: dump_icmp(pk_info); break; } } }