网站首页 > 技术教程 正文
一、背景
二、WinPcap中文技术文档
http://www.ferrisxu.com/WinPcap/html/index.html
二、需要使用到的动态库和外部头文件
① 库文件:Packet.dll、Packet.lib、wpcap.dll、wpcap.lib
② 头文件
三、用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,方可编译成功。
猜你喜欢
- 2024-10-03 这可是全网eNSP安装最完整,最详细的图解,没有之一(常见问题)
- 2024-10-03 如何用命令行安装软件?用WinPcap的安装例子告诉你
- 2024-10-03 太惨了!蓝屏了,我的文章没了 纯蓝屏没有一点文字怎么办
你 发表评论:
欢迎- 05-02谈游戏状态机的设计与实现 探讨状态机的扩展性和易用性
- 05-02算术加减超人:开启智慧与乐趣之旅
- 05-02“哥俩好”“五魁首”“六六六”行酒令和划拳方式你知道多少
- 05-02航海王燃烧意志:第三波蓝钻红包“口令答案”,新阵型不太给力
- 05-02云上行酒令,就地过大年,行酒令何时出现?这些玩法知多少?
- 05-02一听就懂:用Python做一个超简单的小游戏
- 05-02数字炸弹游戏程序 用python来实现
- 05-025-6岁儿童逆向思维发展与趣味游戏
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)