C/C++ 运用Npcap发送UDP数据包

曂沅仴駦  金牌会员 | 2024-1-10 23:35:53 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 890|帖子 890|积分 2670

Npcap 是一个功能强大的开源网络抓包库,它是 WinPcap 的一个分支,并提供了一些增强和改进。特别适用于在 Windows 环境下进行网络流量捕获和分析。除了支持通常的网络抓包功能外,Npcap 还提供了对数据包的拼合与构造,使其成为实现 UDP 数据包发包的理想选择。本章将通过Npcap库构造一个UDP原始数据包,并实现对特定主机的发包功能,通过本章的学习读者可以掌握如何使用Npcap库伪造特定的数据包格式。
Npcap的主要特点和概述:

  • 原始套接字支持: Npcap 允许用户通过原始套接字在网络层捕获和发送数据包。这使得用户能够进行更底层的网络活动监控和分析。
  • WinPcap 的增强版本: Npcap 是 WinPcap 的一个分支,对其进行了一些增强和改进。这些改进包括对新版本 Windows 的支持、更好的性能和稳定性,以及一些额外的功能。
  • 支持 Windows 10: Npcap 被设计用于支持 Windows 10 操作系统。它允许用户在最新的 Windows 平台上进行网络抓包和分析。
  • Loopback 模式: Npcap 允许在 Loopback 接口上进行抓包,使用户能够监视本地主机上的网络流量。
  • 多种应用场景: Npcap 被广泛应用于网络安全、网络管理、网络调试等各种场景。它为开发人员、网络管理员和安全专家提供了一个功能强大的工具,用于分析和理解网络通信。
  • 开源: Npcap 是开源项目,其源代码可以在 GitHub 上获得。这使得用户可以自由查看、修改和定制代码,以满足特定需求。
UDP 是一种无连接、轻量级的传输层协议,与 TCP 相比,它不提供可靠性、流控制和错误恢复机制,但却更加简单且具有较低的开销。UDP 主要用于那些对传输速度要求较高、可以容忍少量丢失的应用场景。
UDP 数据包结构: UDP 数据包由报头和数据两部分组成。

  • 报头(Header):

    • 源端口号(16 位): 指定发送端口。
    • 目标端口号(16 位): 指定接收端口。
    • 长度(16 位): 报头和数据的总长度,以字节为单位。
    • 校验和(16 位): 用于验证数据在传输过程中的完整性。

  • 数据(Payload):

    • 实际传输的数据,长度可变。

UDP 的特点:

  • 面向无连接: UDP 是一种无连接协议,通信双方不需要在传输数据之前建立连接。这使得它的开销较低,适用于一些实时性要求较高的应用。
  • 不可靠性: UDP 不提供数据的可靠性保证,不保证数据包的到达、顺序和完整性。因此,它更适合那些能够容忍一些数据丢失的场景,如音视频传输。
  • 适用于广播和多播: UDP 支持广播和多播通信,可以通过一个发送操作同时向多个目标发送数据。
  • 低开销: 由于缺乏连接建立和维护的开销,以及不提供可靠性保证的特性,UDP 具有较低的开销,适用于对实时性要求较高的应用。
  • 适用于短消息: 由于不需要建立连接,UDP 适合传输短消息,尤其是对实时性要求高的应用。
UDP 的应用场景:

  • 实时性要求高的应用: 如实时音视频传输、在线游戏等。
  • 简单的请求-响应通信: 适用于一些简单的请求-响应场景,如 DNS 查询。
  • 广播和多播应用: UDP 的支持广播和多播特性使其适用于这类通信模式。
  • 实时数据采集: 例如传感器数据采集等场景。
输出网卡

使用 WinPcap(Windows Packet Capture)库列举系统上的网络接口以及它们的 IP 地址。WinPcap 是一个用于 Windows 操作系统的网络数据包捕获库,可以用于网络数据包的捕获和分析。
代码主要做了以下几个事情:

  • 使用 pcap_findalldevs_ex 函数查找系统上的所有网络接口。
  • 遍历每个网络接口,获取其 IP 地址,并将地址列表打印出来。
pcap_findalldevs_ex 用于查找系统上所有网络接口的函数。它的原型如下:
  1. int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
复制代码
函数参数说明:

  • source:一个字符串,用于指定网络接口的来源。可以为 NULL,表示从系统获取网络接口信息。也可以指定为一个网络地址,用于远程捕获。
  • auth:一个 pcap_rmtauth 结构的指针,用于指定远程捕获的认证信息。一般情况下可以为 NULL。
  • alldevs:一个 pcap_if_t 类型的指针的地址,用于保存查找到的网络接口链表的头指针。
  • errbuf:一个字符数组,用于保存错误信息。
函数返回值:

  • 成功时返回 0。
  • 失败时返回 -1,错误信息保存在 errbuf 中。
函数功能:
pcap_findalldevs_ex 主要用于查找系统上的网络接口信息。当调用成功后,alldevs 将指向一个链表,链表中的每个节点都包含一个网络接口的信息。这个链表的头指针是 alldevs。
pcap_freealldevs 用于释放 pcap_findalldevs_ex 函数分配的资源的函数。其原型如下:
  1. void pcap_freealldevs(pcap_if_t *alldevs);
