winpcap

winpcap

網絡訪問系統
winpcap(windows packet capture)是windows平台下一個免費,公共的網絡訪問系統。[1]開發winpcap這個項目的目的在于為win32應用程序提供訪問網絡底層的能力。[2]大多數網絡應用程序訪問網絡是通過廣泛使用的套接字。這種方法很容易實現網絡數據傳輸,因為操作系統負責底層的細節(比如協議棧,數據流組裝等)以及提供了類似于文件讀寫的函數接口。
    網站名稱: 别名: 創始人: 總部地點: 主辦單位: 網站類型: 網站口号: ICP備案号: 外文名:winpcap 全拼:windows packet capture 使用平台:windows 目 的:為win32提供訪問網絡底層能力 作 用:網絡分析,故障排除等方面

簡介

WinPcap是用于網絡封包抓取的一套工具,可适用于32位的操作平台上解析網絡封包,包含了核心的封包過濾,一個底層動态鍊接庫,和一個高層系統函數庫,及可用來直接存取封包的應用程序界面。 

Winpcap是一個免費公開的軟件系統。它用于windows系統下的直接的網絡編程。

大多數網絡應用程序訪問網絡是通過廣泛使用的套接字。這種方法很容易實現網絡數據傳輸,因為操作系統負責底層的細節(比如協議棧,數據流組裝等)以及提供了類似于文件讀寫的函數接口。

但是有時,簡單的方法是不夠的。因為一些應用程序需要一個底層環境去直接操縱網絡通信。因此需要一個不需要協議棧支持的原始的訪問網絡的方法。

特點

Winpcap提供了一個強大的編程接口,它很容易地在各個操作系統之間進行移植,也很方便程序員進行開發。

什麼樣的程序需要使用Winpcap?

很多不同的工具軟件使用Winpcap于網絡分析,故障排除,網絡安全監控等方面。Winpcap特别适用于下面這幾個經典領域:

1、網絡及協議分析

2、網絡監控

3、通信日志記錄

4、traffic generators

5、用戶級别的橋路和路由

6、網絡入侵檢測系統(NIDS)

7、網絡掃描

8、安全工具

Winpcap有些方面不能做。它不依靠主機的諸如TCP/IP協議去收發數據包。這意味着它不能阻塞,不能處理同一台主機中各程序之間的通信數據。它隻能“嗅探”到物理線路上的數據報。因此它不适用于traffic shapers,QoS調度,以及個人防火牆。

Winpcap内部結構

Winpcap是一個Win32平台下用于抓包和分析的系統。包括一個内核級别的packet filter,一個底層的DLL(packet.dll)和一個高級的獨立于系統的DLL(Wpcap.dll)

驅動各項功能

1. 捕獲原始數據包,包括在共享網絡上各主機發送/接收的以及相互之間交換的數據包; 

2. 在數據包發往應用程序之前,按照自定義的規則将某些特殊的數據包過濾掉;

3. 在網絡上發送原始的數據包;

4.收集網絡通信過程中的統計信息。

winpcap的主要功能在于獨立于主機協議(如TCP-IP)而發送和接收原始數據包。也就是說,winpcap不能阻塞,過濾或控制其他應用程序數據包的發收,它僅僅隻是監聽共享網絡上傳送的數據包。因此,它不能用于QoS調度程序或個人防火牆。目前,winpcap開發的主要對象是windows NT/2000/XP,這主要是因為在使用winpcap的用戶中隻有一小部分是僅使用windows 95/98/Me,并且MS也已經放棄了對win9x的開發。

因此本文相關的程序T-ARP也是面向NT/2000/XP用戶的。其實winpcap中的面向9x系統的概念和NT系統的非常相似,隻是在某些實現上有點差異,比如說9x隻支持ANSI編碼,而NT系統則提倡使用Unicode編碼。有個軟件叫sniffer pro.可以作網管軟件用,有很多功能,可監視網絡運行情況,每台網内機器的數據流量,實時反映每台機器所訪問IP以及它們之間的數據流通情況,可以抓包,可對過濾器進行設置,以便隻抓取想要的包,比如POP3包,smtp包,ftp包等,并可從中找到郵箱用戶名和密碼,還有ftp用戶名和密碼。

它還可以在使用交換機的網絡上監聽,不過要在交換機上裝它的一個軟件。還有一個簡單的監聽軟件叫Passwordsniffer,可截獲郵箱用戶名和密碼,還有ftp用戶名和密碼,它隻能用在HUB網絡上。著名軟件tcpdump及ids snort都是基于libpcap編寫的,此外Nmap掃描器也是基于libpcap來捕獲目标主機返回的數據包的。

