日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

计算机网络课程设计之网络嗅探器的设计与实现

發布時間:2025/3/15 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机网络课程设计之网络嗅探器的设计与实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本實驗難點是在于Windows下的raw socket有太多的限制,因此用winpcap編程功能更加強大,但是根據指導書要求要用原始套接字,原始套接字在Linux系統下也十分強大,結尾附上Linuxraw socket源碼 ,但是因為我本人想要將課設全部寫在同一個軟件中,只能查詢資料實現Windows。
參考博客 :(感謝大佬)
https://www.writebug.com/git/codes?owner=Schoolleave&repo=RawSocket_Test
不過需要指出的是,大佬的代碼對于TCP的解析是有問題的,第一是TCP報文長度,第二個是TCP數據部分的解析,由于課設時間和本人的能力有限,僅做了部分修改。再次感謝大佬的開源!!!

白嫖容易,創作不易,本文原創,轉載請注明!!!
源碼和可運行程序:
鏈接:https://pan.baidu.com/s/1A9KctmpP2JJgyW2wLrehIg
提取碼:Lin2

計算機網絡課程設計:
計算機網絡課程設計之網絡聊天程序的設計與實現
計算機網絡課程設計之Tracert與Ping程序設計與實現
計算機網絡課程設計之基于 IP 多播的網絡會議程序
計算機網絡課程設計之網絡嗅探器的設計與實現
計算機網絡課程設計之電子郵件客戶端程序設計與實現
計算機網絡課程設計之TELNET 終端設計與實現
計算機網絡課程設計之網絡代理服務器的設計與實現
計算機網絡課程設計之簡單 Web Server 程序的設計與實現

Qt入門系列:
Qt學習之C++基礎
Qt學習之Qt安裝
Qt學習之Qt基礎入門(上)
Qt學習之Qt基礎入門(中)
Qt學習之Qt基礎入門(下)

創作不易,整個課程設計程序3000多行代碼,所有實驗都寫在了一個程序中,時間有限,能力不足,轉載望注明!!!
本文鏈接
個人博客:https://ronglin.fun/archives/270
PDF鏈接:見博客網站
CSDN: https://blog.csdn.net/RongLin02/article/details/122510398

實驗題目

網絡嗅探器的設計與實現

實驗目的

參照附錄 4 raw socket 編程例子,設計一個可以監視網絡的狀態、數據流動情況以及網絡上傳輸的信息的網絡嗅探器。

總體設計

