(作者:燕云   出处:http://www.cnblogs.com/SwordTao/ 欢迎转载,但也请保留这段声明,谢谢!)


  君不见 黄河之水 天上来 奔流到海不复回

  君不见 高堂明镜 悲白发 朝如青丝暮成雪

  人生得意须尽欢 莫使金樽空对月

——将进酒

pcap文件格式,为多数的tcpdump、wireshark等重量级的数据包抓取、分析应用程序所直接支持,所以,为我们的程序中嵌入此类文件的解析与生成功能,很是值得。

具体信息请看wireshark wiki:http://wiki.wireshark.org/Development/LibpcapFileFormat

笔者本来想借助开源的tcpreplay与libpcap中的代码片段来快速实现此目的,没想到被两个bug,卡住了几个小时,真是欲速则不达!

第一处:tcpreplay,如果不是因为宏SEEK_SET恰巧等于0 ...... 不要多说,虽不致命,但祸患无穷。

第二处:libpcap,关于packet header的结构定义,struct timeval长度为16字节,而实际上这段区域长度为8字节,所以,这个结构体根本不能正常工作。只会更糟!

无碍,我们继续,最终的pcap文件解析函数原型:

上图是即为解析的核心函数原型,对照着第一个图一起看会很清晰!下面进行测试 :)

 1 int main()
 2 {
 3   struct pcap_file_header phdr;
 4   char * filePathPtr="log.pcap";
 5   int fd;
 6   int i;
 7   int packet_counter;
 8   struct packet pkt;
 9
10   if ( ( fd=open(filePathPtr,O_RDONLY) )==-1 )
11   {
12     printf("error: open file error %s \n",filePathPtr);
13     return 1;
14   }
15   if( is_pcap_file_format(fd,&phdr))
16   {
17     print_pcap_file_header(&phdr);
18   }
19   else
20   {
21     printf("error: file %s format not support \n",filePathPtr);
22     return 1;
23   }
24   packet_counter=0;
25   while(1)
26   {
27       if(pcap_file_get_next_packet(fd,&pkt))
28       {
29         packet_counter++;
30         printf("snaplen: %d actual_len: %d packet_counter: %d \n",pkt.len,pkt.actual_len,packet_counter);
31         for(i=0; i<pkt.len; ++i)
32         {
33           printf(" %02x", pkt.data[i]);
34           if( (i + 1) % 16 == 0 )
35           {
36             printf("\n");
37           }
38         }
39         printf("\n\n");
40       }
41       else
42       {
43         printf("done\n");
44           break;
45       }
46   }
47   close(fd);
48 }

View Code

nice ! pcap文件解析已完成,接下来进行流量重放:

