libpcap应用实例

网络编程 专栏收录该内容
7 篇文章 1 订阅

libpcap落地包dump

#include <stdio.h>
#include <pcap.h>       /*Libpcap头文件*/

void packet_callback(u_char *user,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
  static int packet_number = 1;      /*静态局部变量,用来存放捕获到的数据包的个数*/
  printf("The %d packet is captured len%d.\n",packet_number,packet_header->len);   /*输出捕获数据包的个数*/
  pcap_dump(user, packet_header, packet_content);   /*调用pcap_dump函数写入文件*/
  packet_number++;       /*每次调用此回调函数,个数+1*/
}

void main()
{
  pcap_t* pcap_handle;       /*Libpcap句柄*/
  pcap_dumper_t *dumpfp;      /*定义dump句柄*/
  char error_content[PCAP_ERRBUF_SIZE];     /*用来存储错误信息*/
  char *net_interface;       /*用来存储网络接口*/
  struct bpf_program bpf_filter;     /*BPF过滤规则*/
  char bpf_filter_string[] = "tcp port 80";     /*过滤规则字符串形式*/
  bpf_u_int32 net_mask;       /*网络掩码*/
  bpf_u_int32 net_ip;       /*网络地址*/
  net_interface = pcap_lookupdev(error_content);   /*获取网络接口*/
  pcap_lookupnet(net_interface, &net_ip,&net_mask,error_content);

  /*获取网络地址和掩码*/
  pcap_handle = pcap_open_live(net_interface, BUFSIZ, 1, 0, error_content); 
  pcap_compile(pcap_handle, &bpf_filter, bpf_filter_string, 0,  net_ip);
  pcap_setfilter(pcap_handle, &bpf_filter);
  dumpfp = pcap_dump_open(pcap_handle, "./traffic");
  pcap_loop(pcap_handle, -1, packet_callback, (u_char *)dumpfp); 
  pcap_close(pcap_handle);      /*关闭Libpcap操作*/
  pcap_dump_close(dumpfp);      /*关闭写入的文件*/

}


libpcap落地包转发


/*pcap_sendpacket 转发包*/

#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518

/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6

int main(int argc, char **argv)
{

 char *dev = NULL;   /* capture device name */
 char errbuf[PCAP_ERRBUF_SIZE];  /* error buffer */
 pcap_t *handle;    /* packet capture handle */
 pcap_t *sendhandle;    /* packet capture handle */
  const u_char *packet;
  struct pcap_pkthdr header;

 char filter_exp[] =  "tcp port 80";  /* filter expression [3] */
 struct bpf_program fp;   /* compiled filter program (expression) */
 bpf_u_int32 mask;   /* subnet mask */
 bpf_u_int32 net;   /* ip */
 int num_packets = -1;   /* number of packets to capture */

 dev = pcap_lookupdev(errbuf);
 if (dev == NULL) {
  fprintf(stderr, "Couldn't find default device: %s\n",
      errbuf);
  exit(EXIT_FAILURE);
 }
 sendhandle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
 if (handle == NULL) {
  fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
  exit(EXIT_FAILURE);
 } 

 handle = pcap_open_offline("traffic", errbuf);


   while(1){
       packet = pcap_next(handle,&header);
       pcap_sendpacket(sendhandle, packet, header.len) ;
   }
 /* cleanup */
 pcap_freecode(&fp);
 pcap_close(handle);

 printf("\nCapture complete.\n");

return 0;
}

libpcap中转包程序




网关设置/etc/sysconfig/network-scripts/ifcfg-eth0