(含背景知識或基本原理與算法、或模塊介紹、設計步驟等)
主要用到的是RawSocket
主要是思路是:
創建RawSocket套接字-> 綁定到對應的網卡上 -> 設置混雜模式(為了抓到所有包) -> 調用recvfrom()接受數據 ->解析數據
主要的難點是要根據抓到的數據報解析協議,然后根據不同的協議解析對應的數據,注意的是要根據不用的協議的不同的首部長度來提取數據內容
背景知識

  • 原始套接字工作原理與規則
    原始套接字是一種不同于 SOCK_STREAM 和 SOCK_DGRAM 的套接字,它實現于系統核心。它的創建方式跟 TCP/UDP 創建方法幾乎是一模一樣,例如,通過
  • int sockfd; sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);

    這兩句程序你就可以創建一個原始套接字。這種類型套接字的功能與 TCP 或者 UDP 類型套接字的功能有很大的不同:TCP/UDP 類型的套接字只能夠訪問傳輸層以及傳輸層以上的數據,因為當 IP層把數據傳遞給傳輸層時,下層的數據包頭已經被丟掉了。而原始套接字卻可以訪問傳輸層以下的數據,所以使用 raw 套接字你可以實現上至應用層的數據操作,也可以實現下至鏈路層的數據操作。比如:通過

    sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP))

    方式創建的 rawsocket 就能直接讀取鏈路層的數據。
    1)使用原始套接字時應該注意的問題(參考<<unix 網絡編程>>以及網上的優秀文檔)
    (1):對于 UDP/TCP 產生的 IP 數據包,內核不將它傳遞給任何原始套接字,而只是將這些數據交給對應的 UDP/TCP 數據處理句柄(所以,如果你想要通過原始套接字來訪問 TCP/UDP 或者其它類型的數據,調用 socket 函數創建原始套接字第三個參數應該指定為 htons(ETH_P_IP),也就是通過直接訪問數據鏈路層來實現。(我們后面的密碼竊取器就是基于這種類型的)。
    (2):對于 ICMP 和 EGP 等使用 IP 數據包承載數據但又在傳輸層之下的協議類型的 IP 數據包,內核不管是否已經有注冊了的句柄來處理這些數據,都會將這些 IP 數據包復制一份傳遞給協議類型匹配的原始套接字。
    (3):對于不能識別協議類型的數據包,內核進行必要的校驗,然后會查看是否有類型匹配的原始套接字負責處理這些數據,如果有的話,就會將這些 IP 數據包復制一份傳遞給匹配的原始套接字,否則,內核將會丟棄這個 IP 數據包,并返回一個 ICMP 主機不可達的消息給源主機。
    (4):如果原始套接字 bind 綁定了一個地址,核心只將目的地址為本機 IP 地址的數據包傳遞給原始套接字,如果某個原始套接字沒有 bind 地址,核心就會把收到的所有 IP 數據包發給這個原始套接字。
    (5):如果原始套接字調用了 connect 函數,則核心只將源地址為 connect 連接的 IP 地址的 IP 數據包傳遞給這個原始套接字。
    (6):如果原始套接字沒有調用 bind 和 connect 函數,則核心會將所有協議匹配的 IP 數據包傳遞給這個原始套接字。
    2. 編程選項
    原始套接字是直接使用 IP 協議的非面向連接的套接字,在這個套接字上可以調用 bind 和 connect函數進行地址綁定。說明如下:
    (1)bind 函數:調用 bind 函數后,發送數據包的源 IP 地址將是 bind 函數指定的地址。如果不調用bind,則內核將以發送接口的主IP地址填充IP頭 。 如 果 使 用 setsockopt 設置了IP_HDRINCL(headerincluding)選項,就必須手工填充每個要發送的數據包的源 IP 地址,否則,內核將
    自動創建 IP 首部。
    (2)connetc 函數:調用 connect 函數后,就可以使用 write 和 send 函數來發送數據包,而且內核將會用這個綁定的地址填充 IP 數據包的目的 IP 地址,否則的話,則應使用 sendto 或 sendmsg 函數來發送數據包,并且要在函數參數中指定對方的 IP 地址。
    綜合以上種種功能和特點,我們可以使用原始套接字來實現很多功能,比如最基本的數據包分析,主機嗅探等。其實也可以使用原始套接字作一個自定義的傳輸層協議

    詳細設計

    (含主要的數據結構、程序流程圖、關鍵代碼等)
    核心的功能方法主要有兩個
    1.轉化結果

    QString getDataFromPacket(BYTE *lpBuf, int iLen, int iPrintType);

    此方法是用來將一個字節數組轉化為一個可輸出的字符串,int iPrintType有兩個參數,一個是按照16進制輸出,還有一個是按照ASCII碼輸出。
    前者用到的主要解析代碼如下

    len += sprintf(t+len,"%02x ",lpBuf[i]);

    主要是用系統的格式化輸出到字符串中,用到%x輸出
    后者解析ASCII碼用的是強制類型轉化,如下

    t[len++] =(char)lpBuf[i];
  • 解析數據報
  • void analyseRecvPacket(BYTE *lpBuf);

    這個方法是核心,當然主要是參考了大佬的解析代碼,下邊進行簡單的說明
    主要流程有兩個,一個是先分析IP包的協議類型,第二個是根據協議類型分析首部和數據部分,代碼如下:

    void MySniffer::analyseRecvPacket(BYTE *lpBuf) {//Windows上沒辦法用Raw Socket抓MAC層的數據包,只能抓到IP層及以上的數據包!!!//注意:數據包的字節順序轉換問題!!!//這里要將網絡字節序轉換為本地字節序struct sockaddr_in saddr, daddr;PIPV4HEADER t_ip = (PIPV4HEADER)lpBuf;if(t_ip->ipv4_pro == IPPROTO_ICMP){saddr.sin_addr.s_addr = t_ip->ipv4_sourpa;daddr.sin_addr.s_addr = t_ip->ipv4_destpa;emit this->sendData(QStringList()<<"ICMP"<<inet_ntoa(saddr.sin_addr)<<inet_ntoa(daddr.sin_addr)<<""<<"");}else if(t_ip->ipv4_pro == IPPROTO_IGMP){saddr.sin_addr.s_addr = t_ip->ipv4_sourpa;daddr.sin_addr.s_addr = t_ip->ipv4_destpa;emit this->sendData(QStringList()<<"IGMP"<<inet_ntoa(saddr.sin_addr)<<inet_ntoa(daddr.sin_addr)<<""<<"");}else if(t_ip->ipv4_pro == IPPROTO_TCP){PTCPHEADER tcp = (PTCPHEADER)(lpBuf + (t_ip->ipv4_ver_hl & 0x0F) * 4);int hlen = ((t_ip->ipv4_ver_hl & 0x0F) * 4) + ((((tcp->tcp_hlen)>>4 & 0x0F) * 4)& 0x0F);int dlen = ((quint16)ntohs(t_ip->ipv4_plen )) - hlen; //這里要將網絡字節序轉換為本地字節序saddr.sin_addr.s_addr = t_ip->ipv4_sourpa;daddr.sin_addr.s_addr = t_ip->ipv4_destpa;QStringList string_tcp;string_tcp<<"TCP";string_tcp <<QString(inet_ntoa(saddr.sin_addr))+":"+QString::number(ntohs(tcp->tcp_sourport));string_tcp <<QString(inet_ntoa(daddr.sin_addr))+":"+QString::number(ntohs(tcp->tcp_destport));string_tcp<<getDataFromPacket((lpBuf + hlen), dlen, 0);//MyPrintf("ack:%u syn:%u length=%d\n", tcp->tcp_acknu, tcp->tcp_seqnu, dlen);string_tcp <<QString("ack:%1 syn:%2 length=%3").arg(tcp->tcp_acknu).arg(tcp->tcp_seqnu).arg(dlen);emit this->sendData(string_tcp);}else if(t_ip->ipv4_pro == IPPROTO_UDP){PUDPHEADER udp = (PUDPHEADER)(lpBuf + (t_ip->ipv4_ver_hl & 0x0F) * 4);int hlen = (int)((t_ip->ipv4_ver_hl & 0x0F) * 4 + sizeof(UDPHEADER));int dlen = (int)(ntohs(udp->udp_hlen) - 8);// int dlen = (int)(udp->udp_hlen - 8);saddr.sin_addr.s_addr = t_ip->ipv4_sourpa;daddr.sin_addr.s_addr = t_ip->ipv4_destpa;QStringList string_udp;string_udp<<"UDP";string_udp <<QString(inet_ntoa(saddr.sin_addr))+":"+QString::number(ntohs(udp->udp_sourport));string_udp <<QString(inet_ntoa(daddr.sin_addr))+":"+QString::number(ntohs(udp->udp_destport));string_udp<<getDataFromPacket((lpBuf + hlen), dlen, 0);string_udp <<"";emit this->sendData(string_udp);}else{saddr.sin_addr.s_addr = t_ip->ipv4_sourpa;daddr.sin_addr.s_addr = t_ip->ipv4_destpa;emit this->sendData(QStringList()<<"OTHER"<<inet_ntoa(saddr.sin_addr)<<inet_ntoa(daddr.sin_addr)<<""<<"");}}

    需要注意的是,數據報的格式定義在了一個packetstruct.h的文件中,其中定義了IPV4、IPV6、ARP字段結構體、以太網幀頭格式結構體、TCP、UDP的結構體

    實驗結果與分析


    點擊保存到文件,然后把數據保存到,軟件運行路徑下

    打開txt文件,可以看到數據格式

    可以注意到,TCP格式的解析有問題,UDP的首部是固定8字節,解析起來就比較簡單,所以沒啥問題,但是TCP首部復雜,問題主要出現在長度解析和內容解析,精力有限,如果還有時間就再次深入的修改一下代碼。
    根據TCP首部,做了部分修改

    小結與心得體會

    通常我們都是使用類似WireShark的抓包軟件嗅探數據包,這些抓包工具大部分都是基于WinPcap庫實現的數據包嗅探功能。而現在,本實驗是使用原始套接字的RawSocket方式實現數據包的嗅探。當然,和WinPcap相比,Raw Socket有很大的局限性。,它只能抓到IP層及以上的數據包,抓不到MAC層的數據包。而且還需要管理員權限,但是本次實驗對于TCP/UDP的數據格式有了很深的理解,獲益匪淺。
    =w=

    總結

    以上是生活随笔為你收集整理的计算机网络课程设计之网络嗅探器的设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。