其中,函数 build_send_ethernet_packet  是我们的老朋友了,无需多言,重点是 pcap_ip_repaly  的实现:

 1 int pcap_ip_repaly( char * pcapFilePathPtr, int usecDelayPerPacket, char * devName)
 2 {
 3     struct pcap_file_header phdr;
 4     struct ethernet_ip_hdr * hdrPtr;
 5     int packet_counter;
 6     struct packet pkt;
 7     int fd;
 8     int i;
 9
10
11     if ( ( fd=open(pcapFilePathPtr,O_RDONLY) )==-1 )
12     {
13       fprintf(stderr,"error: open file error %s",pcapFilePathPtr);
14       return 1;
15     }
16
17     if( is_pcap_file_format(fd,&phdr) )
18     {
19       print_pcap_file_header(&phdr);
20     }
21     else
22     {
23       fprintf(stderr, "error: the file %s is not .pcap format\n",pcapFilePathPtr);
24       return 1;
25     }
26
27     packet_counter=0;
28     while(1)
29     {
30         if(pcap_file_get_next_packet(fd,&pkt))
31         {
32           usleep(usecDelayPerPacket);
33           packet_counter++;
34           //analyze packet and send it
35           hdrPtr=(struct ethernet_ip_hdr *) pkt.data;
36           if( hdrPtr->ether_type==0x0008) //filter: ip type: 0x0800 -> little endian 0x0008
37               {
38                 // print packet information
39               printf("ether: %02x:%02x:%02x:%02x:%02x:%02x ->",hdrPtr->ether_shost[0],hdrPtr->ether_shost[1]
40                 ,hdrPtr->ether_shost[2],hdrPtr->ether_shost[3],hdrPtr->ether_shost[4],hdrPtr->ether_shost[5]);
41               printf(" %02x:%02x:%02x:%02x:%02x:%02x   ",hdrPtr->ether_dhost[0],hdrPtr->ether_dhost[1]
42                 ,hdrPtr->ether_dhost[2],hdrPtr->ether_dhost[3],hdrPtr->ether_dhost[4],hdrPtr->ether_dhost[5]);
43               printf("ip: %d.%d.%d.%d ->",hdrPtr->ip_src[0],hdrPtr->ip_src[1],hdrPtr->ip_src[2],hdrPtr->ip_src[3]);
44               printf(" %d.%d.%d.%d \n",hdrPtr->ip_dst[0],hdrPtr->ip_dst[1],hdrPtr->ip_dst[2],hdrPtr->ip_dst[3]);
45               if(pkt.len==pkt.actual_len)
46               {
47                 printf("whole packet:padPtr is %x,padLength is %d \n",pkt.data+14,pkt.len-14);
48                     if (build_send_ethernet_packet(devName,1, hdrPtr->ether_dhost,
49                                                hdrPtr->ether_shost,0x0800,pkt.data+14,pkt.len-14)
50                         ==0
51                         )
52                         printf("resend packet success :) \n");
53                     else
54                         printf("resend packet fail :( \n");
55               }
56               else
57               {
58                 fprintf(stderr,"this packet is not entire,cannot resend :(");
59               }
60
61               }
62           else
63            {
64                if(hdrPtr->ether_type==0x0608) //filter: ip type: 0x0806 -> little endian 0x0608
65                  {printf("arp packet \n");}
66                else if(hdrPtr->ether_type==0x3508) //filter: ip type: 0x0835 -> little endian 0x3508
67                  {printf("rarp packet \n");}
68                else
69                     {printf("unknown packet type\n");}
70            }
71           //print packet
72           printf("snaplen: %d actual_len: %d packet_counter: %d \n",pkt.len,pkt.actual_len,packet_counter);
73           for(i=0; i<pkt.len; ++i)
74           {
75             printf(" %02x", pkt.data[i]);
76             if( (i + 1) % 16 == 0 )
77             {
78               printf("\n");
79             }
80           }
81           printf("\n\n");
82         }
83         else
84         {
85           break;
86         }
87     }
88
89     close(fd);
90     return 0;
91
92 }

View Code

int pcap_ip_repaly( char * pcapFilePathPtr, int usecDelayPerPacket, char * devName)

char * pcapFilePathPtr : 待解析 pcap 文件路径

int usecDelayPerPacket : 每隔多少us发一个包。。即控制发包速率
char * devName : 你想让哪个网卡做坏事?写上他的”真名“吧!

进行测试:

int main()
{return  pcap_ip_repaly("log.pcap",0,"eth0");
}

附录:

