/*========================================================== Ethernet Packet Sniffer 'GreedyDog' Version 1.20 Programmed by UNYUN (unewn4th@usa.net) Produced by UNYUN, Shadow Penguin Security, Apr.1999 http://base.oc.to/skyscraper/byte/551 [Compile] LINUX : gcc gdd.c -DLINUX (Tested on TURBO-LINUX 3) SunOS4 : gcc gdd.c -DSUNOS4 (Tested on SunOS 4.1.3) ========================================================== */ #include #include #include #include #include #include #include #ifdef SUNOS4 #include #include #include #include #include #include #include #include #else ifdef LINUX #include #define __FAVOR_BSD #endif #include #include #include #ifdef SUNOS4 /*---------< SUN OS4 用 パケットキャプチャ関連定数 >----------*/ #define NIT_DEV "/dev/nit" /* NITデバイス名 */ #define DEFAULT_NIC "le0" /* NICデバイス名 */ #define CHUNKSIZE 4096 /* チャンクサイズ */ #else ifdef LINUX /*------< LINUX 用 パケットキャプチャ関連定数 >------------*/ #define NIT_DEV "" #define DEFAULT_NIC "eth0" /* NICデバイス名 */ #define CHUNKSIZE 32000 /* チャンクサイズ */ #endif #define S_DEBUG /* DEBUGフラグ */ #define SIZE_OF_ETHHDR 14 /* Length of Thernet Hdr */ #define LOGFILE "./snif.log" /* 保存ログファイル名 */ #define TMPLOG_DIR "/tmp/" /* 臨時ログファイルdir */ struct conn_list{ /*------< 接続テーブルリスト >-----------------------------*/ struct conn_list *next_p; /* 次のElementへのポインタ */ char sourceIP[16],destIP[16]; /* 元、先のIPアドレス */ unsigned long sourcePort,destPort; /* 元、先のポート番号 */ }; struct conn_list *cl; /* 接続テーブルリスト */ struct conn_list *org_cl; /* clの先頭アドレス */ /************************************************ NICをPROMISCUSモードに設定する [Input] nit_dev : NITデバイス名(SUNOSのみ有効) nic_name : NICデバイス名 [Output] -1 : PACKETソケット作成不可 -2 : デバイス状態フラグ取得不可 -3 : 状態フラグセット不可 それ以外 : Socket ************************************************ */ int setnic_promisc(nit_dev,nic_name) char *nit_dev; char *nic_name; { int sock; struct ifreq f; #ifdef LINUX if ((sock=socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL)))<0) return(-1); strcpy(f.ifr_name, nic_name); if (ioctl(sock,SIOCGIFFLAGS,&f)<0) return(-2); f.ifr_flags |= IFF_PROMISC; if (ioctl(sock,SIOCSIFFLAGS,&f)<0) return(-3); #else ifdef SUNOS4 struct strioctl si; struct timeval timeout; u_int chunksize = CHUNKSIZE; u_long if_flags = NI_PROMISC; if ((sock = open(nit_dev, O_RDONLY)) < 0) return(-1); if (ioctl(sock, I_SRDOPT, (char *)RMSGD) < 0) return(-2); si.ic_timout = INFTIM; if (ioctl(sock, I_PUSH, "nbuf") < 0) return(-3); timeout.tv_sec = 1; timeout.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(timeout); si.ic_dp = (char *)&timeout; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-4); si.ic_cmd = NIOCSCHUNK; si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-5); strncpy(f.ifr_name, nic_name, sizeof(f.ifr_name)); f.ifr_name[sizeof(f.ifr_name) - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(f); si.ic_dp = (char *)&f; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-6); si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof(if_flags); si.ic_dp = (char *)&if_flags; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-7); if (ioctl(sock, I_FLUSH, (char *)FLUSHR) < 0) return(-8); #endif return(sock); } /************************************************ 接続テーブルリストclの内容を表示(DEBUG用) ************************************************ */ void show_connection_table() { struct conn_list *ncl; int i; #ifdef S_DEBUF return; #endif ncl=org_cl; printf("\n>\n"); printf("No. SrcIP SrcPort DstIP DstPort\n"); for (i=0;;i++){ if (ncl->next_p==NULL) break; printf("%-5d %-16s %-5d -> %-16s %-5d\n",i, ncl->sourceIP, ncl->sourcePort, ncl->destIP, ncl->destPort); ncl=ncl->next_p; } printf("\n"); } /************************************************ パケット中の表示可能文字だけをファイルに書く [Input] data : パケット len : パケット長 fp : ログファイルポインタ ************************************************ */ void printable_fwrite(data,len,fp) char *data; int len; FILE *fp; { int i; for (i=0;i--------------------------*/ if (ip_header->ip_p==IPPROTO_TCP){ tcp_header = (struct tcphdr *)((char *)ip_header+(ip_header->ip_hl)*4); tcp_data = (char *)tcp_header+sizeof(struct tcphdr); /*-------< ログ対象ポートかどうか検査 >-------------------*/ for (i=0;;i++){ if (snif_port[i]==-1) return; if (tcp_header->th_dport==htons(snif_port[i]) || tcp_header->th_sport==htons(snif_port[i])) break; } /*-------< ヘッダ中の有用データ抽出 >---------------------*/ len_data = length-sizeof(struct tcphdr) -sizeof(struct ip)-SIZE_OF_ETHHDR; sourcePort = ntohs(tcp_header->th_sport); destPort = ntohs(tcp_header->th_dport); memcpy(&ia,&(ip_header->ip_src),sizeof(struct in_addr)); strcpy(sourceIP,(char *)inet_ntoa(ia)); memcpy(&ia,&(ip_header->ip_dst),sizeof(struct in_addr)); strcpy(destIP,(char *)inet_ntoa(ia)); /*-------< 3-wayのSTEP-1 SYNでの処理 >--------------------*/ if (tcp_header->th_flags & TH_SYN && !(tcp_header->th_flags & TH_ACK)){ /*---< Connectionテーブルに情報をセット >-------------*/ if ((cl->next_p=(struct conn_list *)malloc(sizeof(struct conn_list)))==NULL){ printf("Can not allocate memory\n"); return; } strcpy(cl->sourceIP ,sourceIP); strcpy(cl->destIP ,destIP); cl->sourcePort = sourcePort; cl->destPort = destPort; cl = cl->next_p; cl->next_p = NULL; show_connection_table(); /*---< ログファイルにConnection情報を書く >----------*/ sprintf(buf,"%s%s.%lu.%s.%lu", TMPLOG_DIR, sourceIP, sourcePort, destIP, destPort); if ((fp=fopen(buf,"w"))==NULL){ printf("Can not append to temp logfile '%s'",buf); return; } fprintf(fp,"\n\n\n"); for (i=0;i<60;i++) putc('=',fp); fprintf(fp,"\n"); fprintf(fp,"CONNECTION %s(%d) -> %s(%d)\n", sourceIP,sourcePort,destIP,destPort); for (i=0;i<60;i++) putc('=',fp); fprintf(fp,"\n"); fclose(fp); return; } /*-------< Connection切断時の処理 >-----------------------*/ if (tcp_header->th_flags & TH_FIN || tcp_header->th_flags & TH_RST){ /*---< 接続テーブルからこの接続を求める >-------------*/ bcl=org_cl; ncl=org_cl->next_p; for (;;){ if (ncl->sourcePort == sourcePort && ncl->destPort == destPort && !strcmp(ncl->sourceIP,sourceIP) && !strcmp(ncl->destIP,destIP)) break; bcl=ncl; if ((ncl=ncl->next_p)==NULL) break; } if (ncl==NULL) return; /*---< 本ログファイルにTEMPログを追加する >----------*/ sprintf(buf,"%s%s.%lu.%s.%lu", TMPLOG_DIR, ncl->sourceIP, ncl->sourcePort, ncl->destIP, ncl->destPort); if ((fp=fopen(LOGFILE,"a"))!=NULL){ if ((fp2=fopen(buf,"r"))!=NULL){ for (;;){ if ((i=fread(fbuf,1,8000,fp2))<=0) break; fwrite(fbuf,1,i,fp); } fclose(fp2); }else printf("Can not read temp logfile '%s'",buf); fclose(fp); }else printf("Can not append to logfile '%s'",LOGFILE); /*---< TEMPログを消し、接続テーブルから除去する >-----*/ remove(buf); bcl->next_p=ncl->next_p; free(ncl); show_connection_table(); return; } /*-------< 接続テーブルからこの接続を求める >-------------*/ ncl=org_cl->next_p; for (;;){ if (ncl->sourcePort == sourcePort && ncl->destPort == destPort && !strcmp(ncl->sourceIP,sourceIP) && !strcmp(ncl->destIP,destIP)) break; if (ncl->sourcePort == destPort && ncl->destPort == sourcePort && !strcmp(ncl->sourceIP,destIP) && !strcmp(ncl->destIP,sourceIP)) break; if ((ncl=ncl->next_p)==NULL) break; } if (ncl==NULL) return; /*-------< TEMPログファイルに追加する >------------------*/ sprintf(buf,"%s%s.%lu.%s.%lu", TMPLOG_DIR, ncl->sourceIP, ncl->sourcePort, ncl->destIP, ncl->destPort); if ((fp=fopen(buf,"a"))==NULL){ printf("Can not append to temp logfile '%s'",buf); return; } printable_fwrite(tcp_data,len_data,fp); fclose(fp); } } /************************************************ プログラムエントリ ************************************************ */ int main() { static unsigned char packet[CHUNKSIZE]; int sock; int l; #ifdef SUNOS4 unsigned char *buffer_p; struct nit_bufhdr *nit_buffer_header; #endif /*-----------< 接続テーブル初期化 >---------------------------*/ if ((cl=(struct conn_list *)malloc(sizeof(struct conn_list)))==NULL){ printf("Can not allocate memory\n"); exit(1); } org_cl = cl; cl->sourcePort = 0; cl->destPort = 0; strcpy(cl->sourceIP ,"Start"); strcpy(cl->destIP ,"Start"); cl->next_p = (struct conn_list *)malloc(sizeof(struct conn_list)); cl = cl->next_p; cl->next_p = NULL; show_connection_table(); /*-----------< NICをPROMISCUSモードに設定する >---------------*/ if ((sock=setnic_promisc(NIT_DEV,DEFAULT_NIC))<0){ switch(sock){ case -1 : printf("Can not create PACKET socket.\n"); break; case -2 : printf("Can not get device status flag.\n"); break; case -3 : printf("Can not set nic to promisc mode.\n"); break; } printf("%d\n",sock); return(-1); } /*-----------< パケットを拾って解析する >---------------------*/ for (;;){ if ((l=read(sock,packet,sizeof(packet)))>0){ #ifdef SUNOS4 /* NITバッファから順番に拾ってきて解析する */ buffer_p = packet; while (buffer_p < packet+l) { nit_buffer_header = (struct nit_bufhdr *)buffer_p; packet_analysis(buffer_p+sizeof(struct nit_bufhdr), nit_buffer_header->nhb_msglen); buffer_p += nit_buffer_header->nhb_totlen; } #else ifdef LINUX packet_analysis(packet,l); #endif } } }