百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

基于WinPcap实现的Raw EtherNet 抓包、发包程序

suiw9 2024-11-17 01:39 18 浏览 0 评论

一、背景

二、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,方可编译成功。

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: