IP流量重放与pcap文件格式解析
(作者:燕云 出处: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文件格式解析相关推荐
- pcap文件格式及文件解析
pcap文件格式及文件解析 第一部分:PCAP包文件格式 一 基本格式: 文件头 数据包头数据报数据包头数据报...... 二.文件头: 文件头结构体 sturct pcap_file_header ...
- Ubuntu 14.04 64bit上解析wireshark抓包pcap文件格式和源码实现
pcap文件格式是常用的数据报存储格式,包括wireshark在内的主流抓包软件都可以生成这种格式的数据包 下面对这种格式的文件简单分析一下: pcap文件的格式为: 文件头 24字节 ...
- 【Android 逆向】Android 逆向方法 ( 静态逆向解析 | 函数调用分析 | 动态运行跟踪 | 运行日志分析 | 文件格式解析 | 敏感信息分析 | 网络信息监控 | 环境伪装模拟 )
文章目录 一.Android 逆向方法 1.静态逆向解析 2.函数调用分析 3.动态运行跟踪 4.运行日志分析 5.文件格式解析 6.敏感信息分析 7.网络信息监控 8.软件动态调试 9.环境伪装模拟 ...
- cfile清空文件内容_编译-链接-加载 :ELF文件格式解析
摘要:对于C++的初学者,经常在程序的编译或者加载过程中遇到很多错误,类似undefined reference to ... 和 GLIBCXX_3.4.20 not found 等.这些错误都涉及 ...
- 分析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. ...
- java 生成.pcap_java抓包后对pcap文件解析示例
这是自己写的简单的解析pcap文件,方便读取pcap文件,大家参考使用吧 复制代码 代码如下: InputStream is = DataParser.class.getClassLoader().g ...
- pcap文件格式及其大文件切割——C语言
一.Pcap文件格式以及变量类型的选取 这些有很多前辈已经介绍过了,这里就不赘述了.可以参考前辈们的文章,这里推荐两个.https://www.cnblogs.com/caoguoping100/p/ ...
- 【网络】流量监控 - iftop|ifstat|查看某个ip流量|tcpdump|iptraf|Linux
目录 流量监控18个常用工具 tcpdump查看某个端口数据 ifstat iftop 四.运行iftop 五.相关参数及说明 1.iftop界面相关说明 2.iftop相关参数 常用的参数 按端口显 ...
- 使用WinPcap和libpcap类库读写pcap文件(002)PCAP文件格式
本文基本翻译自https://wiki.wireshark.org/Development/LibpcapFileFormat,主要分析pcap文件的格式. 其中一些字段可能和现在的WinPcap类库 ...
最新文章
- Maven进价:Maven的安装和目录结构
- ASP.NET高质量生成缩略图
- python编程面试题
- 动作基类 CCAction
- win32开发(创建子窗口)
- 基于Docker部署Gitlab教程
- matlab怎样设置中文界面
- 新手简明入门级matlab使用教程
- 5个值得收藏的视频下载网站
- IT十八掌徐培成第二天笔记
- postgresql查看数据库及数据表占用空间
- 亲爱的热爱的百度云全集资源
- 过年别再逼婚了,《黑镜》里的AI相亲系统是对爱情最好的匹配
- Zabbix设置微信报警
- 【过分】Python监控小姐姐/小哥哥微博,了解一下??
- n阶奇数魔方阵c语言编程,n阶魔方阵C语言
- 系统安全: GeneXus 新身份验证方案
- 常用MIME类型(Mp4的mime类型设置)
- python实习——03
- linux环境nutch的配置,linux下nutch的安装配置