复制代码
函数参数说明:

  • alldevs:由 pcap_findalldevs_ex 返回的链表的头指针。
函数功能:
pcap_freealldevs 主要用于释放 pcap_findalldevs_ex 函数返回的链表中分配的资源,包括每个节点和节点中保存的接口信息。
输出当前系统中活动网卡信息,可以这样来写,如下代码所示;
  1. #include <WinSock2.h>
  2. #include <Windows.h>
  3. #include <iostream>
  4. #include <pcap.h>
  5. #pragma comment(lib,"ws2_32.lib")
  6. #pragma comment(lib, "packet.lib")
  7. #pragma comment(lib, "wpcap.lib")
  8. // 打开网卡返回的指针
  9. pcap_t* m_adhandle;
  10. unsigned char* FinalPacket;
  11. unsigned int UserDataLen;
  12. int main(int argc, char *argv[])
  13. {
  14.         // 打开网卡
  15.         pcap_if_t* alldevs = NULL, *d = NULL;
  16.         char szErr[MAX_PATH] = { 0 };
  17.         if (-1 == pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, szErr))
  18.         {
  19.                 return 0;
  20.         }
  21.         // 遍历网卡
  22.         char* lpszIP = NULL;
  23.         d = alldevs;
  24.         while (NULL != d)
  25.         {
  26.                 // 遍历网卡IP
  27.                 char szAddress[1024] = { 0 };
  28.                 pcap_addr_t* p = d->addresses;
  29.                 while (p)
  30.                 {
  31.                         lpszIP = inet_ntoa(((sockaddr_in*)p->addr)->sin_addr);
  32.                         strcpy(szAddress, lpszIP);
  33.                         p = p->next;
  34.                 }
  35.                 std::cout << "地址列表: " << szAddress << std::endl;
  36.                 d = d->next;
  37.         }
  38.         // 释放资源
  39.         flags
  40.         system("pause");
  41.         return 0;
  42. }
复制代码
获取匹配网卡的子网掩码。
打开网卡:
  1. if (-1 == pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf))
复制代码
使用 pcap_open 函数打开选择的网卡,该函数的声明如下:
  1. for (d = alldevs; d; d = d->next)
复制代码
这里是对参数的简要解释:

  • source: 要打开的网络适配器的名称,例如 "eth0"。
  • snaplen: 指定捕获数据包时每个数据包的最大长度。如果数据包超过这个长度,它将被截断。通常设置为数据包的最大可能长度。
    1. netmask = ((sockaddr_in*)d->addresses->netmask)->sin_addr.S_un.S_addr;
    复制代码
    : 控制捕获的方式,可以使用位掩码进行组合。常见的标志包括:

    • PCAP_OPENFLAG_PROMISCUOUS: 开启混杂模式,允许捕获所有经过网卡的数据包。
    • PCAP_OPENFLAG_MAX_RESPONSIVENESS: 最大响应性标志,可能在某些平台上影响性能。

  • read_timeout: 设置超时值,以毫秒为单位。如果设置为0,表示无限期等待数据包。
  • auth: 可以指定用于远程捕获的身份验证信息,通常为 NULL。
  • errbuf: 用于存储错误信息的缓冲区,如果函数执行失败,会将错误信息写入这个缓冲区。
函数返回一个 pcap_t 类型的指针,它是一个表示打开的网络适配器的结构。如果打开失败,返回 NULL。
检查以太网:
  1. m_adhandle = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
复制代码
pcap_datalink 函数是 PCAP 库中用于获取网络适配器数据链路类型(datalink type)的函数,确保是以太网,如果不是以太网,输出错误信息并返回。
该函数的声明如下:
  1. pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
复制代码
这里是对参数的简要解释:

  • p: 表示一个已经打开的网络适配器的 pcap_t 结构指针。
函数返回一个整数,表示数据链路类型。这个值通常是预定义的常量之一,用于标识不同类型的网络数据链路。
常见的一些数据链路类型常量包括:

  • DLT_EN10MB(Ethernet): 表示以太网数据链路。
  • DLT_IEEE802(802.5 Token Ring): 表示 IEEE 802.5 Token Ring 数据链路。
  • DLT_PPP(Point-to-Point Protocol): 表示点对点协议数据链路。
  • DLT_ARCNET(ARCNET): 表示 ARCNET 数据链路。
释放网卡设备列表:
  1. flags
复制代码
最后,释放 pcap_findalldevs_ex 函数返回的网卡设备列表,避免内存泄漏。
该函数的其他全局变量 m_adhandle,FinalPacket,UserDataLen 已经在文章开头声明和定义。
[code]// 通过传入本机IP地址打开网卡void OpenAdapter(std::string local_address){  pcap_if_t* alldevs = NULL, * d = NULL;  char errbuf[256] = { 0 };  bpf_program fcode;  u_int netmask;  // 获取网卡设备指针  if (-1 == pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf))  {    std::cout addresses;    while (p)    {      if (local_address == inet_ntoa(((sockaddr_in*)p->addr)->sin_addr))      {        flag = 1;        break;      }      p = p->next;    }    if (1 == flag)      break;  }  if (0 == flag)  {    std::cout name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);  if (NULL == m_adhandle)  {    std::cout
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曂沅仴駦

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表