winpcap提供給用戶兩個不同級别的編程接口:一個基于libpcap的wpcap.dll,另一個是較底層的packet.dll。對于一般的要與unix平台上libpcap兼容的開發來說,使用wpcap.dll是當然的選擇。

内部結構

Winpcap是針對Win32平台上的抓包和網絡分析的一個架構。它包括一個核心态的包過濾器,一個底層的動态鍊接庫(packet.dll)和一個高層的不依賴于系統的庫(wpcap.dll)。 

為什麼使用“architecture”而不是“library”呢?因為抓包是一個要求與網絡适配器(網卡)和操作系統交互的底層機制,而且與網絡的實施也有密切關系,所以僅用“library”不能充分表達Winpcap的作用。

下圖表明了Winpcap的各個組成部分:

首先,抓包系統必須繞過操作系統的協議棧來訪問在網絡上傳輸的原始數據包(raw packet),這就要求一部分運行在操作系統核心内部,直接與網絡接口驅動交互。這個部分是系統依賴(system dependent)的,在Winpcap的解決方案裡它被認為是一個設備驅動,稱作NPF(Netgroup Packet Filter)。

Winpcap開發小組針對Windows95,Windows98,WindowsME,Windows NT 4,Windows2000和WindowsXP提供了不同版本的驅動。這些驅動不僅提供了基本的特性(例如抓包和injection),還有更高級的特性(例如可編程的過濾器系統和監視引擎)。前者可以被用來約束一個抓包會話隻針對網絡通信中的一個子集(例如,僅僅捕獲特殊主機産生的ftp通信的數據包),後者提供了一個強大而簡單的統計網絡通信量的機制(例如,獲得網絡負載或兩個主機間的數據交換量)。

其次,抓包系統必須有用戶級的程序接口,通過這些接口,用戶程序可以利用内核驅動提供的高級特性。Winpcap提供了兩個不同的庫:packet.dll和wpcap.dll。前者提供了一個底層API,伴随着一個獨立于Microsoft操作系統的編程接口,這些API可以直接用來訪問驅動的函數;後者導出了一組更強大的與libpcap一緻的高層抓包函數庫(capture primitives)。這些函數使得數據包的捕獲以一種與網絡硬件和操作系統無關的方式進行。

NPF驅動

網絡數據包過濾器(Netgroup Packet Filter,NPF)是Winpcap的核心部分,它是Winpcap完成困難工作的組件。它處理網絡上傳輸的數據包,并且對用戶級提供可捕獲(capture)、發送(injection)和分析性能(analysis capabilities)。

NPF和NDIS

NDIS(Network Driver Interface Specification)是一個定義網絡适配器(或者說成是管理網絡适配器的驅動程序)與協議驅動(例如TCP/IP的實現)之間通信的規範。NDIS最主要的目的是作為一個允許協議驅動發送和接收網絡(LAN或WAN)上的數據包而不必關心特定的适配器或特定的Win32操作系統的封裝。

NDIS支持三種類型的網絡驅動:

(1)網絡接口卡或NIC驅動(Network interface card or NIC drivers)。NIC驅動直接管理着網絡接口卡(NIC)。NIC驅動接下邊與硬件連接,從上邊表現為一個接口,該接口允許高層發送數據包到網絡上,處理中斷,重置NIC,停止NIC,查詢和設置驅動的運行特征。NIC驅動可以是小端口(miniport)或完全的NIC驅動(full NIC driver)。

Miniport驅動僅僅實現了管理NIC的必要操作,包括在NIC上發送和接收數據。對于所有最底層的NIC驅動的操作由NDIS提供,例如同步(synchronization)。小端口(miniport)不直接調用操作系統函數,它們對于操作系統的接口是NDIS。

小端口僅僅是向上傳遞數據包給NDIS并且NDIS确保這些數據包被傳遞給正确的協議。

完全NIC驅動(Full NIC driver)完成硬件細節的操作和所有由NDIS完成的同步和查詢操作。例如,完全NIC驅動維持接收到的數據的綁定信息。

(2) 中間層驅動

(Intermediate drivers)中間層驅動位于高層驅動(例如協議驅動)和小端口之間。對于高層驅動,中間層驅動看起來像是小端口;對于小端口,中間層驅動看起來像協議驅動。一個中間層協議驅動可以位于另一個中間層驅動之上,盡管這種分層可能對系統性能帶來負面影響。開發中間層驅動的一個關鍵原因是在現存的遺留協議驅動(legacy protocol driver)和小端口之間形成媒體的轉化。例如,中間層驅動可以将LAN協議轉換成ATM協議。中間層驅動不能與用戶模式的應用程序通信,但可以與其他的NDIS驅動通信。

