[关闭]
@xunuo 2017-07-12T20:54:46.000000Z 字数 7627 阅读 1705

利用winpcap分析以太网协议

网络数据包分析


seq和ack应该有点问题
看不懂就对了?!

  1. #include "pcap.h"
  2. #include<cstdlib>
  3. /*ip地址*/
  4. typedef struct ip_address
  5. {
  6. u_char byte1;
  7. u_char byte2;
  8. u_char byte3;
  9. u_char byte4;
  10. } ip_address;
  11. /*以太网协议头*/
  12. struct ether_header
  13. {
  14. u_int8_t ether_dhost[6]; //目的Mac地址
  15. u_int8_t ether_shost[6]; //源Mac地址
  16. u_int16_t ether_type; //协议类型
  17. };
  18. /*IPv4协议头*/
  19. struct ip_header
  20. {
  21. #if defined(WORDS_BIENDIAN)
  22. u_int8_t ip_version : 4, ip_header_length : 4;
  23. #else
  24. u_int8_t ip_header_length : 4, ip_version : 4;
  25. #endif
  26. u_int8_t ip_tos;
  27. u_int16_t ip_length;
  28. u_int16_t ip_id;
  29. u_int16_t ip_off;
  30. u_int8_t ip_ttl;
  31. u_int8_t ip_protocol;
  32. u_int16_t ip_checksum;
  33. ip_address saddr; /*源地址(Source address)*/
  34. ip_address daddr; /*目的地址(Destination address)*/
  35. };
  36. /*UDP协议头*/
  37. struct udphdr
  38. {
  39. u_int16_t source_port; /*源地址端口*/
  40. u_int16_t dest_port; /*目的地址端口*/
  41. u_int16_t len; /*UDP长度*/
  42. u_int16_t check; /*UDP校验和*/
  43. };
  44. //TCP协议头
  45. #define __LITTLE_ENDIAN_BITFIELD
  46. struct tcphdr
  47. {
  48. u_int16_t source_port; /*源地址端口*/
  49. u_int16_t dest_port; /*目的地址端口*/
  50. u_int32_t seq; /*序列号*/
  51. u_int32_t ack_seq; /*确认序列号*/
  52. u_int8_t tcp_header_length : 4;
  53. #if defined(__LITTLE_ENDIAN_BITFIELD)
  54. u_int16_t res1 : 4, /*保留*/
  55. doff : 4, /*偏移*/
  56. fin : 1, /*关闭连接标志*/
  57. syn : 1, /*请求连接标志*/
  58. rst : 1, /*重置连接标志*/
  59. psh : 1, /*接收方尽快将数据放到应用层标志*/
  60. ack : 1, /*确认序号标志*/
  61. urg : 1, /*紧急指针标志*/
  62. ece : 1, /*拥塞标志位*/
  63. cwr : 1; /*拥塞标志位*/
  64. #elif defined(__BIG_ENDIAN_BITFIELD)
  65. u_int16_t doff : 4, /*偏移*/
  66. res1 : 4, /*保留*/
  67. cwr : 1, /*拥塞标志位*/
  68. ece : 1, /*拥塞标志位*/
  69. urg : 1, /*紧急指针标志*/
  70. ack : 1, /*确认序号标志*/
  71. psh : 1, /*接收方尽快将数据放到应用层标志*/
  72. rst : 1, /*重置连接标志*/
  73. syn : 1, /*请求连接标志*/
  74. fin : 1; /*关闭连接标志*/
  75. #else
  76. u_int16_t flag;
  77. #endif
  78. u_int16_t window; /*滑动窗口大小*/
  79. u_int16_t check; /*校验和*/
  80. u_int16_t urg_ptr; /*紧急字段指针*/
  81. };
  82. //UDP协议分析
  83. void udp_protool_packet_callback(u_char *argument, const struct pcap_pkthdr* packet_header, const u_char* packet_content)
  84. {
  85. struct udphdr *udp_protocol;
  86. u_int header_length = 0;
  87. u_int16_t checksum;
  88. udp_protocol = (struct udphdr *) packet_content;
  89. checksum = ntohs(udp_protocol->check);
  90. u_int16_t source_port; /*源地址端口*/
  91. u_int16_t dest_port; /*目的地址端口*/
  92. u_int16_t len; /*UDP长度*/
  93. u_int16_t check; /*UDP校验和*/
  94. printf("---------UDP协议---------\n");
  95. printf("源端口:%d\n", ntohs(udp_protocol->source_port));
  96. printf("目的端口:%d\n", ntohs(udp_protocol->dest_port));
  97. printf("UDP数据包长度:%d\n", ntohs(udp_protocol->len));
  98. printf("UDP校验和:%d\n", checksum);
  99. }
  100. //TCP协议分析
  101. void tcp_protool_packet_callback(u_char *argument, const struct pcap_pkthdr* packet_header, const u_char* packet_content)
  102. {
  103. struct tcphdr *tcp_protocol;
  104. u_int header_length = 0;
  105. u_int offset;
  106. u_char tos;
  107. u_int16_t checksum;
  108. tcp_protocol = (struct tcphdr *) packet_content;
  109. checksum = ntohs(tcp_protocol->check);
  110. printf("---------TCP协议---------\n");
  111. printf("源端口:%d\n", ntohs(tcp_protocol->source_port));
  112. printf("目的端口:%d\n", ntohs(tcp_protocol->dest_port));
  113. printf("SEQ:%d\n", ntohl(tcp_protocol->seq));
  114. printf("ACK SEQ:%d\n", ntohl(tcp_protocol->ack_seq));
  115. printf("TCP校验和:%d\n", checksum);
  116. if (ntohs(tcp_protocol->source_port) == 80 || ntohs(tcp_protocol->dest_port) == 80)//http协议
  117. printf("http data:\n%s\n", packet_content + sizeof(tcphdr));
  118. }
  119. //IP协议分析
  120. void ip_protool_packet_callback(u_char *argument, const struct pcap_pkthdr* packet_header, const u_char* packet_content)
  121. {
  122. struct ip_header *ip_protocol;
  123. u_int offset;
  124. u_char tos;
  125. u_int16_t checksum;
  126. ip_protocol = (struct ip_header *)packet_content;
  127. checksum = ntohs(ip_protocol->ip_checksum);
  128. tos = ip_protocol->ip_tos;
  129. offset = ntohs(ip_protocol->ip_off);
  130. printf("---------IP协议---------\n");
  131. printf("版本号:%d\n", ip_protocol->ip_version);
  132. printf("首部长度:%d\n", ip_protocol->ip_header_length);
  133. printf("服务质量:%d\n", tos);
  134. printf("总长度:%d\n", ntohs(ip_protocol->ip_length));
  135. printf("标识:%d\n", ntohs(ip_protocol->ip_id));
  136. printf("偏移:%d\n", (offset & 0x1fff) * 8);
  137. printf("生存时间:%d\n", ip_protocol->ip_ttl);
  138. printf("协议类型:%d\n", ip_protocol->ip_protocol);
  139. printf("检验和:%d\n", checksum);
  140. printf("源IP地址:%d.%d.%d.%d\n", ip_protocol->saddr.byte1, ip_protocol->saddr.byte2, ip_protocol->saddr.byte3, ip_protocol->saddr.byte4);
  141. printf("目的地址:%d.%d.%d.%d\n", ip_protocol->daddr.byte1, ip_protocol->daddr.byte2, ip_protocol->daddr.byte3, ip_protocol->daddr.byte4);
  142. switch (ip_protocol->ip_protocol)
  143. {
  144. case 1: printf("上层协议是ICMP协议\n"); break;
  145. case 2: printf("上层协议是IGMP协议\n"); break;
  146. case 6:
  147. {
  148. printf("上层协议是TCP协议\n");
  149. tcp_protool_packet_callback(argument, packet_header, packet_content + sizeof(ip_header));
  150. }
  151. break;
  152. case 17:
  153. {
  154. printf("上层协议是UDP协议\n");
  155. udp_protool_packet_callback(argument, packet_header, packet_content + sizeof(ip_header));
  156. }
  157. break;
  158. default:break;
  159. }
  160. }
  161. //以太网协议分析
  162. void ethernet_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr* packet_header, const u_char* packet_content)
  163. {
  164. u_short ethernet_type;
  165. struct ether_header *ethernet_protocol;
  166. u_char *mac_string;
  167. static int packet_number = 1;
  168. printf("----------------------------------------------\n");
  169. printf("捕获第%d个网络数据包\n", packet_number);
  170. printf("该数据包的具体内容:\n");
  171. for (int i = 1; i <= packet_header->len; i++)
  172. {
  173. printf("%02x ", packet_content[i - 1]);
  174. if (i % 8 == 0)
  175. printf(" ");
  176. if (i % 16 == 0)
  177. printf("\n");
  178. }
  179. printf("\n");
  180. printf("数据包长度:%d\n", packet_header->len);
  181. printf("---------以太网协议---------\n");
  182. ethernet_protocol = (struct ether_header*)packet_content;//获得数据包内容
  183. ethernet_type = ntohs(ethernet_protocol->ether_type);//获得以太网类型
  184. printf("以太网类型:%04x\n", ethernet_type);
  185. mac_string = ethernet_protocol->ether_shost;
  186. printf("MAC帧源地址:%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
  187. mac_string = ethernet_protocol->ether_dhost;
  188. printf("MAC帧目的地址:%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
  189. switch (ethernet_type)
  190. {
  191. case 0x0800:
  192. {
  193. ip_protool_packet_callback(argument, packet_header, packet_content + sizeof(ether_header));
  194. printf("上层协议是IPv4协议\n");
  195. }
  196. break;
  197. case 0x0806:
  198. printf("上层协议是ARP协议\n");
  199. break;
  200. case 0x8035:
  201. printf("上层协议是RARP协议\n");
  202. break;
  203. case 0x814C:
  204. printf("上层协议是简单网络管理协议SNMP\n");
  205. break;
  206. case 0x8137:
  207. printf("上层协议是因特网包交换(IPX:Internet Packet Exchange)\n");
  208. break;
  209. case 0x86DD:
  210. printf("上层协议是IPv6协议\n");
  211. break;
  212. case 0x880B:
  213. printf("上层协议是点对点协议(PPP:Point-to-Point Protocol)\n");
  214. break;
  215. default:break;
  216. }
  217. printf("----------------------------------------------\n");
  218. packet_number++;
  219. }
  220. int main()
  221. {
  222. pcap_if_t * allAdapters; //适配器列表
  223. pcap_if_t * adapter; //跑适配器列表
  224. pcap_t * adapterHandle; //适配器句柄
  225. //char error_content[PCAP_ERRBUF_SIZE]; //存储错误信息
  226. bpf_u_int32 net_mask = 0; //掩码地址
  227. bpf_u_int32 net_ip = 0; //网络地址
  228. char *net_interface; //网络接口
  229. struct bpf_program bpf_filter; //BPF过滤规则
  230. char bpf_filter_string[] = "ip"; //过滤规则字符串,只分析IPv4的数据包
  231. char errorBuffer[PCAP_ERRBUF_SIZE]; //错误信息缓冲区
  232. if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,&allAdapters, errorBuffer) == -1) //检索机器连接的所有网络适配器
  233. {
  234. fprintf(stderr, "Error in pcap_findalldevs_ex function: %s\n", errorBuffer);
  235. return -1;
  236. }
  237. if (allAdapters == NULL) //不存在任何适配器
  238. {
  239. printf("\nNo adapters found! Make sure WinPcap is installed.\n");
  240. return 0;
  241. }
  242. int crtAdapter = 0;
  243. for (adapter = allAdapters; adapter != NULL; adapter = adapter->next)
  244. { //遍历输入适配器信息(名称和描述信息)
  245. printf("\n%d.%s ", ++crtAdapter, adapter->name);
  246. printf("-- %s\n", adapter->description);
  247. }
  248. printf("\n");
  249. int adapterNumber;
  250. printf("Enter the adapter number between 1 and %d:", crtAdapter);//选择要捕获数据包的适配器
  251. scanf_s("%d", &adapterNumber);
  252. if (adapterNumber < 1 || adapterNumber > crtAdapter)
  253. {
  254. printf("\nAdapter number out of range.\n");
  255. pcap_freealldevs(allAdapters);// 释放适配器列表
  256. return -1;
  257. }
  258. adapter = allAdapters;
  259. for (crtAdapter = 0; crtAdapter < adapterNumber - 1; crtAdapter++)
  260. adapter = adapter->next;
  261. adapterHandle = pcap_open(adapter->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errorBuffer);// 打开指定适配器
  262. if (adapterHandle == NULL)//指定适配器打开失败
  263. {
  264. fprintf(stderr, "\nUnable to open the adapter\n", adapter->name);
  265. pcap_freealldevs(allAdapters);// 释放适配器列表
  266. return -1;
  267. }
  268. char errbuf[2048];
  269. pcap_createsrcstr(NULL, 0, NULL, "80", NULL, errbuf);
  270. printf("\nCapture session started on adapter %s\n", adapter->name);
  271. pcap_freealldevs(allAdapters);//释放适配器列表
  272. pcap_compile(adapterHandle, &bpf_filter, bpf_filter_string, 0, net_ip); //编译过滤规则
  273. pcap_setfilter(adapterHandle, &bpf_filter);//设置过滤规则
  274. if (pcap_datalink(adapterHandle) != DLT_EN10MB) //DLT_EN10MB表示以太网
  275. return 0;
  276. pcap_loop(adapterHandle, 30, ethernet_protocol_packet_callback, NULL); //捕获65536个数据包进行分析
  277. pcap_close(adapterHandle);
  278. return 0;
  279. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注