zoukankan      html  css  js  c++  java
  • 实现一个简单的sniffer

    #include<stdio.h>
    #include<pcap.h>
    #include<unistd.h>
    #include<stdlib.h>
    //#include<pcap/bpf.h>
    #include<netinet/ip.h>
    #include<netinet/ip_icmp.h>
    #include<netinet/tcp.h>
    #include<netinet/udp.h>
    #include<netinet/ether.h>
    #include<arpa/inet.h>
    #define ETHER_SIZE 14
    
    ///get_packet()回调函数
    ///header:收到的数据包的pcap_pkthdr类型的指针
    ///packet:收到的数据包数据
    void get_packet(u_char*args, const struct pcap_pkthdr *header,const u_char *packet){
    	
    	static int count = 1;
    	const char * payload;
    	printf("==================================packet number: %d=============================
    ",count++);
    	
    	///ETHER_SIZE:以太帧首部长度14个字节
    	///IP包头(tcp包头(数据))
    	///IP包头(udp包头(数据))
    	///IP包头(icmp包头(数据))
    	struct ip * ip = (struct ip *)(packet + ETHER_SIZE);
    	printf("IP header length: %d
    ",ip->ip_hl<<2);
    	printf("From %s
    ",inet_ntoa(ip->ip_src));
    	printf("To %s
    ",inet_ntoa(ip->ip_dst));
    	int ip_hl = ip->ip_hl<<2;
    
    	///对报文类型进行了扩展
    	///可以分析IP包、ICMP包、TCP包、UDP包
    	switch(ip->ip_p){
    
    		case IPPROTO_TCP:
    		{
    			printf("----Protocol TCP----
    ");
    			struct tcphdr *tcp = (struct tcphdr *)(packet + 14 + ip_hl);			
    			printf("tcp -> source:%d
    ",ntohs(tcp -> source));
    			printf("tcp -> dest:%d
    ",ntohs(tcp -> dest));
    			printf("tcp -> seq:%d
    ",ntohs(tcp -> seq));
    			printf("tcp -> ack_seq:%d
    ",ntohs(tcp -> ack_seq));		
    			printf("tcp -> headerLenth:%d
    ",tcp -> doff << 2);
    			printf("tcp -> fin:%d
    ",tcp -> fin);
    			printf("tcp -> syn:%d
    ",tcp -> syn);
    			printf("tcp -> rst:%d
    ",tcp -> rst);
    			printf("tcp -> psh:%d
    ",tcp -> psh);
    			printf("tcp -> ack:%d
    ",tcp -> ack);
    			printf("tcp -> urg:%d
    ",tcp -> urg);
    			printf("tcp -> window:%d
    ",ntohs(tcp -> window));
    			printf("tcp -> check:%d
    ",ntohs(tcp -> check));	
    			//printf("tcp -> urg_ptr:%d
    ",tcp -> urg_ptr);
    			
    			int h_size = tcp->doff<< 2;
    			int payload_size = ntohs(ip->ip_len) - ip_hl - h_size;
    			
    			int i = payload_size;
    			printf("payload is:%d
    ",i);
    			
    			while(i > 0)
    			{
    				printf("%02x  ", packet[i]);
    				if( i % 16 == 0 )
    					printf("
    ");
    				i--;
    			}
    			printf("
    ");
    			break;
    		}
    		case IPPROTO_UDP:
    		{
    			printf("----Protocol UDP----
    ");
    			struct udphdr *udp = (struct udphdr *)(packet + 14 + ip_hl);			
    			printf("udp -> source:%d
    ",ntohs(udp -> source));
    			printf("udp -> dest:%d
    ",ntohs(udp -> dest));
    			printf("udp -> length:%d
    ",ntohs(udp -> len));
    			printf("udp -> check:%d
    ",ntohs(udp -> check));
    			int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
    			int i = payload_size;
    			printf("payload is:%d
    ",i);
    			
    			while(i > 0)
    			{
    				printf("%02x  ", packet[i]);
    				if( i % 16 == 0 )
    					printf("
    ");
    				i--;
    			}
    			printf("
    ");
    			break;
    		}
    		case IPPROTO_ICMP:
    		{
    			printf("----Protocol ICMP----
    ");
    			struct icmphdr *icmp = (struct icmphdr *)(packet + 14 + ip_hl);
    
    			if(icmp -> type == 8)
    			{
    				printf("--icmp_echo request--
    ");
    				printf("icmp -> type:%d
    ",icmp -> type);
    				printf("icmp -> code:%d
    ",icmp -> code);
    				printf("icmp -> checksum:%d
    ",icmp -> checksum);
    	
    				printf("icmp -> id:%d
    ",icmp -> un.echo.id);
    				printf("icmp -> sequence:%d
    ",icmp -> un.echo.sequence);
    				int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
    				int i = payload_size;
    				printf("payload is:%d
    ",i);
    			
    				while(i > 0)
    				{
    					printf("%02x  ", packet[i]);
    					if( i % 16 == 0 )
    						printf("
    ");
    					i--;
    				}
    				printf("
    ");
    			}
    			else if(icmp -> type == 0)
    			{
    				printf("--icmp_echo reply--
    ");
    				printf("icmp -> type:%d
    ",icmp -> type);
    				printf("icmp -> code:%d
    ",icmp -> code);
    				printf("icmp -> checksum:%d
    ",icmp -> checksum);				
    
    				printf("icmp -> id:%d
    ",icmp -> un.echo.id);
    				printf("icmp -> sequence:%d
    ",icmp -> un.echo.sequence);
    				int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
    				int i = payload_size;
    				printf("payload is:%d
    ",i);
    			
    				while(i > 0)
    				{
    					printf("%02x  ", packet[i]);
    					if( i % 16 == 0 )
    						printf("
    ");
    					i--;
    				}
    				printf("
    ");
    			}
    			else
    			{
    				printf("icmp -> type:%d
    ",icmp -> type);
    				printf("icmp -> code:%d
    ",icmp -> code);
    				printf("icmp -> checksum:%d
    ",icmp -> checksum);
    				int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
    				int i = payload_size;
    				printf("payload is:%d
    ",i);
    			
    				while(i > 0)
    				{
    					printf("%02x  ", packet[i]);
    					if( i % 16 == 0 )
    						printf("
    ");
    					i--;
    				}
    				printf("
    ");		
    			}
    			break;		
    		}
    		case IPPROTO_IP:
    		{
    			printf("----Protocol IP----
    ");
    			//printf("IP header length: %d
    ",ip -> ip_hl<<2);
    			printf("IP version: %d
    ",ip -> ip_v);
    			printf("IP type of service: %d
    ",ip -> ip_tos);
    			printf("IP total length: %d
    ",ip -> ip_len);
    			printf("IP identification: %d
    ",ip -> ip_id);
    			printf("IP fragment offset field: %d
    ",ip -> ip_off);
    			printf("IP time to live: %d
    ",ip -> ip_ttl);
    			printf("IP protocol: %d
    ",ip -> ip_p);
    			printf("IP checksum: %d
    ",ip -> ip_sum);
    			int payload_size = ntohs(ip->ip_len) - ip_hl;
    			int i = payload_size;
    			printf("payload is:%d
    ",i);			
    			while(i > 0)
    			{
    				printf("%02x  ", packet[i]);
    				if( i % 16 == 0 )
    					printf("
    ");
    				i--;
    			}
    			printf("
    ");
    			break;			
    		}			
    		default:printf("Protocol unknown
    ");
    		return;
    	
    
    	}
    }
    		
    
    
    int main(int argc,char*argv[]){
    
    	char *dev, errbuf[PCAP_ERRBUF_SIZE];
    	struct bpf_program fp;
    	char filter_exp[] = "port 23";
    	bpf_u_int32 mask;
    	bpf_u_int32 net;
    	struct pcap_pkthdr header;
    	const u_char *packet;	
    	int num_packets = 10;
    	
    	///pcap_lookupdev()自动获取网络接口,返回一个网络接口的字符串指针
    	///如果出错,errbuf存放出错信息
    	///若想手动指定,则跳过此步,将要监听的网络字符串硬编码到pcap_open_live中
    	dev = pcap_lookupdev(errbuf);
    	if(dev==NULL){
    		printf("ERROR:%s
    ",errbuf);
    		exit(2);
    	}
    	printf("The sniff interface is:%s
    ",dev);
    
    	///pcap_lookupnet()获得设备的IP地址,子网掩码等信息
    	///net:网络接口的IP地址
    	///mask:网络接口的子网掩码
    	if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1){
    		printf("ERROR:%s
    ",errbuf);
    		net = 0;
    		mask = 0;
    	}	
    
    	///pcap_open_live()打开网络接口
    	///BUFSIZ:抓包长度
    	///第三个参数:0代表非混杂模式,1代表混杂模式
    	///第四个参数:等待的毫秒数,超过这个值,获取数据包的函数会立即返回,0表示一直等待直到有数据包到来
    	pcap_t * handle = pcap_open_live(dev,BUFSIZ,1,0,errbuf);
    	if(handle == NULL){
    		printf("ERROR:%s
    ",errbuf);
    		exit(2);
    	}
    /*这里我们测试发现不能过滤,注释掉这部分代码,程序可以正常运行了。
    	///pcap_compile()编译过滤表达式
    	///fp指向编译后的filter_exp
    	///filter_exp过滤表达式
    	///参数四:是否需要优化过滤表达式
    	if(pcap_compile(handle,&fp,filter_exp,0,net)==-1){
    		printf("Can't parse filter %s:%s
    ",filter_exp,pcap_geterr(handle));
    		return(2);
    	}
    	
    	///pcap_setfilter()应用这个过滤表达式
    	///完成过滤表达式后,我们可以使用pcap_loop()或pcap_next()登抓包函数抓包了
    	if(pcap_setfilter(handle,&fp)==-1){	
    		printf("cant' install filter %s:%s
    ",filter_exp,pcap_geterr(handle));
    		return(2);
    	}	
    */
    	printf("Hello
    ");	
    
    //	packet = pcap_next(handle,&header);
    //	printf("Get a packet with length %d.
    ",header.len);
    
    	///
    	///num_packets:需要抓的数据包的个数,一旦抓到了num_packets个数据包,pcap_loop立即返回。负数表示永远循环抓包,直到出错
    	///get_packet:回调函数指针
    	//pcap_loop(handle,num_packets,get_packet,NULL);
    	pcap_loop(handle,-1,get_packet,NULL);
    	
    	pcap_freecode(&fp);
    	
    	///pcap_close()释放网络接口
    	///关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源
    	pcap_close(handle);
    	return(0);
    }
    

      

  • 相关阅读:
    程序员学习提高必看的一篇文章
    SpringAOP拦截器的代理机制
    springboot03_RabbitMQ
    Docker_02
    Docker_01
    Redis_02
    Redis_01
    关于Linux下内存和Swap
    密码学DAY2
    密码学DAY1_02
  • 原文地址:https://www.cnblogs.com/ailx10/p/5459890.html
Copyright © 2011-2022 走看看