日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

(原创)WinpCap的详解(三)

發布時間:2023/12/13 综合教程 35 生活家
生活随笔 收集整理的這篇文章主要介紹了 (原创)WinpCap的详解(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  接著WinpCap詳解(二),這篇博客主要來討論一下,堆文件的處理以及簡單發送數據包。

1、處理脫機堆文件

  我們將學習如何處理捕獲到文件中的數據包。 WinPcap提供了很多函數來將網絡數據流保存到文件并讀取它們 -- 本講將教你如何使用這些函數。我們還將看到如何使用WinPcap內核堆特性來獲取一個高性能的堆。

  堆文件的格式是libpcap的一種。這種格式中,包含了被捕捉到的包的二進制數據,并且,這種格式是許多網絡工具所使用的一種標準,這些工具包括WinDump,Etheral和Snort。

 保存數據包到堆文件

  首先,讓我們看一下如何將一個數據包寫成libpcap的格式。

  接下來的例子講從一個選定的接口捕獲數據包,并且將它們保存到用戶指定的文件中。 

  這里pcap_dump_t和pcap_dump一樣的東西,表示的是libpcap存儲文件的描述符,對用戶來說也是不透明的。

  這里的pcap_findalldevs_ex()函數是pcap_findalldevs()的擴展。這里我列出他的英文解釋吧,翻譯起來還不是很好,看英文比較容易了。

  This function is a superset of the old 'pcap_findalldevs()', which is obsolete, and which allows listing only the devices present on the local machine. Vice versa, pcap_findalldevs_ex() allows listing the devices present on a remote machine as well. Additionally, it can list all the pcap files available into a given folder. Moreover, pcap_findalldevs_ex() is platform independent, since it relies on the standard pcap_findalldevs() to get addresses on the local machine.

  pcap_dump_open(pcap_t* p,const char* name)打開一個堆文件,第二個參數是文件的名字,第一個參數是已經打開的適配器描述符。

#include "pcap.h"

/* 回調函數原型 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

main(int argc, char **argv)
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_dumper_t *dumpfile;


    
    /* 檢查程序輸入參數 */
    if(argc != 2)
    {
        printf("usage: %s filename", argv[0]);
        return -1;
    }
    
    /* 獲取本機設備列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }
    
    /* 打印列表 */
    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("%d", &inum);
    
    if(inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        /* 釋放列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }
        
    /* 跳轉到選中的適配器 */
    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
    
    
    /* 打開適配器 */
    if ( (adhandle= pcap_open(d->name,          // 設備名
                              65536,            // 要捕捉的數據包的部分 
                                        		   // 65535保證能捕獲到不同數據鏈路層上的每個數據包的全部內容
                              PCAP_OPENFLAG_PROMISCUOUS,    // 混雜模式
                              1000,             // 讀取超時時間
                              NULL,             // 遠程機器驗證
                              errbuf            // 錯誤緩沖池
                              ) ) == NULL)
    {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        /* 釋放設備列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }

    /* 打開堆文件 */
    dumpfile = pcap_dump_open(adhandle, argv[1]);

    if(dumpfile==NULL)
    {
        fprintf(stderr,"\nError opening output file\n");
        return -1;
    }
    
    printf("\nlistening on %s... Press Ctrl+C to stop...\n", d->description);
    
    /* 釋放設備列表 */
    pcap_freealldevs(alldevs);
    
    /* 開始捕獲 */
    pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);

    return 0;
}

/* 回調函數,用來處理數據包 */
void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
    /* 保存數據包到堆文件 */
    pcap_dump(dumpfile, header, pkt_data);
}


 從堆文件中讀取數據包

  既然我們有了可用的堆文件,那我們就能讀取它的內容了。 以下代碼將打開一個WinPcap/libpcap的堆文件,并顯示文件中每一個包的信息。文件通過 pcap_open_offline() 打開,然后,我們通常使用 pcap_loop() 來有序獲取數據包。你可以看到,從脫機文件中讀取數據包和從物理接口中接收它們是很相似的。

  這個例子還會介紹另一個函數:pcap_createsrcsrc()。這個函數用于創建一個源字符串,這個源字符串以一個標志開頭,這個標志會告訴WinPcap這個源的類型。比如,使用"rpcap://"標志來打開一個適配器,使用"file://"來打開一個文件。如果 pcap_findalldevs_ex() 已經被使用,那么這部是不需要的,因為其返回值已經包含了這些字符串。然而,在這個例子中,我們需要它。因為文件的名字來自于用戶的輸入。

  

2、發送數據包

  盡管從 WinPcap 的名字上看,這個庫的目標應該是數據捕捉(Packet Capture),然而,它也提供了針對很多其它有用的特性。在其中,我們可以找到一組很完整的用于發送數據包的函數。

  請注意:原始的libpcap庫是不支持發送數據包的,因此,這里展示的函數都屬于是WinPcap的擴展,并且它們不能運行于Unix平臺下。

  使用 pcap_sendpacket() 發送單個數據包

  下面的代碼展示了發送一個數據包的最簡單的方式。打開適配器以后,調用 pcap_sendpacket() 來發送手工制作的數據包。 pcap_sendpacket() 的參數有一個要包涵發送數據的緩沖區,緩沖的長度,以及用來發送數據的適配器。注意,緩沖數據將直接發送到網絡,而不會進行任何加工和處理。這就意味著應用程序需要創建一個正確的協議首部,來使這個數據包更有意義。

#include <stdlib.h>
#include <stdio.h>

#include <pcap.h>


void main(int argc, char **argv)
{
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
u_char packet[100];
int i;

    /* 檢查命令行參數的合法性 */
    if (argc != 2)
    {
        printf("usage: %s interface (e.g. 'rpcap://eth0')", argv[0]);
        return;
    }
    
    /* 打開輸出設備 */
    if ( (fp= pcap_open(argv[1],            // 設備名
                        100,                // 要捕獲的部分 (只捕獲前100個字節)
                        PCAP_OPENFLAG_PROMISCUOUS,  // 混雜模式
                        1000,               // 讀超時時間
                        NULL,               // 遠程機器驗證
                        errbuf              // 錯誤緩沖
                        ) ) == NULL)
    {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
        return;
    }

    /* 假設在以太網上,設置MAC的目的地址為 1:1:1:1:1:1 */
    packet[0]=1;
    packet[1]=1;
    packet[2]=1;
    packet[3]=1;
    packet[4]=1;
    packet[5]=1;
    
    /* 設置MAC源地址為 2:2:2:2:2:2 */
    packet[6]=2;
    packet[7]=2;
    packet[8]=2;
    packet[9]=2;
    packet[10]=2;
    packet[11]=2;
    
    /* 填充剩下的內容 */
    for(i=12;i<100;i++)
    {
        packet[i]=i%256;
    }

    /* 發送數據包 */
    if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)
    {
        fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));
        return;
    }

    return;
}


  這里面只是簡單的數據發送,還有更復雜的隊列發送,由于現在不需要用到這一塊,所以就不看這一部分了,因為我只需要發送簡單的命令,不需要大量的數據發送,這里就不再講下去啦,如果想更深入的了解WinpCap的功能,推薦一個好的網站,http://www.ferrisxu.com/WinPcap/html/modules.html,這個網站里面有很多關于WinpCap的東西,可能里面有很多更新的東西,還值得大家以后共同學習,本人就學習這么多啦!

總結

以上是生活随笔為你收集整理的(原创)WinpCap的详解(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。