用C实现截获网络数据包


1.  把网卡置于混杂模式。

2.  捕获数据包。

3.  分析数据包。 

注:下面的源代码取至Chad  Renfro的 < <  Basic  Packet-Sniffer  Construction  from  the  Ground  Up> > 一文中 
/************************Tcp_sniff_2.c********************/ 
1.#include    
2.#include    
3.#include 
4.#include 
5.#include 
6.#include 
7.#include    
8.#include 
9.#include  "headers.h " 
     
#define  INTERFACE  "eth0 " 
     
 /*Prototype  area*/ 
     
10.int  Open_Raw_Socket(void);  
11.int  Set_Promisc(char  *interface,  int  sock);  
12.int  main()  {    
13.int  sock,  bytes_recieved,  fromlen;   
14.char  buffer[65535]; 
15.struct  sockaddr_in  from;  
16.struct  ip  *ip; 
17.struct  tcp  *tcp;    
18.sock  =  Open_Raw_Socket(); 
19.  Set_Promisc(INTERFACE,  sock); 
     
20.  while(1) 
22.  { 
23.  fromlen  =  sizeof  from; 
24.  bytes_recieved  =  recvfrom(sock,  buffer,  sizeof  buffer,  0,  (struct  sockaddr  *)&from,  &fromlen); 
25.  printf( "\nBytes  received  :::  %5d\n ",bytes_recieved); 
26.  printf( "Source  address  :::  %s\n ",inet_ntoa(from.sin_addr)); 
27.  ip  =  (struct  ip  *)buffer; 
/*See  if  this  is  a  TCP  packet*/ 
28.  if(ip-> ip_protocol  ==  6)  { 
29.  printf( "IP  header  length  :::  %d\n ",ip-> ip_length); 
30.  printf( "Protocol  :::  %d\n ",ip-> ip_protocol); 
31.  tcp  =  (struct  tcp  *)(buffer  +  (4*ip-> ip_length)); 
32.  printf( "Source  port  :::  %d\n ",ntohs(tcp-> tcp_source_port)); 
33.  printf( "Dest  port  :::  %d\n ",ntohs(tcp-> tcp_dest_port)); 
34.  } 
     
35.  } 
36.} 
37.int  Open_Raw_Socket()  {     
38.  int  sock; 
39.  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 
/*Then  the  socket  was  not  created  properly  and  must  die*/ 
40.  perror( "The  raw  socket  was  not  created "); 
41.  exit(0); 
42.  };   
43.  return(sock);   
44.  } 
     
45.int  Set_Promisc(char  *interface,  int  sock  )  {    
46.  struct  ifreq  ifr;         
47.  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1); 
48.  if((ioctl(sock,  SIOCGIFFLAGS,  &ifr)  ==  -1))  {   
/*Could  not  retrieve  flags  for  the  interface*/ 
49.  perror( "Could  not  retrive  flags  for  the  interface "); 
50.  exit(0); 
51.  }  
52.  printf( "The  interface  is  :::  %s\n ",  interface);   
53.  perror( "Retrieved  flags  from  interface  successfully "); 
54.  ifr.ifr_flags  |=  IFF_PROMISC;    
55.  if  (ioctl  (sock,  SIOCSIFFLAGS,  &ifr)  ==  -1  )  {    
/*Could  not  set  the  flags  on  the  interface  */    
56.  perror( "Could  not  set  the  PROMISC  flag: "); 
57.  exit(0);      
58.  } 
59.  printf( "Setting  interface  :::  %s  :::  to  promisc ",  interface); 
60.  return(0); 
61.  } 
     
/***********************EOF**********************************/ 

上面这段程序中有很详细的注解,不过我想还是有必要说一说,首先第10行--int  Open_Raw_Socket(void); 是我们的自定义函数,具体内容如下: 

37.int  Open_Raw_Socket()  {     
38.  int  sock; 
39.  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 
/*Then  the  socket  was  not  created  properly  and  must  die*/ 
40.  perror( "The  raw  socket  was  not  created "); 
41.  exit(0); 
42.  };   
43.  return(sock);   
44.  } 
     

                    

第39行  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 

这里我们调用了socket函数,使创建了了一个原始套接口,使之收到TCP/IP信息包。 

  接下来第11行-int  Set_Promisc(char  *interface,  int  sock),这也是我们的自定义函数,目的是把网卡置于混杂模式,具体内容如下: 
45.int  Set_Promisc(char  *interface,  int  sock  )  {    
46.  struct  ifreq  ifr;         
47.  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1); 
48.  if((ioctl(sock,  SIOCGIFFLAGS,  &ifr)  ==  -1))  {   
/*Could  not  retrieve  flags  for  the  interface*/ 
49.  perror( "Could  not  retrive  flags  for  the  interface "); 
50.  exit(0); 
51.  }  
52.  printf( "The  interface  is  :::  %s\n ",  interface);   
53.  perror( "Retrieved  flags  from  interface  successfully "); 
54.  ifr.ifr_flags  |=  IFF_PROMISC;    
55.  if  (ioctl  (sock,  SIOCSIFFLAGS,  &ifr)  ==  -1  )  {    
/*Could  not  set  the  flags  on  the  interface  */    
56.  perror( "Could  not  set  the  PROMISC  flag: "); 
57.  exit(0);      
58.  } 
59.  printf( "Setting  interface  :::  %s  :::  to  promisc ",  interface); 
60.  return(0); 
61.  } 

  首先  struct  ifreq  ifr;  定一了一个ifrreg的结构ifr,接下来  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1);,就是把我们网络设备的名字填充到ifr结构中,在这里  #define  INTERFACE  "eth0 "  ,让我们再往下看,ioctl(sock,  SIOCGIFFLAGS,  &ifr),SIOCGIFFLAGS请求表示需要获取接口标志,现在到了第54行,在我们成功的获取接口标志后把他设置成混杂模式,ifr.ifr_flags  |=  IFF_PROMISC;ioctl  (sock,  SIOCSIFFLAGS,  &ifr)。OK,现在我们所说的第一步已经完成--------把网卡置于混杂模式。 

更多详情见请继续阅读下一页的精彩内容:

  • 1
  • 2
  • 下一页

相关内容