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