当前位置:   article > 正文

C语言解析pcap数据包格式_struct pcap

struct pcap

通过tcpdump命令或者wireshark抓取数据包。

如下图所示:

pcap文件格式: 24字节pcap文件头+(16字节pcap数据包头+数据包)*n

 

解析源码如下:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. #include<netinet/in.h>
  5. #include<time.h>
  6. #define BUFSIZE 10240
  7. #define STRSIZE 1024
  8. #define FILE_NAME "test.pcap"
  9. typedef int32_t bpf_int32;
  10. typedef u_int32_t bpf_u_int32;
  11. typedef u_int16_t u_short;
  12. typedef u_int32_t u_int32;
  13. typedef u_int16_t u_int16;
  14. typedef u_int8_t u_int8;
  15. //pacp文件头结构体
  16. struct pcap_file_header
  17. {
  18. bpf_u_int32 magic; /* 0xa1b2c3d4 */
  19. u_short version_major; /* magjor Version 2 */
  20. u_short version_minor; /* magjor Version 4 */
  21. bpf_int32 thiszone; /* gmt to local correction */
  22. bpf_u_int32 sigfigs; /* accuracy of timestamps */
  23. bpf_u_int32 snaplen; /* max length saved portion of each pkt */
  24. bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
  25. };
  26. //时间戳
  27. struct time_val
  28. {
  29. int tv_sec; /* seconds 含义同 time_t 对象的值 */
  30. int tv_usec; /* and microseconds */
  31. };
  32. //pcap数据包头结构体
  33. struct pcap_pkthdr
  34. {
  35. struct time_val ts; /* time stamp */
  36. bpf_u_int32 caplen; /* length of portion present */
  37. bpf_u_int32 len; /* length this packet (off wire) */
  38. };
  39. //数据帧头
  40. typedef struct FramHeader_t
  41. { //Pcap捕获的数据帧头
  42. u_int8 DstMAC[6]; //目的MAC地址
  43. u_int8 SrcMAC[6]; //源MAC地址
  44. u_short FrameType; //帧类型
  45. } FramHeader_t;
  46. //IP数据报头
  47. typedef struct IPHeader_t
  48. { //IP数据报头
  49. u_int8 Ver_HLen; //版本+报头长度
  50. u_int8 TOS; //服务类型
  51. u_int16 TotalLen; //总长度
  52. u_int16 ID; //标识
  53. u_int16 Flag_Segment; //标志+片偏移
  54. u_int8 TTL; //生存周期
  55. u_int8 Protocol; //协议类型
  56. u_int16 Checksum; //头部校验和
  57. u_int32 SrcIP; //源IP地址
  58. u_int32 DstIP; //目的IP地址
  59. } IPHeader_t;
  60. //TCP数据报头
  61. typedef struct TCPHeader_t
  62. { //TCP数据报头
  63. u_int16 SrcPort; //源端口
  64. u_int16 DstPort; //目的端口
  65. u_int32 SeqNO; //序号
  66. u_int32 AckNO; //确认号
  67. u_int8 HeaderLen; //数据报头的长度(4 bit) + 保留(4 bit)
  68. u_int8 Flags; //标识TCP不同的控制消息
  69. u_int16 Window; //窗口大小
  70. u_int16 Checksum; //校验和
  71. u_int16 UrgentPointer; //紧急指针
  72. }TCPHeader_t;
  73. void match_http(FILE *fp, char *head_str, char *tail_str, char *buf, int total_len); //查找 http 信息函数
  74. int main()
  75. {
  76. struct pcap_file_header *file_header;
  77. struct pcap_pkthdr *ptk_header;
  78. FramHeader_t *mac_header;
  79. IPHeader_t *ip_header;
  80. TCPHeader_t *tcp_header;
  81. FILE *fp, *output;
  82. int pkt_offset, i = 0;
  83. int ip_len, http_len, ip_proto;
  84. int src_port, dst_port, tcp_flags;
  85. char buf[BUFSIZE], my_time[STRSIZE];
  86. char src_ip[STRSIZE], dst_ip[STRSIZE];
  87. char host[STRSIZE], uri[BUFSIZE];
  88. //初始化
  89. //file_header = (struct pcap_file_header *)malloc(sizeof(struct pcap_file_header));
  90. ptk_header = (struct pcap_pkthdr *)malloc(sizeof(struct pcap_pkthdr));
  91. mac_header = (FramHeader_t *)malloc(sizeof(FramHeader_t));
  92. ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t));
  93. tcp_header = (TCPHeader_t *)malloc(sizeof(TCPHeader_t));
  94. /*memset(buf, 0, sizeof(buf));*/
  95. //
  96. if ((fp = fopen(FILE_NAME, "r")) == NULL)
  97. {
  98. printf("error: can not open pcap file\n");
  99. exit(0);
  100. }
  101. /*if ((output = fopen("output.txt", "w+")) == NULL)
  102. {
  103. printf("error: can not open output file\n");
  104. exit(0);
  105. }*/
  106. //开始读数据包
  107. pkt_offset = 24; //pcap文件头结构 24个字节
  108. while (fseek(fp, pkt_offset, SEEK_SET) == 0) //遍历数据包
  109. {
  110. i++;
  111. //pcap_pkt_header 16 byte
  112. memset(ptk_header, 0, sizeof(struct pcap_pkthdr));
  113. if (fread(ptk_header, 16, 1, fp) != 1) //读pcap数据包头结构
  114. {
  115. printf("\nread end of pcap file\n");
  116. break;
  117. }
  118. pkt_offset += 16 + ptk_header->caplen; //下一个数据包的偏移值
  119. //读取pcap包时间戳,转换成标准格式时间
  120. struct tm *timeinfo;
  121. time_t t = (time_t)(ptk_header->ts.tv_sec);
  122. timeinfo = localtime(&t);
  123. strftime(my_time, sizeof(my_time), "%Y-%m-%d %H:%M:%S", timeinfo); //获取时间
  124. //printf("%s\n", my_time);
  125. //数据帧头 14字节
  126. fseek(fp, 14, SEEK_CUR); //忽略数据帧头
  127. //IP数据报头 20字节
  128. memset(ip_header, 0, sizeof(IPHeader_t));
  129. if (fread(ip_header, sizeof(IPHeader_t), 1, fp) != 1)
  130. {
  131. printf("%d: can not read ip_header\n", i);
  132. break;
  133. }
  134. inet_ntop(AF_INET, (void *)&(ip_header->SrcIP), src_ip, 16);
  135. inet_ntop(AF_INET, (void *)&(ip_header->DstIP), dst_ip, 16);
  136. ip_proto = ip_header->Protocol;
  137. printf("time:%s, src_ip:%s, dst_ip:%s, ip protocol:%d\n",my_time, src_ip, dst_ip, ip_proto);
  138. ip_len = ip_header->TotalLen; //IP数据报总长度
  139. /*
  140. if (ip_proto != 6) //判断是否是 TCP 协议
  141. {
  142. continue;
  143. }
  144. //TCP头 20字节
  145. if (fread(tcp_header, sizeof(TCPHeader_t), 1, fp) != 1)
  146. {
  147. printf("%d: can not read ip_header\n", i);
  148. break;
  149. }
  150. printf("AAA\n");
  151. src_port = ntohs(tcp_header->SrcPort);
  152. dst_port = ntohs(tcp_header->DstPort);
  153. tcp_flags = tcp_header->Flags;
  154. // printf("%d: src=%x\n", i, tcp_flags);
  155. //if (tcp_flags == 0×18) // (PSH, ACK) 3路握手成功后
  156. //{
  157. // if (dst_port == 80) // HTTP GET请求
  158. // {
  159. // http_len = ip_len – 40; //http 报文长度
  160. // match_http(fp, "Host: ", "\r\n", host, http_len); //查找 host 值
  161. // match_http(fp, "GET ", "HTTP", uri, http_len); //查找 uri 值
  162. // sprintf(buf, "%d: %s src = %s : %d dst = %s : %d %s%s\r\n", i, my_time, src_ip, src_port, dst_ip, dst_port, host, uri);
  163. // //printf("%s", buf);
  164. // if (fwrite(buf, strlen(buf), 1, output) != 1)
  165. // {
  166. // printf("output file can not write");
  167. // break;
  168. // }
  169. // }
  170. //}
  171. */
  172. } // end while
  173. fclose(fp);
  174. //fclose(output);
  175. //free(file_header);
  176. free(ptk_header);
  177. free(ip_header);
  178. free(tcp_header);
  179. return 0;
  180. }
  181. //查找 HTTP 信息
  182. void match_http(FILE *fp, char *head_str, char *tail_str, char *buf, int total_len)
  183. {
  184. int i;
  185. int http_offset;
  186. int head_len, tail_len, val_len;
  187. char head_tmp[STRSIZE], tail_tmp[STRSIZE];
  188. //初始化
  189. memset(head_tmp, 0, sizeof(head_tmp));
  190. memset(tail_tmp, 0, sizeof(tail_tmp));
  191. head_len = strlen(head_str);
  192. tail_len = strlen(tail_str);
  193. //查找 head_str
  194. http_offset = ftell(fp); //记录下HTTP报文初始文件偏移
  195. while ((head_tmp[0] = fgetc(fp)) != EOF) //逐个字节遍历
  196. {
  197. if ((ftell(fp) - http_offset) > total_len)//遍历完成
  198. {
  199. sprintf(buf, "can not find %s \r\n", head_str);
  200. exit(0);
  201. }
  202. if (head_tmp[0] == *head_str) //匹配到第一个字符
  203. {
  204. for (i = 1; i<head_len; i++) //匹配 head_str 的其他字符
  205. {
  206. head_tmp[i] = fgetc(fp);
  207. if (head_tmp[i] != *(head_str + i))
  208. break;
  209. }
  210. if (i == head_len) //匹配 head_str 成功,停止遍历
  211. break;
  212. }
  213. }
  214. // printf("head_tmp=%s \n", head_tmp);
  215. //查找 tail_str
  216. val_len = 0;
  217. while ((tail_tmp[0] = fgetc(fp)) != EOF) //遍历
  218. {
  219. if ((ftell(fp) - http_offset) > total_len) //遍历完成
  220. {
  221. sprintf(buf, "can not find %s \r\n", tail_str);
  222. exit(0);
  223. }
  224. buf[val_len++] = tail_tmp[0]; //用buf 存储 value 直到查找到 tail_str
  225. if (tail_tmp[0] == *tail_str) //匹配到第一个字符
  226. {
  227. for (i = 1; i<tail_len; i++) //匹配 head_str 的其他字符
  228. {
  229. tail_tmp[i] = fgetc(fp);
  230. if (tail_tmp[i] != *(tail_str + i))
  231. break;
  232. }
  233. if (i == tail_len) //匹配 head_str 成功,停止遍历
  234. {
  235. buf[val_len - 1] = 0; //清除多余的一个字符
  236. break;
  237. }
  238. }
  239. }
  240. // printf("val=%s\n", buf);
  241. fseek(fp, http_offset, SEEK_SET); //将文件指针 回到初始偏移
  242. }

编译执行之后:

完!

 

总结:以上代码主要是读取pcap包,获取到网络层的数据,再继续做下去就要根据具体四层协议进行解析。

 

参考:

https://www.cnblogs.com/wocgcow/p/8473736.html

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号