使用PCAP创建你的sniffer

利用pcap你可以截取你网卡的所有的包,创建你自己的网络嗅觉器(sniffer)

pcap是一个用C写的,基于BSD授权协议的,抓取网络包的工具。pcap代表是的packet capture,就是包截取。它有2个版本,unix-based的操作系统下面的libpcap和windows下面的winpcap。 有了这个包,你可以很轻松的截取你网卡的中所有数据包。像tcpdump, Wireshark, CA NetMaster,Microsoft Network Monitor 3.x都是基于pcap实现的。

下面简单说说怎么使用winpcap包来创建截取网卡中所有包。

1. 下载sdk

winpcap的官网,
下载dll包
或者直接下载本文使用的包
http://www.winpcap.org/install/bin/WinPcap_4_1_3.exe
这个是一个安装包,会安装一些必要的动态库到c:windowssystem32
这些dll是我们的程序在运行的时候加载。
下载开发包
或者直接下载本文使用的包
http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip
这个里面包含
文档
示例代码
头文件include
库文件lib
include和lib是我们在编译程序的需要,否则,你无法编译连接。

2. 创建vc工程

使用vs2005创建一个win32的控制台工程。
打开工程的属性,添加WPCAP, HAVE_REMOTE到preprocessor中,
添加include的路径,和lib的路径
添加wpcap.lib, ws2_32.lib到linker的library中。

3. 使用API截取数据包
添加main.cpp文件到这个空的工程中,内容如下:
#include <stdlib.h>
#include <stdio.h>

//
// NOTE: remember to include WPCAP and HAVE_REMOTE among your
// preprocessor definitions.
//

#include <pcap.h>

#define LINE_LEN 16

int main(int argc, char **argv)
{   
pcap_if_t *alldevs, *d;
pcap_t *fp;
u_int inum, i=0;
char errbuf[PCAP_ERRBUF_SIZE];
int res;
struct pcap_pkthdr *header;
const u_char *pkt_data;

    printf("pktdump_ex: prints the packets of the network using WinPcap.n");
    printf("   Usage: pktdump_ex [-s source]nn"
           "   Examples:n"
           "      pktdump_ex -s file://c:/temp/file.acpn"
           "      pktdump_ex -s rpcap://\Device\NPF_{C8736017-F3C3-4373-94AC-9A34B7DAD998}nn");

    if(argc < 3)
    {

        printf("nNo adapter selected: printing the device list:n");
        /* The user didn't provide a packet source: Retrieve the local device list */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
        {
            fprintf(stderr,"Error in pcap_findalldevs_ex: %sn", errbuf);
            return -1;
        }
        
        /* Print the list */
        for(d=alldevs; d; d=d->next)
        {
            printf("%d. %sn    ", ++i, d->name);

            if (d->description)
                printf(" (%s)n", d->description);
            else
                printf(" (No description available)n");
        }
        
        if (i==0)
        {
            fprintf(stderr,"No interfaces found! Exiting.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 ( (fp= pcap_open(d->name,
                            100 /*snaplen*/,
                            PCAP_OPENFLAG_PROMISCUOUS /*flags*/,
                            20 /*read timeout*/,
                            NULL /* remote authentication */,
                            errbuf)
                            ) == NULL)
        {
            fprintf(stderr,"nError opening adaptern");
            return -1;
        }
    }
    else 
    {
        // Do not check for the switch type ('-s')
        if ( (fp= pcap_open(argv[2],
                            100 /*snaplen*/,
                            PCAP_OPENFLAG_PROMISCUOUS /*flags*/,
                            20 /*read timeout*/,
                            NULL /* remote authentication */,
                            errbuf)
                            ) == NULL)
        {
            fprintf(stderr,"nError opening source: %sn", errbuf);
            return -1;
        }
    }

    /* Read the packets */
    while((res = pcap_next_ex( fp, &header, &pkt_data)) >= 0)
    {

        if(res == 0)
            /* Timeout elapsed */
            continue;

        /* print pkt timestamp and pkt len */
        printf("%ld:%ld (%ld)n", header->ts.tv_sec, header->ts.tv_usec, header->len);          
        
        /* Print the packet */
        for (i=1; (i < header->caplen + 1 ) ; i++)
        {
            printf("%.2x ", pkt_data[i-1]);
            if ( (i % LINE_LEN) == 0) printf("n");
        }
        
        printf("nn");     
    }

    if(res == -1)
    {
        fprintf(stderr, "Error reading the packets: %sn", pcap_geterr(fp));
        return -1;
    }

    return 0;
}

编译运行,选择你当前的网卡,你就可以看到所有数据包。

抓到这些包,你就可以分析,是什么样的包,里面的数据又是什么,这个留作自己去做吧。

完。

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.

    分享到:
This entry was posted in 网络开发 and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*