WinPcap教程(3):打开网卡抓包

我们已经知道如何获取网卡信息了,现在让我们开始进行真正的开发工作,即打开一个网卡并抓取数据包。本文中,我们将写一个程序来打印出流经网卡的每个包的相关信息。

 

打开抓包设备的函数是pcap_open(),该函数的参数中,snaplen,flags和to_ms这三个值得解释一下:

snaplen

该参数设定了包需要抓取的部分。在一些操作系统上(如xBSD和Win32),包驱动程序可以配置成只抓取包的初始部分:这降低了应用拷贝数据的数量,从而提高扎包的效率。在我们使用高于我们可能碰到的最大MTU(Maximum Transmission Unit,最大传输单元,以字节为单位) 65536的情况下,这将确保应用总是接收到包的全部。

 

flags

最重要的标致应该是否将网卡设置成混杂模式(promiscuous mode)。在正常模式下,网卡只抓取来自网络的,以它为目的地的数据包,其他机器之间交换的包将被忽略。而在混杂模式下,将抓取所有的包,而不管该网卡是不是这些包的目的地。这意味着在共享介质(如未经交换的以太网,non-switched Ethernet)的情况下,WinPcap能够抓取到其他机器的包。多数抓包应用,混杂模式都是缺省的模式,下面的示例程序中,我们也采用混杂模式。

 

to_ms

该参数指定了读超时,以毫秒为单位。从网卡读数据时(比如,用pcap_dispatch()或者pcap_next_ex()),如果网络上无包可读,超时后(即过了to_ms毫秒后)总会返回。to_ms也定义了统计报告的时间间隔。将to_ms设为0,表示无超时,即在读网卡时,如果没有数据包到来,将永不返回;另一方面,如果设为-1,会使得对网卡的读操作立即返回。

 

#include "pcap.h"

 

/* prototype of the packet handler */

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

 

int main()

{

pcap_if_t *alldevs;

pcap_if_t *d;

int inum;

int i=0;

pcap_t *adhandle;

char errbuf[PCAP_ERRBUF_SIZE];

 

    /* Retrieve the device list on the local machine */

    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)

    {

        fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);

        exit(1);

    }

 

    /* Print the list */

    for(d=alldevs; d; d=d->next)

    {

        printf("%d. %s", ++i, d->name);

        if (d->description)

            printf(" (%s)/n", d->description);

        else

            printf(" (No description available)/n");

    }

 

    if(i==0)

    {

        printf("/nNo interfaces found! Make sure WinPcap is installed./n");

        return -1;

    }

 

    printf("Enter the interface number (1-%d):",i);

    scanf_s("%d", &inum);

 

    if(inum < 1 || inum > i)

    {

        printf("/nInterface number out of range./n");

        /* Free the device list */

        pcap_freealldevs(alldevs);

        return -1;

    }

 

    /* Jump to the selected adapter */

    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);

 

    /* Open the device */

    if ( (adhandle= pcap_open(d->name,      // name of the device

                              65536,      // portion of the packet to capture

                                          // 65536 guarantees that the whole packet will be captured on all the link layers

                              PCAP_OPENFLAG_PROMISCUOUS,    // promiscuous mode

                              1000,             // read timeout

                              NULL,             // authentication on the remote machine

                              errbuf            // error buffer

                              ) ) == NULL)

    {

        fprintf(stderr,"/nUnable to open the adapter. %s is not supported by WinPcap/n", d->name);

        /* Free the device list */

        pcap_freealldevs(alldevs);

        return -1;

    }

 

    printf("/nlistening on %s.../n", d->description);

 

    /* At this point, we don't need any more the device list. Free it */

    pcap_freealldevs(alldevs);

 

    /* start the capture */

    pcap_loop(adhandle, 0, packet_handler, NULL);

 

    return 0;

}

 

 

/* Callback function invoked by libpcap for every incoming packet */

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

{

    struct tm ltime;

    char timestr[16];

    time_t local_tv_sec;

 

    /*

     * unused variables

     */

    (VOID)(param);

    (VOID)(pkt_data);

 

    /* convert the timestamp to readable format */

    local_tv_sec = header->ts.tv_sec;

    localtime_s(&ltime, &local_tv_sec);

    strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);

 

    printf("%s,%.6d len:%d/n", timestr, header->ts.tv_usec, header->len);

 

}

 

打开网卡后,就可以用pcap_dispatch()或者pcap_loop()开始抓包了。这两个函数非常相似,不同的是当超时到了后,pcap_dispatch()会返回(尽管不能保证),而pcap_loop()则不会返回,直到抓取了cnt个包(译注:cnt是pcap_loop()函数的一个参数,其含义见pcap_loop()的原型),因此在比较空闲网络情况下,会被阻塞很长时间。在本例中,pcap_loop()就够用了,pcap_dispatch()通常用于更复杂的程序。

 

这两个函数都各有一个callback参数,即packet_handler,它指向用于处理包数据的函数。每当有新的包从网络上到达时,该函数就会自动被libpcap调用,以接收一个通用状态(generic status,和pcap_loop()或pcap_dispatch()中的user参数对应);一个含有信息包头,诸如时间戳和长度;以及包括协议头在内的真正包数据。注意CRC帧一般不提供,因为网卡在帧完整性验证后会将其删除。另外,大多数网卡在收到错误的CRC后,会将相应的包丢弃。因此,这些被丢弃的包,WinPcap是抓取不到的。

 

上面的例子从pcap_pkthdr头提取了时间戳和每个包的长度,并打印在屏幕上。

 

请注意到,上面的pcap_loop()或许存在一个不足之处,主要是基于这样一个事实:处理函数(handler)是由抓包驱动程序调用的,因此用户的应用程序不能直接控制它。另外一个方法就是使用pcap_next_ex()函数,将在下一个示例程序说明。

 

后篇:待续…

 

此文章来自于【http://blog.csdn.net/pathuang68/article/details/4292603

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WinPcap是一个开放源代码的Windows平台上的网络封捕获工具。它提供了一个用于在网络上取数据的接口和库,以及一系列功能强大的工具和库函数,使用户能够进行网络流量分析和协议分析。 WinPcap的使用非常方便,用户只需安装它的驱动程序和库文件,并调用相应的API函数即可开始网络。用户可以选择使用WinPcap提供的命令行工具来进行,也可以使用自己开发的程序进行网络数据的捕获。 通过使用WinPcap,用户可以捕获到网络中的数据括从底层网络设备(如网卡)接收到的原始数据。用户可以根据自己的需要选择捕获的数据类型、过滤条件和捕获时机等。捕获的数据可以保存到文件中,用户可以随后对保存的数据进行分析和后续处理。 WinPcap支持的网络协议非常广泛,括以太网、IP、TCP、UDP、ICMP等常见的网络协议,还支持更高层的协议如HTTP、FTP、SMTP等。用户可以根据自己的需求对特定协议的数据进行分析,从中提取出需要的信息。 通过对网络分析,用户可以了解网络流量的组成以及各个协议的运行机制,进一步发现网络中的问题和安全隐患。网络分析在网络故障排除、性能优化、安全审计等方面都有广泛的应用。同时,网络分析也是网络安全研究的重要手段之一,可以帮助用户发现网络攻击行为并采取相应的防御措施。 总而言之,WinPcap是一个强大的网络分析工具,通过它,用户可以方便地进行网络数据的捕获和分析,从中获得对网络运行状况和安全性的深入了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值