/*本机需要设置为SRCIP,DESTIP机器的网关
通过SRCIP机器,连接DEST地址,DEST必须和SRCIP不是一个网段,这样通过网关转到本机
本程序捕获后,将DEST转化到DESTIP,SRCIP转化到SRC(为了回消息的时候也通过网关给本机)
这样SRCIP访问DESTIP会通过本机中转,本机可以截获所有信息
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pcap.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

void handle_packet(u_char *user, const struct pcap_pkthdr* pkthdr,const u_char* packet);
unsigned short check_sum(unsigned short *addr,int len);
void print_payload(const u_char *payload, int len);
void print_hex_ascii_line(const u_char *payload, int len, int offset);
struct psd_header{
   unsigned long saddr;
   unsigned long daddr;
   char mbz;
   char ptcl;
   unsigned short tcpl;                            
};

unsigned short port;
#define SRCIP "192.168.100.51"//源真实IP
#define DESTIP "192.168.100.190"//目标真实IP
#define DEST "192.168.0.190" //目标虚拟地址
#define SRC "192.168.0.207" //源虚拟地址(无所谓不用改,只要不在一个网段就行)
#define PORT 8443
//程序所在本机为网关

/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518

int main(int argc, char **argv)
{
   char *dev = NULL;
   char errbuf[PCAP_ERRBUF_SIZE];
   pcap_t *handle = NULL;
   struct bpf_program filter;
   char filter_app[] = "tcp port 8443 and ( host 192.168.100.190 or 192.168.100.51 )";//源真实IP+目标真实IP+端口
   bpf_u_int32 mask;
   bpf_u_int32 net;
   struct pcap_pkthdr header;
   const u_char *packet;
   int on = 1;

   int sockfd = socket(PF_INET,SOCK_RAW,IPPROTO_TCP);
   if(sockfd < 0){
       fprintf(stderr,"Socket error:\n");
       exit(-4);
   }
   if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)) < 0)
     fprintf(stderr,"HDRINCL error\n");
   /* create a socket */  
  
 if (argc == 2) {
   dev = argv[1];
  }
  else if (argc > 2) {
   fprintf(stderr, "error: unrecognized command-line options\n\n");
   exit(EXIT_FAILURE);
  }
  else {
   /* find a capture device if not specified on command-line */
   dev = pcap_lookupdev(errbuf);
   if (dev == NULL) {
    fprintf(stderr, "Couldn't find default device: %s\n",
        errbuf);
    exit(EXIT_FAILURE);
   }
  }
  
  /* get network number and mask associated with capture device */
  if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
   fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
       dev, errbuf);
   net = 0;
   mask = 0;
  }
 
  /* print capture info */
  printf("Device: %s\n", dev);
  printf("Filter expression: %s\n", filter_app);

   if(NULL == (handle = pcap_open_live(dev,SNAP_LEN,1,0,errbuf))){
       fprintf(stderr,"pcap_open_live() error:%s\n",errbuf);
       exit(-2);
   }

   if(-1 == pcap_compile(handle,&filter,filter_app,1,net)){
       fprintf(stderr,"pcap_compile() error.\n");
       exit(-3);
   }

   pcap_setfilter(handle,&filter);

//   while(1){
//       packet = pcap_next(handle,&header);
//       printf("captured a packet with length of [%d]\n",header.len);
//       handle_packet(&header,packet,sockfd);
//   }
   pcap_loop(handle, -1, handle_packet, (u_char *)&sockfd); 


   pcap_close(handle);

   return 0;
}

void handle_packet(u_char *user, const struct pcap_pkthdr* pkthdr,const u_char* packet)
{
  int sockfd = *user;
   u_char buffer[SNAP_LEN];
   int len = pkthdr->len;
   struct iphdr* ip;
   struct tcphdr* tcp;
   char srcbuf[16];
   char dstbuf[16];
   u_char temp[SNAP_LEN];
   struct sockaddr_in addr;
   struct psd_header psdhdr;
   int ip_len;

   memset(buffer,0,SNAP_LEN);
   memset(temp,0,SNAP_LEN);
   memcpy(buffer,packet,len);
   memset(srcbuf,0,16);
   memset(dstbuf,0,16);
   memset(&addr,0,sizeof(struct sockaddr_in));
   memset(&psdhdr,0,sizeof(struct psd_header));

   ip = (struct iphdr *)(buffer + sizeof(struct ethhdr));
   tcp = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr));
  
   //int iphl_size = ip->ihl *4 ; //ip头长度
  // int tcphl_size =tcp->doff * 4;//tcp头长度
  //u_char *payload = (u_char *)(buffer + sizeof(struct ethhdr) + iphl_size + tcphl_size );
  /* compute tcp payload (segment) size */
  //int size_payload = ntohs(ip->tot_len) - ( iphl_size + tcphl_size) ;

 /*
  * Print payload data; it might be binary, so don't just
  * treat it as a string.
  */
// if (size_payload > 0) {
//  printf("   Payload (%d bytes):\n", size_payload);
//  print_payload(payload, size_payload);
// }
   
   
   ip_len = ntohs(ip->tot_len);
   strcpy(srcbuf,inet_ntoa(((struct ip *)(buffer + sizeof(struct ethhdr)))->ip_src));
   strcpy(dstbuf,inet_ntoa(((struct ip *)(buffer + sizeof(struct ethhdr)))->ip_dst));
   printf("source ip:%s\n",srcbuf);
   printf("destination ip:%s\n",dstbuf);
   printf("len:%d\n",ip_len);
   printf("fin:%x,syn:%x,rst:%x,psh:%x,ack:%x,urg:%x\n", tcp->fin,tcp->syn,tcp->rst,tcp->psh,tcp->ack,tcp->urg );

   if(strcmp(dstbuf,DEST) == 0)
   {
      if(strcmp(srcbuf,SRCIP) == 0)
       {
          addr.sin_family = AF_INET;
          addr.sin_port = htons(PORT);
          addr.sin_addr.s_addr = inet_addr(DESTIP);
          ip->daddr = addr.sin_addr.s_addr;
          ip->saddr = inet_addr(SRC);
          ip->check = 0;
          ip->check = check_sum((unsigned short *)ip,sizeof(struct iphdr));
          tcp->dest = addr.sin_port;
          port = tcp->source;
          tcp->source = htons(PORT);    
          tcp->check = 0;
          psdhdr.saddr = ip->saddr;
          psdhdr.daddr = ip->daddr;
          psdhdr.mbz = 0;
          psdhdr.ptcl = IPPROTO_TCP;
          psdhdr.tcpl = htons(ip_len - sizeof(struct iphdr));
          memcpy(temp,&psdhdr,sizeof(struct psd_header));
          memcpy(temp + sizeof(struct psd_header),tcp,ip_len - sizeof(struct iphdr));
          tcp->check = check_sum((unsigned short *)temp,sizeof(struct psd_header) + ip_len - sizeof(struct iphdr));
          sendto(sockfd,buffer + sizeof(struct ethhdr),ip_len,0,(struct sockaddr *)(&addr),sizeof(struct sockaddr));
      }
   }
   else if(strcmp(srcbuf,DESTIP) == 0)
   {
     if(strcmp(dstbuf,SRC) == 0)
     {
       addr.sin_family = AF_INET;
       addr.sin_port = port; 
       addr.sin_addr.s_addr = inet_addr(SRCIP);
       ip->daddr = addr.sin_addr.s_addr;
       ip->saddr = inet_addr(DEST);
       ip->check = 0;
       ip->check = check_sum((unsigned short *)ip,sizeof(struct iphdr));
       tcp->dest = addr.sin_port;
       tcp->source = htons(PORT);
       tcp->check = 0;
       psdhdr.saddr = ip->saddr;
       psdhdr.daddr = ip->daddr;
       psdhdr.mbz = 0;
       psdhdr.ptcl = IPPROTO_TCP;
       psdhdr.tcpl = htons(ip_len - sizeof(struct iphdr));
       memcpy(temp,&psdhdr,sizeof(struct psd_header));
       memcpy(temp + sizeof(struct psd_header),tcp,ip_len - sizeof(struct iphdr));
       tcp->check = check_sum((unsigned short *)temp,sizeof(struct psd_header) + ip_len - sizeof(struct iphdr)); 
       sendto(sockfd,buffer + sizeof(struct ethhdr),ip_len,0,(struct sockaddr *)(&addr),sizeof(struct sockaddr));
     }
   }
}

unsigned short check_sum(unsigned short *addr,int len){
   register int nleft = len;
   register int sum = 0;
   register u_short *w = addr;
   u_short answer = 0;

   while(nleft > 1){
       sum += *w++;
       nleft -= 2;
   }
   if(nleft == 1){
       *(u_char *)(&answer) = *(u_char *)w;
       sum += answer;
   }
   sum = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);
   answer = ~sum;
   return (answer);
}

/*
 * print packet payload data (avoid printing binary data)
 */
void print_payload(const u_char *payload, int len)
{

 int len_rem = len;
 int line_width = 16;   /* number of bytes per line */
 int line_len;
 int offset = 0;     /* zero-based offset counter */
 const u_char *ch = payload;

 if (len <= 0)
  return;

 /* data fits on one line */
 if (len <= line_width) {
  print_hex_ascii_line(ch, len, offset);
  return;
 }

 /* data spans multiple lines */
 for ( ;; ) {
  /* compute current line length */
  line_len = line_width % len_rem;
  /* print line */
  print_hex_ascii_line(ch, line_len, offset);
  /* compute total remaining */
  len_rem = len_rem - line_len;
  /* shift pointer to remaining bytes to print */
  ch = ch + line_len;
  /* add offset */
  offset = offset + line_width;
  /* check if we have line width chars or less */
  if (len_rem <= line_width) {
   /* print last line and get out */
   print_hex_ascii_line(ch, len_rem, offset);
   break;
  }
 }

return;
}


/*
 * print data in rows of 16 bytes: offset   hex   ascii
 *
 * 00000   47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a   GET / HTTP/1.1..
 */
void print_hex_ascii_line(const u_char *payload, int len, int offset)
{

 int i;
 int gap;
 const u_char *ch;

 /* offset */
 printf("%05d   ", offset);
 
 /* hex */
 ch = payload;
 for(i = 0; i < len; i++) {
  printf("%02x ", *ch);
  ch++;
  /* print extra space after 8th byte for visual aid */
  if (i == 7)
   printf(" ");
 }
 /* print space to handle line less than 8 bytes */
 if (len < 8)
  printf(" ");
 
 /* fill hex gap with spaces if not full line */
 if (len < 16) {
  gap = 16 - len;
  for (i = 0; i < gap; i++) {
   printf("   ");
  }
 }
 printf("   ");
 
 /* ascii (if printable) */
 ch = payload;
 for(i = 0; i < len; i++) {
  if (isprint(*ch))
   printf("%c", *ch);
  else
   printf(".");
  ch++;
 }

 printf("\n");

return;
}

 



  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值