明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

詳細(xì)介紹怎么捕獲網(wǎng)絡(luò)數(shù)據(jù)包

[摘要]前 言 經(jīng)?吹秸搲腥藛柶痍P(guān)于數(shù)據(jù)包的截獲、分析等問題,幸好本人也對(duì)此略有所知,也寫過很多的sniffer,所以就想寫一系列的文章來詳細(xì)深入的探討關(guān)于數(shù)據(jù)包的知識(shí)。 我希望通過這一系列的文章...

前 言
經(jīng)?吹秸搲腥藛柶痍P(guān)于數(shù)據(jù)包的截獲、分析等問題,幸好本人也對(duì)此略有所知,也寫過很多的sniffer,所以就想寫一系列的文章來詳細(xì)深入的探討關(guān)于數(shù)據(jù)包的知識(shí)。
我希望通過這一系列的文章,能使得關(guān)于數(shù)據(jù)包的知識(shí)得以普及,所以這系列的每一篇文章我都會(huì)有由淺入深的解釋、詳細(xì)的分析、以及編碼步驟,另外附上帶有詳細(xì)注釋的源碼(為了照顧大多數(shù)朋友,我提供的都是MFC的源碼)。
不過由于也是初學(xué)者,疏漏之處還望不吝指正。
本文凝聚著筆者心血,如要轉(zhuǎn)載,請(qǐng)指明原作者及出處,謝謝!^_^

OK,. Let’s go ! Have fun!! q^_^p

第二篇 手把手教你捕獲數(shù)據(jù)包
目錄:
一.捕獲數(shù)據(jù)包的實(shí)現(xiàn)原理
二.捕獲數(shù)據(jù)包的編程實(shí)現(xiàn):
1. raw socket的實(shí)現(xiàn)方法
2. Winpcap的實(shí)現(xiàn)方法
a. 枚舉本機(jī)網(wǎng)卡的信息
b. 打開相應(yīng)網(wǎng)卡并設(shè)置為混雜模式
c. 截獲數(shù)據(jù)包并保存為文件

作者:
CSDN VC/MFC 網(wǎng)絡(luò)編程版主 PiggyXP

一.捕獲數(shù)據(jù)包的實(shí)現(xiàn)原理:--------------------------------------------------------------------
在通常情況下,網(wǎng)絡(luò)通信的套接字程序只能響應(yīng)與自己硬件地址相匹配的或是以廣播形式發(fā)出的數(shù)據(jù)幀,對(duì)于其他形式的數(shù)據(jù)幀比如已到達(dá)網(wǎng)絡(luò)接口但卻不是發(fā)給此 地址的數(shù)據(jù)幀,網(wǎng)絡(luò)接口在驗(yàn)證投遞地址并非自身地址之后將不引起響應(yīng),也就是說應(yīng)用程序無法收取與自己無關(guān)的的數(shù)據(jù)包。
所以我們要想實(shí)現(xiàn)截獲流經(jīng)網(wǎng)絡(luò)設(shè)備的所有數(shù)據(jù)包,就要采取一點(diǎn)特別的手段了:
將網(wǎng)卡設(shè)置為混雜模式。
這樣一來,該主機(jī)的網(wǎng)卡就可以捕獲到所有流經(jīng)其網(wǎng)卡的數(shù)據(jù)包和幀。
但是要注意一點(diǎn),這種截獲僅僅是數(shù)據(jù)包的一份拷貝,而不能對(duì)其進(jìn)行截?cái),要想截(cái)嗑W(wǎng)絡(luò)流量就要采用一些更底層的辦法了,不在本文的討論范圍之內(nèi)。

