首页 » 软件开发 » 基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据)「winpcap抓包软件编程」

基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据)「winpcap抓包软件编程」

乖囧猫 2024-07-23 17:40:53 软件开发 0

扫一扫用手机浏览

文章目录 [+]

二、WinPcap中文技术文档

  http://www.ferrisxu.com/WinPcap/html/index.html

二、需要使用到的动态库和外部头文件

基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据) 基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据) 软件开发
(图片来自网络侵删)

  ① 库文件:Packet.dll、Packet.lib、wpcap.dll、wpcap.lib

基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据) 基于WinPcap实现的Raw EtherNet 抓包、发包程序(发包以太网程序地址数据) 软件开发
(图片来自网络侵删)

  ② 头文件

三、用vs创建工程(我这里使用的是vs2015)

  工程创建完毕需要配置工程属性

  ① 右键工程属性-->VC++目录-->找到包含目录、库目录,把刚才的库文件路径和头文件的路径添加进去,如下图所示

  ② 找到链接器--->附加依赖项,添加Packet.lib、wpcap.lib库文件

四、示例代码

  ① 头文件

/ @file RawEtherSniffer.h @brief 通过原始以太网解析FPGA发送的数据 Details. @author jiang shuang @email @version 1.0.0.0(版本号) @date @license ---------------------------------------------------------------------------- Remark : Description ---------------------------------------------------------------------------- Change History : <Date> | <Version> | <Author> | <Description> ---------------------------------------------------------------------------- 2019/09/10 | 1.0.0.0 | jiangshuang | Create file ---------------------------------------------------------------------------- /#pragma once#define WIN32#include <iostream>#include <stdio.h>#include <stdlib.h>#include <pcap.h>class RawEtherTools{public: RawEtherTools(); ~RawEtherTools(); / @brief 以太网数据数据帧嗅探器 @input 无 @output 无 @return 无 / void CaptureRawEtherFrame(); int ethernet_protocol_packet_handle(u_char argument, const struct pcap_pkthdr packet_header, const u_char packet_content);};

  ② cpp文件

