专业汉语词典知识平台,分享汉字词语知识、历史文学知识解答!

励北网
励北网

winpcap编程软件使用教程

来源:小易整编  作者:小易  发布时间:2023-03-21 05:06
摘要:winpcap编程软件使用教程WinPcap原理我们在安装WinPcap的时候,除了安装相关的Dll文件到系统目录,最重要的是在系统的NDIS层安装了一个用于原始封包过滤的驱动程序。通过Dll提供的函数,使得运行于Ring3层的应用程序也能...

winpcap编程软件使用教程

winpcap编程软件使用教程

WinPcap 原理
我们在安装 WinPcap 的时候,除了安装相关的 Dll 文件到系统目录,最重要的是在系统的 NDIS 层安装了一个用于原始封包过滤的驱动程序。通过 Dll 提供的函数,使得运行于 Ring3 层的应用程序也能访问到底层的网络数据。至于这些过程具体是如何实现的,不是本教程关注的内容,有兴趣的读者可以自行百度,或者直接阅读 WinPcap 的源码!有任何心得体会欢迎与我交流:)
WinPcap 编程的一般方法
平心而论,使用 WinPcap 提供的 API 接口编程实现原始封包数据的获取、发送、转储等功能,还是比较简单的。以抓包为例,必须步骤依次是:获取网络驱动接口、打开网络驱动接口、开始抓包,通常我们不会需要捕获所有的数据包,因此抓包之前还需要设定合适的过滤规则,比如指定 IP 地址、TCP 或者 UDP 端口等等。下面将分别介绍这些步骤。
1、获取网络驱动接口
需要注意的是,我们这里说的是网络驱动接口,而不是物理网卡,也就是说实际上 WinPcap 是通过网卡驱动程序来实现与网卡的交互。这也就是为什么在很多机器上明明只有一个物理网卡,但 WinPcap 却能获取到两个或者更多的网卡驱动接口信息。那些软件虚拟的网卡多数是因为系统中安装了与 VPN 客户端类似的连接程序。下面是获取网络驱动接口信息的代码:

  1.                 pcap_if_t *alldevs, *pDev;

  2.                 char errbuf[PCAP_ERRBUF_SIZE+1];

  3.                 /* Retrieve the device list */

  4.                 if(pcap_findalldevs(&alldevs, errbuf) == -1)

  5.                 {

  6.                         //出错了返回自定义错误代码‘2’,通常用于定位故障;

  7.                         return 2;

  8.                 }

复制代码

函数 pcap_findalldevs 用于获取网络驱动接口的相关信息,并将他们存储在由 alldevs 指向的链表结构中。该链表结构的元素均由 pcap_if_t  结构定义,其中最重要的字段就是接口的名字,在以上代码中可以使用 pDev->name 访问,比如笔者机器上的物理网卡的 name 就是:

  1. \Device\NPF_{79D843D7-2AE1-4E2E-A54F-D46154627742}

复制代码

这个名字不是很友好,看起来应该就是系统注册表中对应的表项值。pDev->description 中是此接口的描述信息:

  1. Network adapter 'Realtek 10/100/1000 Ethernet NIC

复制代码

这个就友好多了吧。除了名字和描述,pDev->address 也很重要,主要保存了配置在该接口上的网络地址,通常就是 IP 地址和对应的掩码。需要注意的是,一个网络接口上通常可以配置多个地址,因此 address 字段指向的是一个地址链表。
2、选择合适的网络驱动接口(最佳路由匹配)
如果上一步仅获取到一个接口,那就直接用它好了,但是实际的情况是很多时候你都会获取到两个以及两个以上的接口。比如笔记本电脑通常会有有线和无线两种网卡,自然对应两个网络驱动接口。那么这种情况下如何选择合适的网卡呢?通常为了简化程序设计,可以直接将列出所有的接口信息,让用户手动选择!但是本教程采用最佳路由匹配的方法让程序自动选择合适的接口。
要使用最佳路由匹配,需要在我们的程序中包含 Iphlpapi.h 头文件,这是标准的 Windows API,因此可以使用如下代码:

  1. #include <Iphlpapi.h>

复制代码

