winpcap编程

(一)获得网卡接口
  #i nclude "pcap.h"
  void main()
  {
      pcap_if_t *alldevs;
      /*struct pcap_if_t{
      pcap_if_t *next;
      char *name;
      char *description;
      pcap_addr *addresses;
      U_int falgs;
      }
      */
      pcap_if_t *d;
      int i=0;
      char errbuf[PCAP_ERRBUF_SIZE];
      /* Retrieve the device list */
      if (pcap_findalldevs(&alldevs, errbuf) == -1)//返回网卡列表,alldevs指向表头
      {
          fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
          exit(1);
      }
      /* Print the list */
      for(d=alldevs;d;d=d->next)
      {
          printf("%d. %s", ++i, d->name);
          if (d->description)
              printf(" (%s)\n", d->description);
          else
                    printf(" (No description available)\n");
        }
      if(i==0)
      {
          printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
          return;
      }
  /* We don't need any more the device list. Free it */
      pcap_freealldevs(alldevs);
  }
  --------------------------------------------------------------------------------
(二)抓包
  本程序俘获局域网内UDP报文。
  #i nclude "pcap.h"
  /* 4 bytes IP address */
  typedef struct ip_address{
  u_char byte1;
  u_char byte2;
  u_char byte3;
  u_char byte4;
  }ip_address;
  /* IPv4 header */
  typedef struct ip_header{
  u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
  u_char tos; // Type of service
  u_short tlen; // Total length
  u_short identification; // Identification
  u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
  u_char ttl; // Time to live
  u_char proto; // Protocol
  u_short crc; // Header checksum
  ip_address saddr; // Source address
  ip_address daddr; // Destination address
  u_int op_pad; // Option + Padding
  }ip_header;
  /* UDP header*/
  typedef struct udp_header{
  u_short sport; // Source port
  u_short dport; // Destination port
  u_short len; // Datagram length
  u_short crc; // Checksum
  }udp_header;
  /* prototype of the packet handler */
  void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
  main()
  {
  pcap_if_t *alldevs;
  pcap_if_t *d;
  int inum;
  int i=0;
  pcap_t *adhandle;
  char errbuf[PCAP_ERRBUF_SIZE];
  u_int netmask;
  char packet_filter[] = "ip and udp";
  struct bpf_program fcode;
  /* Retrieve the device list */
  if (pcap_findalldevs(&alldevs, errbuf) == -1)
  {
  fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  exit(1);
  }
  /* Print the list */
  for(d=alldevs; d; d=d->next)
  {
  printf("%d. %s", ++i, d->name);
  if (d->description)
  printf(" (%s)\n", d->description);
  else
  printf(" (No description available)\n");
  }
  if(i==0)
  {
  printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
  return -1;
  }
  printf("Enter the interface number (1-%d):",i);
  scanf("%d", &inum);
  if(inum < 1 || inum > i)
  {
  printf("\nInterface number out of range.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
  }
  /* Jump to the selected adapter */
  for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
  /* Open the adapter */
  if ( (adhandle= pcap_open_live(d->name, // name of the device
  65536,                                                     // portion of the packet to capture.
                                                                  // 65536 grants that the whole packet will be captured on all the MACs.
  1,                                                             // promiscuous mode
  1000,                                                         // read timeout
  errbuf                                                         // error buffer
  ) ) == NULL)
  {
  fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
  }
  /* Check the link layer. We support only Ethernet for simplicity. */
  if(pcap_datalink(adhandle) != DLT_EN10MB)
  {
  fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
  }
  if(d->addresses != NULL)
  /* Retrieve the mask of the first address of the interface */
  netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  else
  /* If the interface is without addresses we suppose to be in a C class network */
  netmask=0xffffff;
  //compile the filter
  if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ){
  fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
  }
  //set the filter
  if(pcap_setfilter(adhandle, &fcode)<0){
  fprintf(stderr,"\nError setting the filter.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
  }
  printf("\nlistening on %s...\n", d->description);
  /* At this point, we don't need any more the device list. Free it */
  pcap_freealldevs(alldevs);
  /* start the capture */
  pcap_loop(adhandle, 0, packet_handler, NULL);
  return 0;
  }
  /* Callback function invoked by libpcap for every incoming packet */
  void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
  {
  struct tm *ltime;
  char timestr[16];
  ip_header *ih;
  udp_header *uh;
  u_int ip_len;
  /* convert the timestamp to readable format */
  ltime=localtime(&header->v_sec);
  strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
  /* print timestamp and length of the packet */
  /* retireve the position of the ip header */
  ih = (ip_header *) (pkt_data +
  14); //length of ethernet header
  /* retireve the position of the udp header */
  ip_len = (ih->ver_ihl & 0xf) * 4;
  uh = (udp_header *) ((u_char*)ih + ip_len);
  /* convert from network byte order to host byte order */
  printf("%s.%.6d len:%d ", timestr, header->_usec, header->len);
  /* print ip addresses */
  printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
  ih->saddr.byte1,
  ih->saddr.byte2,
  ih->saddr.byte3,
  ih->saddr.byte4,
  ih->daddr.byte1,
  ih->daddr.byte2,
  ih->daddr.byte3,
  ih->daddr.byte4
  );
  }
  --------------------------------------------------------------------------------
(三)发包
  要在命令行下运行,给与参数:网卡描述符。或者添加代码findalldevs(),那样应很方便。
  #i nclude <stdlib.h>
  #i nclude <stdio.h>
  #i nclude
  void usage();
  void main(int argc, char **argv) {
  pcap_t *fp;
  char error[PCAP_ERRBUF_SIZE];
  u_char packet[100];
  int i;
  /* Check the validity of the command line */
  if (argc != 2)
  {
  printf("usage: %s inerface", argv[0]);
  return;
  }
  /* Open the output adapter */
  if((fp = pcap_open_live(argv[1], 100, 1, 1000, error) ) == NULL)
  {
  fprintf(stderr,"\nError opening adapter: %s\n", error);
  return;
  }
  /* Supposing to be on ethernet, set mac destination to 1:1:1:1:1:1 */
  packet[0]=1;
  packet[1]=1;
  packet[2]=1;
  packet[3]=1;
  packet[4]=1;
  packet[5]=1;
  /* set mac source to 2:2:2:2:2:2 */
  packet[6]=2;
  packet[7]=2;
  packet[8]=2;
  packet[9]=2;
  packet[10]=2;
  packet[11]=2;
  /* Fill the rest of the packet */
  for(i=12;i<100;i++){
  packet=i%256;
  }
  /* Send down the packet */
  pcap_sendpacket(fp,
  packet,
  100);
  return;
  }
 
=================================================================================================
百度上面摘下来的,使用一三配合成功在链路层发出过数据包,抓包程序上面的写的太过复杂,我参照下面的方法写出一个比较简单的程序,也可抓到链路层数据包
首先,先枚举系统中的所有网卡:
/* 获取设备列表 */  
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
  fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  exit(1);
}
/* 数据列表 */  
for(d=alldevs; d; d=d->next)
{
  printf("%d. %s", ++i, d->name);
  if (d->description)
   printf(" (%s)\n", d->description);
  else
   printf(" (No description available)\n");
}
然后选择网卡,然后设备。
if ( (adhandle= pcap_open_live(d->name, //设备名  
  65536, // 捕捉完整的数据包  
  1 , // 混在模式  
  1, // 读入超时  
  errbuf // 错误缓冲  
  ) ) == NULL)
{
  printf("Unable to open the adapter");
  pcap_freealldevs(alldevs);
  return;  
}
打开设备之后,我们就可以利用adhandle句柄来正式抓包了,先新建一个回调函数,形如
void packet_handler(u_char* packets,const struct pcap_pkthdr *header,const u_char *data)
{
}
然后调用pcap_loop(adhandle, 0, packet_handler, NULL);pcap_loop的最后一个参数和packet_handler的packets参数是对应的,用于在函数间传递数据。WinpCap每收到一个包就自动调用packet_handler函数,将包的内容作为data参数,我们对data作强制类型转化就可以得到数据包各部分的内容。
事实上,WinpCap开发包除了可以用回调函数抓包外,还可以用非回调的方法。在得到adhandle后不调用pcap_loop,而用下面的方法:
while(1)
{
   res = pcap_next_ex(adhandle,&header,&data);
  if(res==0)
  {
   Sleep(100);
   continue;
  }
}
用pcap_next_ex读取数据包内容,至于if(res==0)这一段是为了防止没数据包到达时重复循环。
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值