基于WINPCAP的网络通信

实验名称:基于WINPCAP的网络通信

实验目的:

熟练掌握基于WinpCap的网络数据包捕获及数据发送方法

实验要求:第一题,至少显示数据包的源IP,目的IP,源端口,目的端口及协议及TCP或UDP数据部分的10个字节的数据。

实验内容:

  • 1、修改老师给的WinpCap程序,可以捕获TCP和UDP通信,显示数据包相关数据。(必须完成)
  • 2、修改老师给的winpcapsend程序,完成TCP三次握手( winpcapsend程序只完成了两次握手),用wireshark查看,是否正常完成三次,同时查看wireshark上显示的端口号、IP地址等是否和你的程序的端口号、IP地址一致。

实验结果:

窗体顶端

  1. // winpcap.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include "stdafx.h"
  5.  
  6. #include "include/pcap.h"
  7. #include "winpcap.h"
  8. #pragma comment(lib "ws2_32.lib");
  9. #pragma comment (lib "packet.lib")
  10. #pragma comment (lib "wpcap.lib")
  11. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
  12.  
  13.  
  14. int main(int argc, char* argv[])
  15. {
  16.    pcap_if_t *alldevs;
  17.    pcap_if_t *d;
  18.    int inum;
  19.    int i=0;
  20.    pcap_t *adhandle;
  21.    char errbuf[PCAP_ERRBUF_SIZE];
  22.    u_int netmask;
  23.    char packet_filter[] = "ip and udp";
  24.    struct bpf_program fcode;
  25.  
  26.    /* 获取设备列表 */
  27.    if(pcap_findalldevs(&alldevs, errbuf) == -1)
  28.    {
  29.             fprintf(stderr,"pcap_findalldevs函数调用错误: %s\n", errbuf);
  30.             return 1;;
  31.    }
  32.  
  33.    /* 打印设备列表 */
  34.    for(d=alldevs; d; d=d->next)
  35.    {
  36.             printf("%d. %s", ++i, d->name);
  37.             if (d->description)
  38.                     printf(" (%s)\n", d->description);
  39.             else
  40.                     printf(" (没有可用的描述符)\n");
  41.    }
  42.  
  43.    if(i==0)
  44.    {
  45.             printf("\n无法找到网络接口!请确认WinPcap已正确安装.\n");
  46.             return -1;
  47.    }
  48.  
  49.    printf("请待捕获数据的输入网卡编号 (1-%d):",i);
  50.    scanf("%d", &inum);
  51.  
  52.    /* 检查用户输入的网卡编号是否合法 */
  53.    if(inum < 1 || inum > i)
  54.    {
  55.             printf("\nAdapter number out of range.\n");
  56.  
  57.             /* 释放设备列表 */
  58.             pcap_freealldevs(alldevs);
  59.             return -1;
  60.    }
  61.  
  62.    /* 跳转到用户选择的网卡 */
  63.    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
  64.  
  65.    /* 打开网卡 */
  66.    adhandle= pcap_open_live(d->name,                 // 设备名
  67.                         65536,                        // 保证能捕获到不同数据链路层上的每个数据包的全部内容
  68.                         1,                            // 混杂模式
  69.                         1000,                         // 读取超时时间
  70.                         errbuf                        // 错误缓冲池
  71.                         );
  72.     if ( adhandle == NULL)
  73.    {
  74.             fprintf(stderr,"\n无法打开网络适配器. WinPcap不支持%s \n", d->name);
  75.         // 释放设备列表
  76.         pcap_freealldevs(alldevs);
  77.         return -1;
  78.  
  79.    }
  80.  
  81.    /* 检查链接层.本程序只支持以太网. */
  82.    if(pcap_datalink(adhandle) != DLT_EN10MB)
  83.    {
  84.             fprintf(stderr,"\n本程序仅在以太网环境下可用.\n");
  85.             /* 释放设备列表 */
  86.             pcap_freealldevs(alldevs);
  87.             return -1;
  88.    }
  89.  
  90.  
  91.    if(d->addresses != NULL)
  92.             /* 获得第一个接口地址的网络掩码 */
  93.             netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  94.    else
  95.             /* 如果接口没有地址,那么我们假设一个C类的掩码 */
  96.             netmask=0xffffff;
  97.  
  98.  
  99.    //编译过滤器
  100.     if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
  101.     {
  102.         fprintf(stderr,"\n无法编译过滤规则,请检查语法的正确性.\n");
  103.         // 释放设备列表
  104.         pcap_freealldevs(alldevs);
  105.         return -1;
  106.     }
  107.  
  108.     //设置过滤器
  109.     if (pcap_setfilter(adhandle, &fcode)<0)
  110.     {
  111.         fprintf(stderr,"\n设置过滤器错误.\n");
  112.         // 释放设备列表
  113.         pcap_freealldevs(alldevs);
  114.         return -1;
  115.     }
  116.  
  117.  
  118.          printf("\nlistening on %s...\n", d->description);
  119.  
  120.          /* 不需要其他的设备列表信息,释放资源 */
  121.          pcap_freealldevs(alldevs);
  122.  
  123.          /* 开始流量捕获 */
  124.          pcap_loop(adhandle, 0, packet_handler, NULL);
  125.          return 0;
  126. }
  127.  
  128. struct Packet {
  129.          ether_header eth;
  130.     ip_header ip;
  131.     udp_header udp;
  132. };
  133.  
  134.  
  135. /* 每当有数据包进入,则以下回调函数被WinPcap调用 */
  136. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
  137. {
  138.     struct tm *ltime;
  139.     char timestr[16];
  140.     ip_header *ih;
  141.     udp_header *uh;
  142.     u_int ip_len;
  143.     u_short sport,dport;
  144.     time_t local_tv_sec;
  145.     /* 将时间戳转换成可识别的格式 */
  146.     local_tv_sec = header->ts.tv_sec;
  147.     ltime=localtime(&local_tv_sec);
  148.     strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
  149.  
  150.    struct Packet *pack=(struct Packet *)pkt_data;
  151.  
  152.   // ether_header *eth=&(pack->eth)://(ether_header *)pkt_data;
  153.  
  154.     /* 打印数据包的时间戳和长度 */
  155.     printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
  156.  
  157.  /* 获得IP数据包头部的位置 */
  158.     ih = (ip_header *) (pkt_data + sizeof(ether_header)); //以太网头部长度
  159.  
  160.  
  161.           /* 打印IP地址和UDP/TCP端口 */
  162.     if (ih->ip_protocol == IPPROTO_TCP) {
  163.         printf("TCP ");
  164.     } else if (ih->ip_protocol == IPPROTO_UDP) {
  165.         printf("UDP ");
  166.     }
  167.     /* 获得UDP首部的位置 */
  168.     ip_len = ih->ip_header_length * 4;
  169.     uh = (udp_header *) ((u_char*)ih + ip_len);
  170.     /* 将网络字节序列转换成主机字节序列 */
  171.     sport = ntohs( uh->udp_source_port );
  172.     dport = ntohs( uh->udp_destination_port );
  173.  
  174.  
  175.  
  176.  
  177.     /* 打印IP地址和UDP端口 */
  178.     printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
  179.         ih->ip_souce_address.S_un.S_un_b.s_b1,
  180.         ih->ip_souce_address.S_un.S_un_b.s_b2,
  181.         ih->ip_souce_address.S_un.S_un_b.s_b3,
  182.         ih->ip_souce_address.S_un.S_un_b.s_b4,
  183.         sport,
  184.         ih->ip_destination_address.S_un.S_un_b.s_b1,
  185.         ih->ip_destination_address.S_un.S_un_b.s_b2,
  186.         ih->ip_destination_address.S_un.S_un_b.s_b3,
  187.         ih->ip_destination_address.S_un.S_un_b.s_b4,
  188.         dport);
  189.  
  190.                  if (ih->ip_protocol == IPPROTO_TCP) {
  191.         printf("协议为TCP,数据部分的10个字节的数据为: ");
  192.         for (int i = 0; i < 10; i++) {
  193.             printf("%02X \n", pkt_data[ip_len + sizeof(udp_header) + i]);
  194.         }
  195.  
  196.     } else if (ih->ip_protocol == IPPROTO_UDP) {
  197.         printf("协议为UDP,数据部分的10个字节的数据为: ");
  198.         for (int i = 0; i < 10; i++) {
  199.             printf("%02X \n", pkt_data[ip_len + sizeof(tcp_header) + i]);
  200.         }
  201.     }
  202.  
  203.  
  204. }
  205.  
  206.  

窗体底端

实验心得:

通过这段代码的实验,我对网络数据包的捕获和分析有了更深入的了解。在实验中,我学会了如何使用WinPcap库来捕获网络数据包,并对捕获到的数据包进行解析和分析。具体来说,我了解到了网络数据包由数据链路层、网络层、传输层和应用层组成,每个层次都有自己的协议和头部。在代码中,我学会了如何解析以太网头部、IP头部和UDP/TCP头部,并从中获取相关信息。WinPcap是一个开源的网络数据包捕获库,可以在Windows平台上捕获网络数据包。在代码中,我学会了如何使用WinPcap库来打开网络接口、设置过滤条件、捕获数据包和关闭网络接口。在实验中,我学会了如何根据数据包的协议类型、源IP地址、目的IP地址、源端口号和目的端口号等信息,来分析数据包的内容和用途。通过对数据包的分析,我可以了解网络流量的特征和趋势,以及排查网络问题的原因。总的来说,这次实验让我更深入地了解了网络数据包的捕获和分析,也让我掌握了一些基本的网络分析技巧。这对于我今后从事网络安全工作都非常有帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值