所谓最佳路由,其实就是找网关,方法是调用函数 GetBestRoute 计算出到达某个公网地址“114.114.114.114”的下一跳地址,通常就是网卡上配置的网关地址。接着逐个计算网络驱动接口上的 IP 是否与下一跳地址在相同网段,如果确实在相同网段,那么则拥有该 IP 的接口就是我们要使用的接口。关于 IP 路由的基础知识,如果您不是很了解的话,可以参考本站教程:[图解] IP 路由基础。通过最佳路由选定网络接口(网卡)的代码如下:

  1.                 PMIB_IPFORWARDROW pBestRoute = new MIB_IPFORWARDROW;

  2.                 DWORD dwGateway,*pIPAddr,*pNetMask;

  3.                 CString str;

  4.                 if(GetBestRoute(inet_addr("114.114.114.114"),0,pBestRoute) == NO_ERROR)

  5.                 { 

  6.                         dwGateway = pBestRoute->dwForwardNextHop;

  7.                 }

  8.                 pcap_addr_t *a;

  9.                 for(pDev=alldevs;pDev;pDev=pDev->next)

  10.                 {

  11.                         for(a=pDev->addresses;a;a=a->next)

  12.                         {

  13.                                 if(a->addr->sa_family == AF_INET)

  14.                                 {

  15.                                         pIPAddr = (DWORD*)(&a->addr->sa_data[2]);

  16.                                         pNetMask = (DWORD*)(&a->netmask->sa_data[2]);

  17.                                         if((*pIPAddr & *pNetMask) == (dwGateway & *pNetMask))

  18.                                         {

  19.                                                 str.Format("%s",pDev->name);

  20.                                                 pcap_freealldevs(alldevs);

  21.                                                 delete pBestRoute;

  22.                                         }

  23.                                 }

  24.                         }

  25. }

复制代码

这段代码首先使用函数 GetBestRoute 获取到达指定地址“114.114.114.114”的最佳路由信息,并将其存储在由 pBestRoute 指向的 MIB_IPFORWARDROW 结构中,MIB_IPFORWARDROW 结构中的字段 dwForwardNextHop 就是我们所需要的下一跳地址,多数情况下这就是网关地址!然后接下来的循环体用来找出与下一跳地址在相同网段的接口 IP,外循环是遍历网络驱动接口,内循环是遍历当前接口上的 IP 地址。判断接口 IP 与下一跳地址是否在相同网段的方法是:“接口IP & 接口掩码” 等于 “下一跳(网关)地址 & 接口掩码”,如果找到了符合条件的 IP ,则将拥有这个 IP 地址的网络驱动接口的名字保存起来,然后使用函数 pcap_freealldevs 释放之前由 pcap_findalldevs 获取的接口列表 alldevs。
注意:此方法并不能适用于系统中存在逻辑连接的情况!什么是逻辑连接?很多计算机上网都是通过 PPPoE 宽带拨号上网的,拨号成功以后系统中将存在一条逻辑连接,它是建立在网络驱动接口之上的虚拟连接,而 pcap_findalldevs 函数无法获取到这些逻辑连接的信息。同时 WinXP 系统下没有很好的办法可以获取逻辑连接与网络驱动接口直接的堆叠关系,如果是 Win7 或者以上系统则可以通过 GetIfStackTable 函数来获取逻辑连接与物理连接之间的堆叠关系。
3、打开网络驱动接口
当选定了正确的网络驱动接口后,使用函数 pcap_open 来打开网络驱动接口,如果成功将返回一个对应网络驱动接口的句柄,并保存在 adhandle 中,以后如果需要对该网络驱动接口进行相关操作,那么都可以通过 adhandle 来实现。

  1. if((adhandle = pcap_open(pDev->name, 65536, 0, 250, NULL, errbuf)) == NULL)[indent]{

  2.         // 打开失败!

  3.         return 0;

  4. }

复制代码

仅打开接口,创建一个接口句柄还不能满足我们的要求,必须要能针对指定的封包流(只对游戏封包感兴趣)进行过滤,一来降低系统消耗,二来减少不必要的数据处理。因此我们还需要设定过滤规则,并将过滤规则与网络驱动接口绑定。相关代码如下:

  1. if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)

  2. {

  3.         //过滤规则编译失败!

  4.         return 0;

  5. }

  6. if (pcap_setfilter(adhandle, &fcode)<0)[/indent]{

  7.         //设定过滤规则失败!

  8.         return 0;

  9. }

复制代码

代码中的 fcode 是由函数 pcap_compile 输出的过滤规则,根据 WinPcap 手册我们知道 fcode 中保存的是二进制的可执行代码,可以通过函数 pcap_setfilter 将这段代码与对应的网络驱动接口绑定起来,以实现对指定封包数据流的捕获。packet_filter  则是用用户指定的用于描述封包数据流的规则,也就是通常所说的过滤规则。fcode 和 packet_filter 可以通过如下代码定义:

  1.         char *packet_filter = "tcp port 4000";

  2.         struct bpf_program fcode;

复制代码