二. 捕獲數(shù)據(jù)包的編程實(shí)現(xiàn):
1.raw socket的實(shí)現(xiàn)方法--------------------------------------------------------------------
不同于我們常用的數(shù)據(jù)流套接字和數(shù)據(jù)報(bào)套接字,在創(chuàng)建了原始套接字后,需要用WSAIoctl()函數(shù)來設(shè)置一下,它的定義是這樣的
int WSAIoctl(
SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpvOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
雖然咋一看參數(shù)比較多,但是其實(shí)我們最關(guān)心的只是其中的第二項(xiàng)而已,我們需要做的就是把第二項(xiàng)設(shè)置為SIO_RCVALL,講了這么多其實(shí)要做的就是這么一行代碼,很簡(jiǎn)單吧?^_^
當(dāng)然我們還可以指定是否親自處理IP頭,但是這并不是必須的。
完整的代碼類似與如下這樣,加粗的代碼是與平常不同的需要注意的地方:
( 為了讓代碼一目了然,我把錯(cuò)誤處理去掉了,下同)

#include “WinSock2.h”
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

SOCKET SnifferSocket
WSADATA wsaData;
iFlag=WSAStartup(MAKEWORD(2,2),&wsaData); //開啟winsock.dll

SnifferSocket=WSASocket(AF_INET, //創(chuàng)建raw socket
SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);

char FAR name[128]; //獲取本機(jī)IP地址
gethostname(name, sizeof(name));
struct hostent FAR * pHostent;
pHostent = gethostbyname(name);

SOCKADDR_IN sa; //填充SOCKADDR_IN結(jié)構(gòu)的內(nèi)容
sa.sin_family = AF_INET;
sa.sin_port = htons(6000); // 端口號(hào)可以隨便改,當(dāng)然與當(dāng)然系統(tǒng)不能沖突
memcpy(&(sa.sin_addr),pHostent->h_addr,pHostent->h_length);

bind(SnifferSocket,(LPSOCKADDR)&sa,sizeof(sa)); //綁定
// 置ioctl來接收所有網(wǎng)絡(luò)數(shù)據(jù),關(guān)鍵步驟
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
WSAIoctl(SnifferSocket, IO_RCVALL,&dwBufferInLen, izeof(dwBufferInLen),
&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
至此,實(shí)際就可以開始對(duì)網(wǎng)絡(luò)數(shù)據(jù)包進(jìn)行嗅探了,而對(duì)于數(shù)據(jù)包的接收還是和普通的socket一樣,通過recv()函數(shù)來完成,因?yàn)檫@里涉及到不同的socket模型,接收方法差別很大,所以在此就不提供接收的代碼了。

2.winpcap的實(shí)現(xiàn)方法:-----------------------------------------------------------------------
winpcap驅(qū)動(dòng)包,是我們玩轉(zhuǎn)數(shù)據(jù)包不可或缺的好東東,winpcap的主要功能在于獨(dú)立于主機(jī)協(xié)議(如TCP-IP)而發(fā)送和接收原始數(shù)據(jù)報(bào),主要為我們提供了四大功能:
功能:
1> 捕獲原始數(shù)據(jù)報(bào),包括在共享網(wǎng)絡(luò)上各主機(jī)發(fā)送/接收的以及相互之間交換的數(shù)據(jù)報(bào);
2> 在數(shù)據(jù)報(bào)發(fā)往應(yīng)用程序之前,按照自定義的規(guī)則將某些特殊的數(shù)據(jù)報(bào)過濾掉;
3> 在網(wǎng)絡(luò)上發(fā)送原始的數(shù)據(jù)報(bào);
4> 收集網(wǎng)絡(luò)通信過程中的統(tǒng)計(jì)信息
如果環(huán)境允許的話(比如你做的不是木馬程序),我還是推薦大家用winpcap來截獲數(shù)據(jù)包,因?yàn)樗墓δ芨鼜?qiáng)大,工作效率更高,唯一的缺點(diǎn)就是在運(yùn)行用winpcap開發(fā)的程序以前,都要在主機(jī)上先安裝winpcap的driver。
而且一會(huì)我們就會(huì)發(fā)現(xiàn)它比raw socket功能強(qiáng)大的多,而且工作得更為底層,最明顯的理由就是raw socket捕獲的數(shù)據(jù)包是沒有以太頭的,此乃后話。
至于怎么來安裝使用,請(qǐng)參考本系列的系列一《手把手教你玩轉(zhuǎn)ARP包中的》,里面有詳細(xì)的加載winpcap驅(qū)動(dòng)的方法^_^
廢話不多說了,讓我們轉(zhuǎn)入正題, 具體用winpcap來截獲數(shù)據(jù)包需要做如下的一些工作:
A . 枚舉本機(jī)網(wǎng)卡的信息(主要是獲得網(wǎng)卡的名稱)
其中要用到pcap_findalldevs函數(shù),它是這樣定義的
/*************************************************
int pcap_findalldevs ( pcap_if_t ** alldevsp,
char * errbuf
)
功能:
枚舉系統(tǒng)所有網(wǎng)絡(luò)設(shè)備的信息
參數(shù): alldevsp: 是一個(gè)pcap_if_t結(jié)構(gòu)體的指針,如果函數(shù)pcap_findalldevs函數(shù)執(zhí)行成功,將獲得一個(gè)可用網(wǎng)卡的列表,而里面存儲(chǔ)的就是第一個(gè)元素的指針。
Errbuf: 存儲(chǔ)錯(cuò)誤信息的字符串
返回值: int : 如果返回0 則執(zhí)行成功,錯(cuò)誤返回 -1。
*************************************************/
我們利用這個(gè)函數(shù)來獲得網(wǎng)卡名字的完整代碼如下:

pcap_if_t* alldevs;
pcap_if_t* d;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_findalldevs(&alldevs,errbuf); // 獲得網(wǎng)絡(luò)設(shè)備指針
for(d=alldevs;d;d=d->next) // 枚舉網(wǎng)卡然后添加到ComboBox中
{
d->name; // d->name就是我們需要的網(wǎng)卡名字字符串,按照你// 自己的需要保存到你的相應(yīng)變量中去
}
pcap_freealldevs(alldevs); // 釋放alldev資源
B. 打開相應(yīng)網(wǎng)卡并設(shè)置為混雜模式: 在此之前肯定要有一段讓用戶選擇網(wǎng)卡、并獲得用戶選擇的網(wǎng)卡的名字的代碼,既然上面已經(jīng)可以獲得所有網(wǎng)卡的名字了,這段代碼就暫且略過了。


上面是電腦上網(wǎng)安全的一些基礎(chǔ)常識(shí),學(xué)習(xí)了安全知識(shí),幾乎可以讓你免費(fèi)電腦中毒的煩擾。