全部代码

  1 #include <sys/time.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <sys/types.h>
  7 #include <sys/time.h>
  8 #include <sys/types.h>
  9 #include <stdint.h>
 10 #include <libnet.h>
 11
 12
 13 #define PCAP_MAGIC  0xa1b2c3d4  /* magic constants for various pcap file types */
 14 #define DEFAULT_MTU 1500        /* Max Transmission Unit of standard ethernet
 15                                                  * don't forget *frames* are MTU + L2 header! */
 16 #define MAXPACKET 16436         /* MTU of Linux loopback */
 17 #define MAX_SNAPLEN 65535       /* tell libpcap to capture the entire packet */
 18
 19 struct pcap_file_header {
 20         unsigned int  magic;
 21         unsigned short int version_major;
 22         unsigned short int version_minor;
 23         int thiszone;     /* gmt to local correction */
 24         unsigned int sigfigs;    /* accuracy of timestamps */
 25         unsigned int snaplen;    /* max length saved portion of each pkt */
 26         unsigned int linktype;   /* data link type (LINKTYPE_*) */
 27 };
 28 struct pcap_pkthdr {
 29         time_t ts;//struct timeval ts;  /* time stamp */
 30         unsigned int caplen;     /* length of portion present */
 31         unsigned int len;        /* length this packet (off wire) */
 32 };
 33
 34 struct packet {
 35     unsigned char data[MAXPACKET];       /* pointer to packet contents */
 36     unsigned int len;                    /* length of data (snaplen) */
 37     unsigned int actual_len;             /* actual length of the packet */
 38     time_t ts;          /* timestamp */
 39 };
 40
 41 struct ethernet_ip_hdr
 42 {
 43     uint8_t  ether_dhost[6];/* destination ethernet address */
 44     uint8_t  ether_shost[6];/* source ethernet address */
 45     uint16_t ether_type;    /* protocol */
 46     uint8_t  ip_ver_hdrlen;
 47     uint8_t  ip_tos;
 48     uint16_t ip_total_len;         /* total length */
 49     uint16_t ip_id;          /* identification */
 50     uint16_t ip_frag;
 51     uint8_t  ip_ttl;          /* time to live */
 52     uint8_t  ip_proto;            /* protocol */
 53     uint16_t ip_hdrCRC;         /* checksum */
 54     uint8_t  ip_src[4];
 55     uint8_t  ip_dst[4];
 56 };
 57
 58 /* return flag if this is a pcap file */
 59 /*
 60 retCode
 61 0 fail
 62 1 success
 63 */
 64 int is_pcap_file_format(int fd,struct pcap_file_header * pcapFileHdrPtr)
 65 {
 66
 67     if (lseek(fd, 0, SEEK_SET) != 0)
 68     {
 69         fprintf(stderr,"Unable to seek to start of file\n");
 70         return 0;
 71     }
 72
 73     if (read(fd, (void *) pcapFileHdrPtr, sizeof( struct pcap_file_header )) != sizeof( struct pcap_file_header ))
 74     {
 75         fprintf(stderr,"Unable to read whole pcap file hdr of file\n");
 76         return 0;
 77        }
 78
 79     switch (pcapFileHdrPtr->magic)
 80     {
 81       case PCAP_MAGIC:
 82         break;
 83       default:
 84           {
 85         fprintf(stderr,"Unable to resolve the magic number %d \n",pcapFileHdrPtr->magic);
 86         return 0;
 87           }
 88     }
 89
 90     /* version, snaplen, & linktype magic */
 91     if (pcapFileHdrPtr->version_major != 2)
 92         {
 93         fprintf(stderr,"Unable to resolve the version_major number %d \n",pcapFileHdrPtr->version_major);
 94         return 0;
 95         }
 96
 97
 98     if (pcapFileHdrPtr->linktype != 1)
 99             {
100             fprintf(stderr,"Only could resolve the ethernet linktype packet, not %d \n",pcapFileHdrPtr->linktype);
101             return 0;
102             }
103
104     return 1;
105 }
106
107 void print_pcap_file_header(struct pcap_file_header * pcapFileHdrPtr)
108 {
109   printf("magic number: %X \n",pcapFileHdrPtr->magic);
110   printf("version_major: %d \n",pcapFileHdrPtr->version_major);
111   printf("version_minor: %d \n",pcapFileHdrPtr->version_minor);
112   printf("gmt to local correction: %d \n",pcapFileHdrPtr->thiszone);
113   printf("accuracy of timestamps: %d \n",pcapFileHdrPtr->sigfigs);
114   printf("max snap length: %d \n",pcapFileHdrPtr->snaplen);
115   printf("linktype(1 for ethernet): %d \n",pcapFileHdrPtr->linktype);
116 }
117
118 int
119 pcap_file_get_next_packet(int fd, struct packet *pkt)
120 {
121     struct pcap_pkthdr p1, *p;
122
123     if (read(fd, &p1, sizeof(p1)) != sizeof(p1))
124         return 0;
125     p = &p1;
126
127     pkt->len = p->caplen;
128         /* stupid OpenBSD, won't let me just assign things, so I've got
129          * to use a memcpy() instead
130          */
131     memcpy(&(pkt->ts), &(p->ts), sizeof(time_t));
132     pkt->actual_len = p->len;
133
134     if (read(fd, &pkt->data, pkt->len) != pkt->len)
135        return 0;
136
137     return pkt->len;
138 }
139
140 int pcap_file_print( char * pcapFilePathPtr )
141 {
142     struct pcap_file_header phdr;
143     int packet_counter;
144     struct packet pkt;
145     int fd;
146     int i;
147
148
149     if ( ( fd=open(pcapFilePathPtr,O_RDONLY) )==-1 )
150     {
151       fprintf(stderr,"error: open file error %s",pcapFilePathPtr);
152       return 1;
153     }
154
155     if( is_pcap_file_format(fd,&phdr) )
156     {
157       print_pcap_file_header(&phdr);
158     }
159     else
160     {
161       fprintf(stderr, "error: the file %s is not .pcap format\n",pcapFilePathPtr);
162       return 1;
163     }
164
165     packet_counter=0;
166     while(1)
167     {
168         if(pcap_file_get_next_packet(fd,&pkt))
169         {
170           packet_counter++;
171           printf("snaplen: %d actual_len: %d packet_counter: %d \n",pkt.len,pkt.actual_len,packet_counter);
172           for(i=0; i<pkt.len; ++i)
173           {
174             printf(" %02x", pkt.data[i]);
175             if( (i + 1) % 16 == 0 )
176             {
177               printf("\n");
178             }
179           }
180           printf("\n\n");
181         }
182         else
183         {
184           break;
185         }
186     }
187
188     close(fd);
189     return 0;
190
191 }
192
193
194
195 int build_send_ethernet_packet(const char * dev,const unsigned int sendTimes,
196                    const unsigned char * dst_mac,const unsigned char * src_mac,
197                                const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
198                                )
199 {
200          libnet_t *net_t = NULL;
201          char err_buf[LIBNET_ERRBUF_SIZE];
202          libnet_ptag_t p_tag;
203          unsigned int i=0;
204
205      //init the libnet context structure
206          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
207          if(net_t == NULL)
208          {
209                  fprintf(stderr,"libnet_init error:%s\n",err_buf);
210                  return 1;
211          }
212
213       //build the ethernet packet
214          p_tag = libnet_build_ethernet(//create ethernet header
215                          dst_mac,//dest mac addr
216                          src_mac,//source mac addr
217                          protoType,//protocol type
218                          padPtr,//payload
219                          padLength,//payload length
220                          net_t,//libnet context
221                          0//0 to build a new one
222          );
223          if(-1 == p_tag)
224          {
225                  fprintf(stderr,"libnet_build_ethernet error!\n");
226                  fprintf(stderr,"BuildAndSendEthernetPacket: %s",net_t->err_buf);
227                  goto FAIL;
228          }
229
230          for(i=0;i<sendTimes;i++)
231            if(-1 == libnet_write(net_t))
232            {
233                  fprintf(stderr,"B libnet_write error!\n");
234                  fprintf(stderr,"BuildAndSendEthernetPacket: %s",net_t->err_buf);
235                  goto FAIL;
236            }
237
238          libnet_destroy(net_t);
239          return 0;
240      FAIL:
241          libnet_destroy(net_t);
242          return 1;
243 }
244
245
246 int pcap_ip_repaly( char * pcapFilePathPtr, int usecDelayPerPacket, char * devName)
247 {
248     struct pcap_file_header phdr;
249     struct ethernet_ip_hdr * hdrPtr;
250     int packet_counter;
251     struct packet pkt;
252     int fd;
253     int i;
254
255
256     if ( ( fd=open(pcapFilePathPtr,O_RDONLY) )==-1 )
257     {
258       fprintf(stderr,"error: open file error %s",pcapFilePathPtr);
259       return 1;
260     }
261
262     if( is_pcap_file_format(fd,&phdr) )
263     {
264       print_pcap_file_header(&phdr);
265     }
266     else
267     {
268       fprintf(stderr, "error: the file %s is not .pcap format\n",pcapFilePathPtr);
269       return 1;
270     }
271
272     packet_counter=0;
273     while(1)
274     {
275         if(pcap_file_get_next_packet(fd,&pkt))
276         {
277           usleep(usecDelayPerPacket);
278           packet_counter++;
279           //analyze packet and send it
280           hdrPtr=(struct ethernet_ip_hdr *) pkt.data;
281           if( hdrPtr->ether_type==0x0008) //filter: ip type: 0x0800 -> little endian 0x0008
282               {
283                 // print packet information
284               printf("ether: %02x:%02x:%02x:%02x:%02x:%02x ->",hdrPtr->ether_shost[0],hdrPtr->ether_shost[1]
285                 ,hdrPtr->ether_shost[2],hdrPtr->ether_shost[3],hdrPtr->ether_shost[4],hdrPtr->ether_shost[5]);
286               printf(" %02x:%02x:%02x:%02x:%02x:%02x   ",hdrPtr->ether_dhost[0],hdrPtr->ether_dhost[1]
287                 ,hdrPtr->ether_dhost[2],hdrPtr->ether_dhost[3],hdrPtr->ether_dhost[4],hdrPtr->ether_dhost[5]);
288               printf("ip: %d.%d.%d.%d ->",hdrPtr->ip_src[0],hdrPtr->ip_src[1],hdrPtr->ip_src[2],hdrPtr->ip_src[3]);
289               printf(" %d.%d.%d.%d \n",hdrPtr->ip_dst[0],hdrPtr->ip_dst[1],hdrPtr->ip_dst[2],hdrPtr->ip_dst[3]);
290               if(pkt.len==pkt.actual_len)
291               {
292                 printf("whole packet:padPtr is %x,padLength is %d \n",pkt.data+14,pkt.len-14);
293                     if (build_send_ethernet_packet(devName,1, hdrPtr->ether_dhost,
294                                                hdrPtr->ether_shost,0x0800,pkt.data+14,pkt.len-14)
295                         ==0
296                         )
297                         printf("resend packet success :) \n");
298                     else
299                         printf("resend packet fail :( \n");
300               }
301               else
302               {
303                 fprintf(stderr,"this packet is not entire,cannot resend :(");
304               }
305
306               }
307           else
308            {
309                if(hdrPtr->ether_type==0x0608) //filter: ip type: 0x0806 -> little endian 0x0608
310                  {printf("arp packet \n");}
311                else if(hdrPtr->ether_type==0x3508) //filter: ip type: 0x0835 -> little endian 0x3508
312                  {printf("rarp packet \n");}
313                else
314                     {printf("unknown packet type\n");}
315            }
316           //print packet
317           printf("snaplen: %d actual_len: %d packet_counter: %d \n",pkt.len,pkt.actual_len,packet_counter);
318           for(i=0; i<pkt.len; ++i)
319           {
320             printf(" %02x", pkt.data[i]);
321             if( (i + 1) % 16 == 0 )
322             {
323               printf("\n");
324             }
325           }
326           printf("\n\n");
327         }
328         else
329         {
330           break;
331         }
332     }
333
334     close(fd);
335     return 0;
336
337 }
338
339 int main()
340 {
341   return  pcap_ip_repaly("/home/yun/Codes/wp.pcap",0,"eth0");
342 }