(3) 傳輸驅動或協議驅動

(Transport drivers or protocol drivers)協議驅動實現了網絡協議棧,例如IPX/SPX或TCP/IP,在一個或多個網絡接口卡上提供它的服務。在協議驅動的上面,它為應用層客戶程序服務;在它的下面,它與一個或多個NIC驅動或中間層NDIS驅動連接。

NPF是一個協議驅動。從性能方面來看,這不是最好的選擇,但是它合理地獨立于MAC層并且有權使用原始通信(raw traffic)

NPF結構基礎

下圖表現了伴随着NPF驅動細節的Winpcap的結構。

抓包

抓包是NPF最重要的操作。在抓包的時候,驅動使用一個網絡接口監視着數據包,并将這些數據包完整無缺地投遞給用戶級應用程序。

抓包過程依賴于兩個主要組件:

一個數據包過濾器,它決定着是否接收進來的數據包并把數據包拷貝給監聽程序。數據包過濾器是一個有布爾輸出的函數。如果函數值是true,抓包驅動拷貝數據包給應用程序;如果是false,數據包将被丢棄。NPF數據包過濾器更複雜一些,因為它不僅決定數據包是否應該被保存,而且還得決定要保存的字節數。被NPF驅動采用的過濾系統來源于BSD Packet Filter(BPF),一個虛拟處理器可以執行僞彙編書寫的用戶級過濾程序。

應用程序采用用戶定義的過濾器并使用wpcap.dll将它們編譯進BPF程序。然後,應用程序使用BIOCSETF IOCTL寫入核心态的過濾器。這樣,對于每一個到來的數據包該程序都将被執行,而滿足條件的數據包将被接收。與傳統解決方案不同,NPF不解釋(interpret)過濾器,而是執行(execute)它。由于性能的原因,在使用過濾器前,NPF提供一個JIT編譯器将它轉化成本地的80x86函數。當一個數據包被捕獲,NPF調用這個本地函數而不是調用過濾器解釋器,這使得處理過程相當快。

一個循環緩沖區,用來保存數據包并且避免丢失。一個保存在緩沖區中的數據包有一個頭,它包含了一些主要的信息,例如時間戳和數據包的大小,但它不是協議頭。此外,以隊列插入的方式來保存數據包可以提高數據的存儲效率。可以以組的方式将數據包從NPF緩沖區拷貝到應用程序。這樣就提高了性能,因為它降低了讀的次數。如果一個數據包到來的時候緩沖區已經滿了,那麼該數據包将被丢棄,因此就發生了丢包。

實例

獲得網卡接口。在普通的SOCKET編程中,對雙網卡編程是不行的。當主機為雙網卡時,本程序可分别獲得兩張網卡各自的描述結構及地址,然後可以對它們分别進行操作。返回的alldevs隊列首部為邏輯網卡,一般不對它進行什麼操作。

獲得網卡接口

#i nclude "pcap.h"

void main()

{

pcap_if_t *alldevs;

/*struct pcap_if_t{

pcap_if_t *next;

char *name;

char *description;

pcap_addr *addresses; 

U_int falgs; 

*/ 

pcap_if_t *d; 

int i=0; 

char errbuf[PCAP_ERRBUF_SIZE]; 

/* Retrieve the device list */ 

if (pcap_findalldevs(&alldevs, errbuf) == -1)//返回網卡列表,alldevs指向表頭 

fprintf(stderr,"Error in pcap_findalldevs: %sn", 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; 

/* We don't need any more the device list. Free it */ 

pcap_freealldevs(alldevs); 

--------------------------------------------------------------------------------

俘獲

本程序俘獲 局域網内 UDP報文。 

#i nclude "pcap.h" 

/* 4 bytes IP address */ 

typedef struct ip_address{ 

u_char byte1; 

u_char byte2; 

u_char byte3; 

u_char byte4; 

}ip_address; 

/* IPv4 header */ 

typedef struct ip_header{ 

u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) 

u_char tos; // Type of service 

u_short tlen; // Total length 

u_short identification; // Identification 

u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) 

u_char ttl; // Time to live 

u_char proto; // Protocol 

u_short crc; // Header checksum 

ip_address saddr; // Source address 

ip_address daddr; // Destination address 

u_int op_pad; // Option + Padding 

}ip_header; 

/* UDP header*/ 

typedef struct udp_header{ 

u_short sport; // Source port 

u_short dport; // Destination port 

u_short len; // Datagram length 

u_short crc; // Checksum 

}udp_header; 

/* prototype of the packet handler */ 

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

main() 

