/* * G o r k - U n i x P a c k e t L o g g e r * * c o m p a t i b l e v e r s i o n * * * Compile with: gcc gork.c -O4 -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 ) * * * Gork is a tcp/udp/icmp/ip dumper with options to log only packets * from/to specific machine/s in a file with name = its ip/hostname * This version supports pcap library * so this code can be compiled in other boxes * How can i log? * For example we can use a config file [gork.conf] like this: * whitehouse.gov * 192.168.1 * www.dead.net <---- great grateful stuff!!! * baubau.bau * * And we see every packets from/to whitehouse.gov in whitehouse.gov file * from/to 192.168.1.XXX in 192.168.1 file and so on .... * NOTE: To log all pkt use a "." in gork.conf file... Output will be in * all_g0rk.log * * Gork can be used to log pkt from / to a particular port: * * gork -p port * or to check for a particular syslog msg * gork -l refused * And you can see result in gork.syslog * * usage: gork -h for help ... * * Greetings go to: s0ftPj, MTV (gork was created after Beavis & Butthead show) * b0z0/iKX, PacketStorm, all members of Metro Olografix (a cool organization), * dislessici, dead.net for their stuffs, Sky, Francesca & other my friends... * * * pIGpEN */ /* Wake of the flood, laughing water, forty-nine. Get out the pans. Don't just stand the dreamin'. Get out the way. Get out the way. Here comes sunshine, Here comes sunshine */ // CONFIGURATION /* * * DONT_LOOKUP: * gork uses gethostbyaddr() function to obtain hostnames: this * can create a lot of traffic from your box to your name server * and vice versa so you can disable lookup with DONT_LOOKUP * but hostnames or strings in gork.conf can't be considered * * NOTE: gork has a little filter for this.. look for yes_lookup * flag * */ //#define DONT_LOOKUP // if you have problem with gork & your dns /* * PROMISC: * value: 0 --> NO PROMISC * (you see only packets from/to your box) * 1 --> PROMISC MODE * (you see all your network packets) */ #define PROMISC 1 /* * SYSTEM LOG: * gork can send msg via syslog... This isn't a good thing if * you send syslog msg to another host... and can also gives * you problem with console output */ //#define SYSTEM_LOG /* * * G 0 R K a porting of Timothy Leary on your Box ... ;) * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (linux) #define __FAVOR_BSD #endif #include #include #include #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 300 #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; /* Line up a longshot, maybe try it two times, maybe more. Good to know you got shoes to wear, when you find the floor. Why hold out for more? Here comes sunshine, here comes sunshine!! */ 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[2000]; }; 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; }; // think different not so much ... int main __P((int, char **)); unsigned long in_aton __P((const 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((unsigned long)); char *hostLookup(unsigned long in) { struct in_addr addr; struct hostent *hostEnt; addr.s_addr = in; hostEnt = gethostbyaddr((char *)&addr, sizeof(struct in_addr),AF_INET); if(!hostEnt) return NULL; return (hostEnt->h_name); } #endif unsigned long in_aton(const char *str) { unsigned long l; unsigned int val; int i; l = 0; for (i = 0; i < 4; i++) { l <<= 8; if (*str != '\0') { val = 0; while (*str != '\0' && *str != '.') { val *= 10; val += *str - '0'; str++; } l |= val; if (*str != '\0') str++; } } return(htonl(l)); } 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 was found in syslog messages\n"); printf("Other options: \n"); printf(" -i interface\n"); printf(" -v verbose mode for tcp\n"); WHITE; } /* Askin' you nice now, keep the mother rollin' one more time. Been down before, you just don't have to go no more, No More. Here comes sunshine! Here comes sunshine! */ 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; struct protoent *proto; 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=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; if(!(hst_saddr=hostLookup(in_aton(s_addr)))) printf("none -> "); else printf("%s -> ",hst_saddr); MAGENTA; if(!(hst_daddr=hostLookup(in_aton(d_addr)))) 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; 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==1 ) { #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); exit(-1); } 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; default: 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; default: break; }//switch buf[strlen(buf)+1]=0; buf[strlen(buf)]='\n'; fclose(of); } } fclose(iff); } void pcap_device_on(void) { char errbuf[1028]; struct pcap_pkthdr pcap_hdr; int datalink; if (!deviceglobal || !strcmp(deviceglobal, "default")) { deviceglobal=pcap_lookupdev(errbuf); printf("Device detected ->"); 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); bzero(&pcap_hdr, sizeof(struct pcap_pkthdr)); 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; default: 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; default: 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; default: break; } } }