封包过滤规则详见 WinPcap 手册中的“Filtering expression syntax”小节。
4、开始抓包
在以上步骤都顺利完成后,终于可以开始捕获我们心仪已久网络封包数据了!在 WinPcap 中提供了三种获取封包的方式,分别是:pcap_loop、pcap_dispatch 和 pcap_next(pcap_next_ex),如何选择呢?
首先 pcap_next 不支持回调函数,大大降低灵活性,直接出局!pcap_loop 貌似没有 pcap_dispatch 灵活,介于 WinPcap 对 pcap_loop 与 pcap_dispatch 区别的介绍不够详细,我也不好妄自揣测。本文选择使用 pcap_dispatch 的原因是因为大名鼎鼎的 Wireshark 就是用的 pcap_dispatch ,有兴趣的朋友可以去读读 Wireshark 的源码(dumpcap.c)。开启抓包的代码如下:

  1. pcap_dispatch(adhandle, 1, packet_handler, (u_char*)pParam);

  2. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)

  3. {//...处理封包的代码...}

复制代码

代码中的 packet_handler 是回调函数,每当 pcap_dispatch 获取到一个符合过滤规则的封包后,就会自动调用packet_handler  来对封包中的数据进行处理,回调函数有三个参数,第一个参数可以用来给回调函数传递参数,比如告诉回调函数应该如何处理数据;第二个参数是 WinPcap 自动生成的关于这个数据包的一些基本信息,比如获取此封包的时间,封包长度等等;第三个参数就是原始的封包数据了,包含了从数据链路层到应用层的完整封包数据。
到此,使用 WinPcap 进行抓包的主要步骤就介绍完了。如果读者觉得无法很好的理解这部分内容,建议先去学习下 WinPcap技术手册,并动手编译调试一下 WinPcap 源码包中 Example 目录下的实例,以加深理解。


本文地址:百科问答频道 https://www.neebe.cn/wenda/935163.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


百科问答
小编:小易整编
相关文章相关阅读
  • DOS工具软件

    DOS工具软件

      DOS系统之所以还能发挥余热,与DOS具有丰富的工具软件是分不开的。突出的几个工具软件有format、fdisk、DM、Ghost等。  在DOS下也可以完成很多在Windows下完成的工作,包括游戏激活、系统维护、磁盘修复等,...

  • 软件环境是什么意思?

    软件环境是什么意思?

    软件环境是指软件运行所需的硬件和软件资源,可以分为两个方面:系统环境和开发环境。系统环境是指运行软件所需的硬件和软件平台。硬件包括处理器、内存、硬盘、显示器等,而软件平台则指操作系统和相关组件,比如Windows、Linux、MacOS等...

  • 代码编程是什么意思?

    代码编程是什么意思?

    代码编程是把一些有意义的指令(称为程序代码),以一种特定的语言编写成,让机器能够理解并执行的一种过程。程序代码被输入到计算机(或特定的计算设备)中,按照用户编写的指令执行操作,从而实现特定的功能。代码编程具有很多好处,因为它可以使我们有效...

  • 编程框架是什么意思?

    编程框架是什么意思?

    编程框架是一种软件开发工具,它提供标准的、灵活的编程架构,帮助开发者更快的开发软件系统。它提供了一系列可以用于构建应用程序的组件,它们之间具有良好的耦合性,能够帮助应用程序达到最优状态。通常来说,编程框架会集成很多开发工具,如:语言、数据...

  • 如何在PR软件中设置导出视频最佳格式

    如何在PR软件中设置导出视频最佳格式

    我们在PR软件中编辑好视频后,经常不知道选择什么想要的导出格式,又想效果好又不希望占用太多空间,今天就跟大家介绍一下如何在PR软件中设置导出视频最佳格式的具体操作步骤。1.如图,我们在PR软件中,已经剪辑好了视频,下面就要将视频导出了。2...

  • 网页编程是什么意思?

    网页编程是什么意思?

    网页编程是一种通过使用编程语言创建网页的过程。它可以用来开发功能强大的网站,为用户提供完美的用户体验。通常使用编程语言的一个原因是它能够通过在浏览器之间传递指令来控制界面上的更新和数据变化,并更有效地构建网页。网页编程主要涉及到诸如HTM...

  • 安卓系统的软件后缀名apk简介

    安卓系统的软件后缀名apk简介

    APK是AndroidPackage的缩写,即Android安装包(apk)。APK是类似SymbianSis或Sisx的文件格式。通过将APK文件直接传到Android模拟器或Android手机中执行即可安装。apk文件和sis一样,把...

  • 如何从官网中下载“vivo互传”电脑版软件

    如何从官网中下载“vivo互传”电脑版软件

    假如我们使用的是vivo手机的话,可以在电脑中下载一个vivo互传,今天小编跟大家分享下如何从官网中下载“vivo互传”电脑版软件。具体如下:1.首先我们在电脑中打开浏览器,小编使用的是谷歌浏览器。2.然后我们使用百度搜索“vivo互传...

  • 周排行
  • 月排行
  • 年排行

精彩推荐