Pcap文件头24B各字段说明:
//description: parse wireshark pcap file and write it into local file //platform: Ubuntu 14.04 64bit Desktop version //compile: gcc -g pcap_file_parse.c -o pcap_file_parse //run: ./pcap_file_parse test.pcap //author: [email protected], QQ:48019671 //date: 2014-05-24 #include <pcap.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> #include "pcap_utils.h" //公共函数存放在这里 #define STRSIZE 1024 #define SNAP_LEN 1518 // 以太网帧最大长度 #define SIZE_ETHERNET 14 // 以太网包头长度 mac 6*2, type: 2 #define SIZE_UDP 8 // UDP包头8字节 int main(int argc, char **argv){ if(argc<=1 || argc>2){ printf("Usage: %s <input filename>\n", argv[0]); return 0; } struct pcap_file_header *file_header; struct pcap_pkthdr *ptk_header; struct ether_header *eth_header; struct iphdr *ip_header; struct tcphdr *tcp_header; struct udphdr *udp_header; const char *payload; int size_packet, size_payload, size_ip, size_tcp; FILE *fp, *output; int pkt_offset, i=0; char buf[STRSIZE], capture_time[STRSIZE]; u_char *packet = NULL; if((fp=fopen(argv[1], "r")) == NULL){ printf("Error: can not open input pcap file\n"); exit(0); } if((output=fopen("./output.txt", "w+")) == NULL){ printf("Error: can not open the output file\n"); exit(0); } file_header = (struct pcap_file_header*)malloc(sizeof(struct pcap_file_header)); ptk_header = (struct pcap_pkthdr*)malloc(sizeof(struct pcap_pkthdr)); //validate the pcap file format int read_size = fread(file_header, sizeof(char), 24, fp); if(read_size != 24){ printf("cannot read pcacp file header, invalid format\n"); goto cleanup; } printf("Pcap file header: %X, %hu, %hu, %u, %u\n",file_header->magic,file_header->version_major,file_header->version_minor,file_header->snaplen,file_header->linktype); //allocate a common packet buffer to use packet = (u_char*)malloc(file_header->snaplen * sizeof(char)); pkt_offset = 24; while(fseek(fp, pkt_offset, SEEK_SET) == 0){ i++; memset(buf,0,sizeof(buf)); memset(packet,0,sizeof(packet)); //read pcap packet header if(fread(buf, 16, 1, fp) != 1){ printf("\nPacket No#%d: cannot read pcap_pkt_header of pcap file\n", i); break; } ptk_header->ts.tv_sec = *(bpf_u_int32*)buf; ptk_header->caplen = *(bpf_u_int32*)(buf+8); ptk_header->len = *(bpf_u_int32*)(buf+12); size_packet = ptk_header->caplen; pkt_offset += 16 + size_packet; strftime(capture_time, sizeof(capture_time), "%Y-%m-%d %T", localtime(&(ptk_header->ts.tv_sec))); printf("capture time: %s, packet len: %u\n", capture_time, size_packet); //read a complete packet if(fread(packet, 1, size_packet, fp) != size_packet){ printf("Packet NO.%d: cannot read a whole packet\n", i); break; } eth_header = (struct ether_header*)packet; //read ip frame header ip_header = (struct iphdr *)(packet + SIZE_ETHERNET); size_ip = (ip_header->ihl)*4; /* if (size_ip < 20) { printf("无效的IP头长度: %u bytes\n", size_ip); break; }*/ if ( (ip_header->protocol != IPPROTO_TCP)&&(ip_header->protocol!=IPPROTO_UDP) ){ // TCP,UDP,ICMP,IP continue; } if(ip_header->protocol==IPPROTO_TCP){ /* TCP头 */ tcp_header = (struct tcphdr *)(packet + SIZE_ETHERNET + size_ip); size_tcp = (tcp_header->th_off)*4; if (size_tcp < 20) { printf("无效的TCP头长度: %u bytes\n", size_tcp); break; } int sport = ntohs(tcp_header->th_sport); int dport = ntohs(tcp_header->th_dport); printf("%s:%d -> ", inet_ntoa(*(struct in_addr*)(&ip_header->saddr)), sport); printf("%s:%d ", inet_ntoa(*(struct in_addr*)(&ip_header->daddr)), dport); //内容 payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); //内容长度 size_payload = ntohs(ip_header->tot_len) - (size_ip + size_tcp); if (size_payload > 0) { printf("seq:%d ack:%d flag:%d payload:%d bytes\n", ntohs(tcp_header->th_seq), ntohs(tcp_header->th_ack), ntohs(tcp_header->th_flags), size_payload ); printf("=====================================TCP=====================================\n"); print_payload(payload, size_payload); } }else if(ip_header->protocol==IPPROTO_UDP){ udp_header = (struct udphdr *)(packet + SIZE_ETHERNET + size_ip); int sport = ntohs(udp_header->source); int dport = ntohs(udp_header->dest); printf("%s:%d -> ", inet_ntoa(*(struct in_addr*)(&ip_header->saddr)), sport); printf("%s:%d ", inet_ntoa(*(struct in_addr*)(&ip_header->daddr)), dport); //内容 payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + SIZE_UDP); //内容长度 size_payload = ntohs(ip_header->tot_len) - (size_ip + SIZE_UDP); if (size_payload > 0) { printf("payload:%d bytes\n", size_payload ); printf("=====================================UDP=====================================\n"); print_payload(payload, size_payload); } } } cleanup: if(file_header) free(file_header); if(ptk_header) free(ptk_header); if(packet) free(packet); fclose(fp); fclose(output); return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> /* * 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"); } /* * 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; } } }