View Code

如有问题或者建议,欢迎留言讨论 :)

转载于:https://www.cnblogs.com/SwordTao/p/3740115.html

IP流量重放与pcap文件格式解析相关推荐

  1. pcap文件格式及文件解析

    pcap文件格式及文件解析 第一部分:PCAP包文件格式 一 基本格式: 文件头 数据包头数据报数据包头数据报...... 二.文件头: 文件头结构体  sturct pcap_file_header ...

  2. Ubuntu 14.04 64bit上解析wireshark抓包pcap文件格式和源码实现

    pcap文件格式是常用的数据报存储格式,包括wireshark在内的主流抓包软件都可以生成这种格式的数据包 下面对这种格式的文件简单分析一下:  pcap文件的格式为:   文件头    24字节   ...

  3. 【Android 逆向】Android 逆向方法 ( 静态逆向解析 | 函数调用分析 | 动态运行跟踪 | 运行日志分析 | 文件格式解析 | 敏感信息分析 | 网络信息监控 | 环境伪装模拟 )

    文章目录 一.Android 逆向方法 1.静态逆向解析 2.函数调用分析 3.动态运行跟踪 4.运行日志分析 5.文件格式解析 6.敏感信息分析 7.网络信息监控 8.软件动态调试 9.环境伪装模拟 ...

  4. cfile清空文件内容_编译-链接-加载 :ELF文件格式解析

    摘要:对于C++的初学者,经常在程序的编译或者加载过程中遇到很多错误,类似undefined reference to ... 和 GLIBCXX_3.4.20 not found 等.这些错误都涉及 ...

  5. 分析ip流量的python脚本

    日志文件格式如下 172.16.225.66 10.71.2.162 1612409 172.16.15.252 10.71.11.31 1210446 172.16.15.252 10.71.11. ...

  6. java 生成.pcap_java抓包后对pcap文件解析示例

    这是自己写的简单的解析pcap文件,方便读取pcap文件,大家参考使用吧 复制代码 代码如下: InputStream is = DataParser.class.getClassLoader().g ...

  7. pcap文件格式及其大文件切割——C语言

    一.Pcap文件格式以及变量类型的选取 这些有很多前辈已经介绍过了,这里就不赘述了.可以参考前辈们的文章,这里推荐两个.https://www.cnblogs.com/caoguoping100/p/ ...

  8. 【网络】流量监控 - iftop|ifstat|查看某个ip流量|tcpdump|iptraf|Linux

    目录 流量监控18个常用工具 tcpdump查看某个端口数据 ifstat iftop 四.运行iftop 五.相关参数及说明 1.iftop界面相关说明 2.iftop相关参数 常用的参数 按端口显 ...

  9. 使用WinPcap和libpcap类库读写pcap文件(002)PCAP文件格式

    本文基本翻译自https://wiki.wireshark.org/Development/LibpcapFileFormat,主要分析pcap文件的格式. 其中一些字段可能和现在的WinPcap类库 ...

最新文章

  1. Maven进价:Maven的安装和目录结构
  2. ASP.NET高质量生成缩略图
  3. python编程面试题
  4. 动作基类 CCAction
  5. win32开发(创建子窗口)
  6. 基于Docker部署Gitlab教程
  7. matlab怎样设置中文界面
  8. 新手简明入门级matlab使用教程
  9. 5个值得收藏的视频下载网站
  10. IT十八掌徐培成第二天笔记
  11. postgresql查看数据库及数据表占用空间
  12. 亲爱的热爱的百度云全集资源
  13. 过年别再逼婚了,《黑镜》里的AI相亲系统是对爱情最好的匹配
  14. Zabbix设置微信报警
  15. 【过分】Python监控小姐姐/小哥哥微博,了解一下??
  16. n阶奇数魔方阵c语言编程,n阶魔方阵C语言
  17. 系统安全: GeneXus 新身份验证方案
  18. 常用MIME类型(Mp4的mime类型设置)
  19. python实习——03
  20. linux环境nutch的配置,linux下nutch的安装配置

热门文章

  1. PTA乙级1014(python3)
  2. [misc]T型知识实践结构的力量
  3. 场景文字识别论文阅读
  4. cad看图软件哪个更好用(免费cad看图软件推荐)
  5. Vue 事件绑定与解绑
  6. mysql 基础语法3
  7. 芮城县县名由来 芮伯庙 古魏城 芮伯万 永乐县
  8. 网易互娱AI研究工程师实习生一面——记人生的第一次面试
  9. 微信公众请求config php,微信公众平台开发之配置与请求_PHP
  10. 内网穿透软件对比——cpolar : 网云穿(下)