B.
打開相應(yīng)網(wǎng)卡并設(shè)置為混雜模式:
??
在此之前肯定要有一段讓用戶選擇網(wǎng)卡、并獲得用戶選擇的網(wǎng)卡的名字的代碼,既然上面已經(jīng)可以獲得所有網(wǎng)卡的名字了,這段代碼就暫且略過了。
??
我們主要是要用到
pcap_open_live
函數(shù),不過這個(gè)函數(shù)
winpcap
的開發(fā)小組已經(jīng)建議用
pcap_open
函數(shù)來代替,不過因?yàn)槲业拇a里面用的就是
pcap_open_live
,所以也不便于修改了,不過
pcap_open_live
使用起來也是沒有任何問題的,下面是
pcap_open_live
的函數(shù)聲明:
?/*************************************************
pcap_t* pcap_open_live? (? char *??? device,?
?
??????????????????????????
?int??? snaplen,?
? int??? promisc,?
? int??? to_ms,?
? char *??? ebuf
?)
?
????
功能:
??????????
根據(jù)網(wǎng)卡名字打開網(wǎng)卡,并設(shè)置為混雜模式,然后返回其句柄
????
參數(shù):
?????????? Device? :
就是前前面我們獲得的網(wǎng)卡的名字;
?????????? Snaplen :?
我們從每個(gè)數(shù)據(jù)包里取得數(shù)據(jù)的長(zhǎng)度,比如設(shè)置為
100
,則每次我們只是獲得每個(gè)數(shù)據(jù)包
100
個(gè)長(zhǎng)度的數(shù)據(jù),沒有什么特殊需求的話就把它設(shè)置為
65535
最大值就可以了;
?????????? Promisc
:這個(gè)參數(shù)就是設(shè)置是否把網(wǎng)卡設(shè)置為“混雜模式”,設(shè)置為
1
即可;
?????????? to_ms :??
超時(shí)時(shí)間,毫秒,一般設(shè)置為
1000
即可。
????
返回值:
?????????? pcap_t :?
類似于一個(gè)網(wǎng)卡“句柄”之類的,不過當(dāng)然不是,這個(gè)參數(shù)是后面截獲數(shù)據(jù)要用到的。
******************************************************************************/
雖然看起來比較復(fù)雜,不過用起來還是非常簡(jiǎn)單的,其實(shí)
1
行就
OK
了:
??
?
pcap_t* adhandle;
??????
char errbuf[PCAP_ERRBUF_SIZE];
//
打開網(wǎng)卡,并且設(shè)置為混雜模式
// pCardName
是前面?zhèn)鱽淼木W(wǎng)卡名字參數(shù)
adhandle = pcap_open_live(pCardName,65535,1,1000,errbuf);
?
C.
截獲數(shù)據(jù)包并保存為文件:
------------------------------------------------------
????
當(dāng)然,不把數(shù)據(jù)包保存為文件也可以,不過如果不保存的話,只能在截獲到數(shù)據(jù)包的那一瞬間進(jìn)行分析,轉(zhuǎn)眼就沒了
^_^
所以,為了便于日后分析,所以高手以及我個(gè)人經(jīng)常是把數(shù)據(jù)包保存下來的慢慢分析的。
但是注意網(wǎng)絡(luò)流量,在流量非常大的時(shí)候注意硬盤空間呵呵,常常幾秒中就有好幾兆是很正常的事情。
下面首先來詳細(xì)講解一下,這個(gè)步驟中需要用到的
winpcap
函數(shù):
/**************************************************************
pcap_dumper_t* pcap_dump_open? (? pcap_t *??? p,?
?
???????????????????????????????????
?const char *??? fname
?)
功能:
?????
建立或者打開存儲(chǔ)數(shù)據(jù)包內(nèi)容的文件
,
并返回其句柄
參數(shù):
?????
?pcap_t *??? p????
:前面打開的網(wǎng)卡句柄;
????? const char * fname
:要保存的文件名字
???
返回值:
?????? pcap_dumper_t*
:
保存文件的描述句柄,具體細(xì)節(jié)我們不用關(guān)心
***************************************************************/
/***************************************************************
int pcap_next_ex? ????????(? pcap_t *??? p,?
?
???????????????????????????
?struct pcap_pkthdr **??? pkt_header,?
? u_char **??? pkt_data
?)
?
功能:
?????
從網(wǎng)卡或者數(shù)據(jù)包文件中讀取數(shù)據(jù)內(nèi)容
參數(shù):
????? pcap_t *??? p:???
網(wǎng)卡句柄
????? struct pcap_pkthdr ** pkt_header:
并非是數(shù)據(jù)包的指針,只是與數(shù)據(jù)包捕獲驅(qū)動(dòng)有關(guān)的一個(gè)
Header
????? u_char ** pkt_data
:指向數(shù)據(jù)包內(nèi)容的指針
,包括了協(xié)議頭
??
返回值:
?????
???
?1 :
如果成功讀取數(shù)據(jù)包
????????? 0
:
pcap_open_live()
設(shè)定的超時(shí)時(shí)間之內(nèi)沒有讀取到內(nèi)容
????????? -1:
出現(xiàn)錯(cuò)誤
????????? -2:
讀文件時(shí)讀到了末尾
***************************************************************/
/***************************************************************
void pcap_dump? (? u_char *??? user,?
?
?????????????????????const struct pcap_pkthdr *??? h,?
? const u_char *??? sp
?)
??
功能:
?????
將數(shù)據(jù)包內(nèi)容依次寫入
pcap_dump_open
()指定的文件中
參數(shù):
????? u_char * user?? :?
網(wǎng)卡句柄
????? const struct pcap_pkthdr * h:
并非是數(shù)據(jù)包的指針,只是與數(shù)據(jù)包捕獲驅(qū)動(dòng)有關(guān)的一個(gè)
Header
???
?
?const u_char * sp
:
數(shù)據(jù)包內(nèi)容指針
???
返回值:
????????? Void
****************************************************************/
?
下面給出一段完整的捕獲數(shù)據(jù)包的代碼,是在線程中寫的,為了程序清晰,我去掉了錯(cuò)誤處理代碼以及線程退出的代碼,完整代碼可下載文后的示例源碼,老規(guī)矩,重要的步驟用粗體字標(biāo)出。
我們實(shí)際在捕獲數(shù)據(jù)包的時(shí)候也最好是把代碼放到另外的線程中。
/*********************************************************
*??
進(jìn)程
:
*??????????????????
這個(gè)是程序的核心部分,完成數(shù)據(jù)包的截獲
*????
參數(shù)
:
*?????????????????? pParam:
用戶選擇的用來捕獲數(shù)據(jù)的網(wǎng)卡的名字
*********************************************************/
UINT CaptureThread(LPVOID pParam)
{
??????
const
char* pCardName=(char*)pParam;? ????????//
轉(zhuǎn)換參數(shù),獲得網(wǎng)卡名字
???????????????????????
?
?????? pcap_t* adhandle;
??????
char errbuf[PCAP_ERRBUF_SIZE];?????????????
??????
//
打開網(wǎng)卡,并且設(shè)置為混雜模式
?
adhandle=pcap_open_live(pCardName,65535,1,1000,errbuf)
;
?
??? {
?
?????? pcap_dumper_t* dumpfile;
//
建立存儲(chǔ)截獲數(shù)據(jù)包的文件
??????
dumpfile=pcap_dump_open(adhandle, "Packet.dat");
???
?
??????
int re;
?????? pcap_pkthdr* header;????? // Header
?????? u_char* pkt_data;???????? //
數(shù)據(jù)包內(nèi)容指針
//
從網(wǎng)卡或者文件中不停讀取數(shù)據(jù)包信息
??????
while((re=pcap_next_ex(adhandle,&header,(const u_char**)&pkt_data))>=0)
?
??? {
???
??????
//
將捕獲的數(shù)據(jù)包存入文件
?????????????
pcap_dump((unsignedchar*)dumpfile,header,pkt_data);
?????
?????? }
??????
return 0;
}
??
將個(gè)線程加入到程序里面啟動(dòng)以后。。。等等,如何來啟動(dòng)這個(gè)線程就不用我說了吧,類似這樣的代碼就可以
::AfxBeginThread(CaptureThread,chNIC);? ???// chNIC
是網(wǎng)卡的名字
,char*
類型
啟動(dòng)線程一段時(shí)間以后
(
幾秒中就有效果了
)
,可以看到數(shù)據(jù)包已經(jīng)被成功的截獲下來,并存儲(chǔ)到程序目錄下的
Packet.dat
文件中。
=====================================================
至此,數(shù)據(jù)包的截獲方法就講完了,大家看了這篇文章,其實(shí)你就一定也明白了,無(wú)論是
raw socket
的方法還是
winpcap
的方法,其實(shí)都很簡(jiǎn)單的,真的沒有什么東西,只是會(huì)讓不明白原理的人看起來很神秘而已,
isn’t it?
呵呵,不過也不要高興的太早,這個(gè)保存下來的數(shù)據(jù)包文件,你可以試著用
UltraEdit
打開這個(gè)文件看看,是不是大部分都是亂碼?基本上沒有什么可讀性,這是因?yàn)椋?/span>
此時(shí)捕獲到的數(shù)據(jù)包并不僅僅是單純的數(shù)據(jù)信息,而是包含有
IP
頭、
TCP
頭等信息頭的最原始的數(shù)據(jù)信息,這些信息保留了它在網(wǎng)絡(luò)傳輸時(shí)的原貌。通過對(duì)這些在低層傳輸?shù)脑夹畔⒌姆治隹梢缘玫接嘘P(guān)網(wǎng)絡(luò)的一些信息。由于這些數(shù)據(jù)經(jīng)過了網(wǎng)絡(luò)層和傳輸層的打包,因此需要根據(jù)其附加的幀頭對(duì)數(shù)據(jù)包進(jìn)行分析。
呵呵,所以我們要走的路還很長(zhǎng),這只是剛剛?cè)腴T而已
^_^
posted on 2007-02-16 15:53
飛鳥 閱讀(548)
評(píng)論(0) 編輯 收藏 所屬分類:
VC