MFC+WinPcap編寫一個嗅探器之六(分析模塊)


這一節是程序的核心,也是最復雜的地方

首先需要明白的一點是,一般對於一個有界面的程序來說,往往需要多線程。本程序中除了界面線程外,抓包需要另外創建一個新的線程。在寫抓包函數之前,首先要將前面兩個模塊的結果返回到主對話框界面對應的類實現中,在SnifferDlg.cpp中,修改之前增加的兩個模塊的觸發函數如下:

1 void CSnifferDlg::OnAdp()
2 {
3     // TODO: 在此添加命令處理程序代碼
4     CAdpDlg adpdlg;
5     if(adpdlg.DoModal() == IDOK)
6     {
7         m_pDevice = adpdlg.returnd();
8     }
9 }
 1 void CSnifferDlg::OnFilter()
 2 {
 3     // TODO: 在此添加命令處理程序代碼
 4     CFilterDlg filterdlg;
 5     if(filterdlg.DoModal() == IDOK)
 6     {
 7         int len =WideCharToMultiByte(CP_ACP,0,filterdlg.GetFilterName(),-1,NULL,0,NULL,NULL); 
 8         WideCharToMultiByte(CP_ACP,0,filterdlg.GetFilterName(),-1,m_filtername,len,NULL,NULL );
 9         
10     }
11 }

 前一個函數是在打開選擇適配器窗口后,在用戶選擇完網卡后,將選擇的網卡返回到主界面的類實現中;后一個函數是在打開設置過濾規則后,將過濾規則的字符串返回到主界面的類實現中。也許你對第二個函數中的兩個函數不太明白,這是一個寬字符轉換為多字符的函數,就只需了解其中兩個參數即可,其它的復制粘貼,函數是這樣使用的。獲得了前兩個模塊的返回值,就可以來寫抓包函數了,創建一個新線程,抓包函數代碼如下:

 1 DWORD WINAPI CapturePacket(LPVOID lpParam)
 2 {
 3     CSnifferDlg *pDlg = (CSnifferDlg *)lpParam;
 4     pcap_t *pCap;
 5     char    strErrorBuf[PCAP_ERRBUF_SIZE];
 6     int res;
 7     struct pcap_pkthdr *pkt_header;
 8     const u_char *pkt_data;
 9     u_int netmask;
10     struct bpf_program fcode;
11 
12     if((pCap=pcap_open_live(pDlg->m_pDevice->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,strErrorBuf))==NULL)
13     {        
14         return -1;
15     }
16 
17     if(pDlg->m_pDevice->addresses != NULL)
18         /* 獲得接口第一個地址的掩碼 */
19         netmask=((struct sockaddr_in *)(pDlg->m_pDevice->addresses->netmask))->sin_addr.S_un.S_addr;
20     else
21         /* 如果接口沒有地址,那么我們假設一個C類的掩碼 */
22         netmask=0xffffff; 
23         //編譯過濾器
24         if (pcap_compile(pCap, &fcode,pDlg->m_filtername, 1, netmask) <0 )
25         {
26             AfxMessageBox(_T("請設置過濾規則"));
27             return -1;
28         }
29         //設置過濾器
30         if (pcap_setfilter(pCap, &fcode)<0)
31             return -1;
32 
33     while((res = pcap_next_ex( pCap, &pkt_header, &pkt_data)) >= 0)
34     {
35 
36         if(res == 0)
37             continue;
38         if(!pDlg->m_bFlag)
39             break;
40         CSnifferDlg *pDlg = (CSnifferDlg *)AfxGetApp()->GetMainWnd(); 
41         pDlg->ShowPacketList(pkt_header,pkt_data);
42         pDlg = NULL;
43     }
44 
45     pcap_close(pCap);
46     pDlg = NULL;
47     return 1;     
48 }

 解釋兩個地方,一是怎樣控制開始抓包和停止抓包,這里采用了一個bool變量m_bFlag,這個變量初值是FALSE,當點擊菜單中的開始捕獲變量為true,點擊停止捕獲變量又變為false。二是當抓完一個包后,又將指針指向主界面的句柄,之后將抓來的數據包的內容在主界面中顯示。

主界面中有三個需要顯示抓包內容的地方,一是數據包的概略信息,用ShowPacketList函數來實現;二是數據包的詳細信息用ShowPacketTree函數來實現;三是數據包的具體內容和統計信息。這三部分是大量相似的代碼,主要涉及到對網絡協議的分析,用到的主要是判斷語句,放到下一節講吧。

 

下一節 MFC+WinPcap編寫一個嗅探器之七(協議)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM