[关闭]
@xunuo 2017-07-12T12:26:13.000000Z 字数 3739 阅读 1257

利用winpcap分析ARP协议


网络数据包分析


  1. #include <cstdlib>
  2. #include <pcap.h>
  3. /*ARP头*/
  4. struct ArpHeader
  5. {
  6. unsigned short hdtyp; //硬件类型
  7. unsigned short protyp; //协议类型
  8. unsigned char hdsize; //硬件地址长度
  9. unsigned char prosize; //协议地址长度
  10. unsigned short op; //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。
  11. u_char smac[6]; //源MAC地址
  12. u_char sip[4]; //源IP地址
  13. u_char dmac[6]; //目的MAC地址
  14. u_char dip[4]; //目的IP地址
  15. };
  16. int main()
  17. {
  18. pcap_if_t *alldevs; //所有网络适配器
  19. pcap_if_t *d; //选中的网络适配器
  20. int inum; //选择网络适配器
  21. int i = 0; //for循环变量
  22. pcap_t *adhandle; //打开网络适配器,捕捉实例,是pcap_open返回的对象
  23. char errbuf[PCAP_ERRBUF_SIZE]; //错误缓冲区,大小为256
  24. int res; //抓包函数pcap_next_ex返回值,1-成功、0:获取报文超时、-1:发生错误、-2: 获取到离线记录文件的最后一个报文
  25. u_int netmask; //子网掩码
  26. //ether proto protocol:如果数据包属于某些以太协议(protocol)类型, 则与此对应的条件表达式为真,协议字段可以是ARP
  27. char packet_filter[] = "ether proto \\arp"; //要抓取的包的类型,这里是抓取ARP包;
  28. struct bpf_program fcode; //pcap_compile所调用的结构体
  29. //struct tm *ltime; //和时间处理有关的变量
  30. //char timestr[16]; //和时间处理有关的变量
  31. //time_t local_tv_sec; //和时间处理有关的变量
  32. struct pcap_pkthdr *header; //接收到的数据包的头部
  33. const u_char *pkt_data; //接收到的数据包的
  34. /* 获取本机设备列表 */
  35. if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
  36. {
  37. fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
  38. exit(1);
  39. }
  40. /* 打印列表 */
  41. for (d = alldevs; d; d = d->next)
  42. {
  43. printf("%d. %s", ++i, d->name);
  44. if (d->description)
  45. printf(" (%s)\n", d->description);
  46. else
  47. printf(" (No description available)\n");
  48. }
  49. if (i == 0)
  50. {
  51. printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
  52. return -1;
  53. }
  54. printf("Enter the interface number (1-%d):", i);
  55. scanf_s("%d", &inum);
  56. if (inum < 1 || inum > i)
  57. {
  58. printf("\nInterface number out of range.\n");
  59. /* 释放设备列表 */
  60. pcap_freealldevs(alldevs);
  61. return -1;
  62. }
  63. /* 跳转到已选中的适配器 */
  64. for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
  65. /* 打开设备 */
  66. if ((adhandle = pcap_open(d->name, // 设备名
  67. 65536, // 要捕捉的数据包的部分
  68. // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
  69. PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式
  70. 1000, // 读取超时时间
  71. NULL, // 远程机器验证
  72. errbuf // 错误缓冲池
  73. )) == NULL)
  74. {
  75. fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
  76. /* 释放设列表 */
  77. pcap_freealldevs(alldevs);
  78. return -1;
  79. }
  80. /* 检查数据链路层,为了简单,我们只考虑以太网 */
  81. if (pcap_datalink(adhandle) != DLT_EN10MB)
  82. {
  83. fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
  84. /* 释放设备列表 */
  85. pcap_freealldevs(alldevs);
  86. return -1;
  87. }
  88. if (d->addresses != NULL)
  89. /* 获得接口第一个地址的掩码 */
  90. netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  91. else
  92. netmask = 0xffffff; /* 如果接口没有地址,那么我们假设一个C类的掩码 */
  93. if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)//编译过滤器
  94. {
  95. fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
  96. /* 释放设备列表 */
  97. pcap_freealldevs(alldevs);
  98. return -1;
  99. }
  100. if (pcap_setfilter(adhandle, &fcode) < 0)//设置过滤器
  101. {
  102. fprintf(stderr, "\nError setting the filter.\n");
  103. /* 释放设备列表 */
  104. pcap_freealldevs(alldevs);
  105. return -1;
  106. }
  107. printf("\nlistening on %s...\n", d->description);
  108. /* 释放设备列表 */
  109. pcap_freealldevs(alldevs);
  110. /*以上代码在WinPcap开发文档中都可以找到,解析ARP包的代码则要自己编写*/
  111. /* 获取数据包 */
  112. while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0)
  113. {
  114. if (res == 0)/* 超时时间到 */
  115. continue;
  116. /*解析ARP包*/
  117. ArpHeader* arph = (ArpHeader *)(pkt_data + 14);
  118. printf("报文类型:");//类型
  119. if (ntohs(arph->op)==1)
  120. printf("请求报文\n");
  121. else
  122. printf("应答报文\n");
  123. printf("数据包具体内容:\n");
  124. for (int i = 1; i < header->len; i++)
  125. {
  126. printf("%02x ", pkt_data[i - 1]);
  127. if (i % 8 == 0)
  128. printf(" ");
  129. if (i % 16 == 0)
  130. printf("\n");
  131. }
  132. printf("\n长度(B):%d\n", header->len);//长度
  133. printf("源IP:");
  134. for (i = 0; i <=3; i++)
  135. {
  136. if(i==3)
  137. printf("%d\n", arph->sip[3]);
  138. else
  139. printf("%d.", arph->sip[i]);
  140. }
  141. printf("目的IP:");
  142. for (i = 0; i <=3; i++)
  143. {
  144. if(i==3)
  145. printf("%d\n", arph->dip[3]);
  146. else
  147. printf("%d.", arph->dip[i]);
  148. }
  149. printf("源MAC:");
  150. for (i = 0; i <=5; i++)
  151. {
  152. if(i==5)
  153. printf("%02x\n", arph->smac[5]);
  154. else
  155. printf("%02x-", arph->smac[i]);
  156. }
  157. printf("目的MAC:");
  158. for (i = 0; i <=5; i++)
  159. {
  160. if(i==5)
  161. printf("%02x\n", *(pkt_data + 5));
  162. else
  163. printf("%02x-", *(pkt_data + i));
  164. }
  165. if (ntohs(arph->hdtyp) == 1)
  166. printf("硬件类型:Ethernet\n");
  167. printf("协议类型:%04x\n", ntohs(arph->protyp));
  168. printf("硬件长度:%d\n", arph->hdsize);
  169. printf("协议长度%d\n", arph->prosize);
  170. printf("操作类型:%d\n", ntohs(arph->op));
  171. printf("\n\n");
  172. }
  173. if (res == -1) //接收ARP包出错
  174. {
  175. printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
  176. return -1;
  177. }
  178. return 0;
  179. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注