pcap_if_t *alldevs; 

pcap_if_t *d; 

int inum; 

int i=0; 

pcap_t *adhandle; 

char errbuf[PCAP_ERRBUF_SIZE]; 

u_int netmask; 

char packet_filter[] = "ip and udp"; 

struct bpf_program fcode; 

/* Retrieve the device list */ 

if (pcap_findalldevs(&alldevs, errbuf) == -1) 

fprintf(stderr,"Error in pcap_findalldevs: %sn", 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("%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 adapter */ 

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

65536, // portion of the packet to capture. 

// 65536 grants that the whole packet will be captured on all the MACs. 

1, // promiscuous mode 

1000, // read timeout 

errbuf // error buffer 

) ) == NULL) 

fprintf(stderr,"nUnable to open the adapter. %s is not supported by WinPcapn"); 

/* Free the device list */ 

pcap_freealldevs(alldevs); 

return -1; 

/* Check the link layer. We support only Ethernet for simplicity. */ 

if(pcap_datalink(adhandle) != DLT_EN10MB) 

fprintf(stderr,"nThis program works only on Ethernet networks.n"); 

/* Free the device list */ 

pcap_freealldevs(alldevs); 

return -1; 

if(d->addresses != NULL) 

/* Retrieve the mask of the first address of the interface */ 

netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; 

else 

/* If the interface is without addresses we suppose to be in a C class network */ 

netmask=0xffffff; 

//compile the filter 

if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ){ 

fprintf(stderr,"nUnable to compile the packet filter. Check the syntax.n"); 

/* Free the device list */ 

pcap_freealldevs(alldevs); 

return -1; 

//set the filter 

if(pcap_setfilter(adhandle, &fcode)<0){ 

fprintf(stderr,"nError setting the filter.n"); 

/* 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]; 

ip_header *ih; 

udp_header *uh; 

u_int ip_len; 

/* convert the timestamp to readable format */ 

ltime=localtime(&header->v_sec); 

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

/* print timestamp and length of the packet */ 

/* retireve the position of the ip header */ 

ih = (ip_header *) (pkt_data + 

14); //length of ethernet header 

/* retireve the position of the udp header */ 

ip_len = (ih->ver_ihl & 0xf) * 4; 

uh = (udp_header *) ((u_char*)ih + ip_len); 

/* convert from network byte order to host byte order */ 

printf("%s.%.6d len:%d ", timestr, header->_usec, header->len); 

/* print ip addresses */ 

printf("%d.%d.%d.%d -> %d.%d.%d.%dn", 

ih->saddr.byte1, 

ih->saddr.byte2, 

ih->saddr.byte3, 

ih->saddr.byte4, 

ih->daddr.byte1, 

ih->daddr.byte2, 

ih->daddr.byte3, 

ih->daddr.byte4 

); 

--------------------------------------------------------------------------------

發包

要在命令行下運行,給與參數:網卡描述符。或者添加代碼findalldevs(),那樣應很方便。 

#i nclude 

#i nclude 

#i nclude 

void usage(); 

void main(int argc, char **argv) { 

pcap_t *fp; 

char error[PCAP_ERRBUF_SIZE]; 

u_char packet[100]; 

int i; 

/* Check the validity of the command line */ 

if (argc != 2) 

printf("usage: %s inerface", argv[0]); 

return; 

/* Open the output adapter */ 

if((fp = pcap_open_live(argv[1], 100, 1, 1000, error) ) == NULL) 

fprintf(stderr,"nError opening adapter: %sn", error); 

return; 

/* Supposing to be on ethernet, set mac destination to 1:1:1:1:1:1 */ 

packet[0]=1; 

packet[1]=1; 

packet[2]=1; 

packet[3]=1; 

packet[4]=1; 

packet[5]=1; 

/* set mac source to 2:2:2:2:2:2 */ 

packet[6]=2; 

packet[7]=2; 

packet[8]=2; 

packet[9]=2; 

packet[10]=2; 

packet[11]=2; 

/* Fill the rest of the packet */ 

for(i=12;i<100;i++){ 

packet =i%256; 

/* Send down the packet */ 

pcap_sendpacket(fp, 

packet, 

100); 

return; 

卸載不幹淨的解決方法

winpcap 卸載不幹淨的的時候,在windows下删除一些文件即可,删除下面的文件即可: 

c:windowssystem32Packet.dll 

c:windowssystem32drivers/ npf.sys

c:windowssystem32 WanPacket.dll

c:windowssystem32wpcap.dll 

c:windowssystem32pthreadVC.dll

上一篇:420

下一篇:馬殺雞

相關詞條

相關搜索

其它詞條