#define _CRT_SECURE_NO_WARNINGS#include "Tools.h"using namespace std;// 以太网协议格式的定义typedef struct ether_header { u_char ether_dhost[6]; // 目标MAC地址 u_char ether_shost[6]; // 源MAC地址 u_short ether_type; // 以太网类型}ether_header;// 用户保存4字节的IP地址typedef struct ip_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4;}ip_address;// 用于保存IPV4的首部typedef struct ip_header {#ifdef WORDS_BIGENDIAN u_char ip_version : 4, header_length : 4;#else u_char header_length : 4, ip_version : 4;#endif u_char ver_ihl; // 版本以及首部长度,各4位 u_char tos; // 服务质量 u_short tlen; // 总长度 u_short identification; // 身份识别 u_short offset; // 分组偏移 u_char ttl; // 生命周期 u_char proto; // 协议类型 u_short checksum; // 包头测验码 ip_address saddr; // 源IP地址 ip_address daddr; // 目的IP地址 u_int op_pad; // 可选 填充字段}ip_header;RawEtherTools::RawEtherTools(){}RawEtherTools::~RawEtherTools(){}/ @brief @input 无 @output 无 @return 无/void RawEtherTools::CaptureRawEtherFrame(){ struct pcap_pkthdr header; pcap_if_t allDevs; pcap_if_t dev; u_int netmask; int inum; int i = 0; int res; const u_char pkt_data; time_t local_tv_sec; struct tm ltime; char timestr[16]; ip_header ih; char errbuf[PCAP_ERRBUF_SIZE]; if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allDevs, errbuf) > 0) { printf("pcap_findallDevs_ex failed\n"); } for (dev = allDevs; dev; dev = dev->next) { printf("%d. %s", ++i, dev->name); if (dev->description) { printf("(%s)\n", dev->description); } else { printf("No description available\n"); } } if (0 == i) { printf("\nNo interface found!Make sure WinPcap is installed\n"); return; } printf("Enter the interface number(1-%d):", i); scanf_s("%d", &inum); if (inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); pcap_freealldevs(allDevs); return; } for (dev = allDevs, i = 0; i < inum - 1; dev = dev->next, i++); pcap_t handler; // 设备名,要捕捉的数据包的部分(65536保证能捕获到不同数据链路层上的每个数据包的全部内容),混杂模式,读取超时时间,错误缓冲池 if ((handler = pcap_open_live(dev->name, 65536, 1, 1000, errbuf)) == NULL) { fprintf(stderr, "\nUnable to open the adapter.%s is not supported by WinPcap\n", errbuf); pcap_freealldevs(allDevs); return; } // 检查数据链路层(只考虑了以太网) if (pcap_datalink(handler) != DLT_EN10MB) { fprintf(stderr, "\nThis program works only on Ethernet networks.\n"); pcap_freealldevs(allDevs); return; } if (dev->addresses != NULL) { // 获得接口的第一个地址的掩码 netmask = ((struct sockaddr_in)(dev->addresses->netmask))->sin_addr.S_un.S_addr; } else { netmask = 0xffffff; } while ((res = pcap_next_ex(handler, &header, &pkt_data)) >= 0) { // 请求超时 if (0 == res) { continue; } // 分析数据包 int ret = ethernet_protocol_packet_handle(NULL, header, pkt_data); if (ret == -1) continue; // 将时间戳转换成可识别的格式 local_tv_sec = header->ts.tv_sec; ltime = localtime(&local_tv_sec); strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime); ih = (ip_header )(pkt_data + 14); //以太网头部长度 // 输出时间和IP信息 //printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len); printf(" len:%d ", header->len); printf("%d.%d.%d.%d -> %d.%d.%d.%d\n", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4); printf("%02x%02x%02x%02x -> %02x%02x%02x%02x\n", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4); //输出每个包的byte数据ws2_32.lib for (int k = 0; k < header->len; k++) { if (k % 16 == 0 && k != 0)//输出美观 printf("\n"); printf("%02x ", (pkt_data + k)); } printf("\n"); } if (-1 == res) { printf("Error reading the packet:%s\n", pcap_geterr(handler)); return; } pcap_freealldevs(allDevs);}/ @brief 抓取以太网协议包 @input 无 @output 无 @return 无/int RawEtherTools::ethernet_protocol_packet_handle(u_char argument, const struct pcap_pkthdr packet_header, const u_char packet_content){ u_short ethernet_type; // 以太网类型 struct ether_header ethernet_protocol; // 以太网协议变量 u_char mac_string; // 以太网地址 ethernet_protocol = (struct ether_header)packet_content;// 获取以太网数据内容 ethernet_type = ntohs(ethernet_protocol->ether_type); // 获取以太网类型 if (ethernet_type != 0x00FF) { return -1; } printf("Ethernet type is : %04x\n", ethernet_type); // 获取以太网源地址 mac_string = ethernet_protocol->ether_shost; printf(" MAC Source Address is === %02x:%02x:%02x:%02x:%02x:%02x", mac_string, (mac_string + 1), (mac_string + 2), (mac_string + 3), (mac_string + 4), (mac_string + 5) ); // 获取以太网目的地址 mac_string = ethernet_protocol->ether_dhost; printf(" MAC Target Address === %02x:%02x:%02x:%02x:%02x:%02x\n", mac_string, (mac_string + 1), (mac_string + 2), (mac_string + 3), (mac_string + 4), (mac_string + 5) ); printf("%d", sizeof(packet_content)); return 0;}

  ③ Main.cpp

#include <iostream>#include "Tools.h"using namespace std;int main(){ RawEtherTools raw = new RawEtherTools(); raw->CaptureRawEtherFrame(); system("pause"); return 0;}

五、编译程序

  ① 错误1 编译程序报错,如下图所示

  解决办法:

    ws2_32.lib文件,提供了对以下网络相关API的支持,若使用其中的API,则应该将ws2_32.lib加入工程

    在工程属性--->链接器--->附加依赖项,添加ws2_32.lib库文件

  ② 错误2 编译程序报错,如下图所示

解决办法:    

1.error C3861: “pcap_findalldevs_ex”: 找不到标识符

2.error C2065: “PCAP_SRC_IF_STRING”: 未声明的标识符

在WinPcap编程调试解决办法 中,需要项目属性-》配置属性-》C/C++-》预处理器-》预处理器定义中添加HAVE_REMOTE,方可编译成功。

标签:

相关文章