日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

基于Linux C的socketEthereal程序和Package分析 (一个)

發(fā)布時間:2025/3/19 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Linux C的socketEthereal程序和Package分析 (一个) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


執(zhí)行測試平臺:CentOS 6.5發(fā)行版,內(nèi)核版本號3.11


1. Linux抓包源程序

OSI七層模型中。網(wǎng)卡工作在物理層和數(shù)據(jù)鏈路層的MAC子層。

進行網(wǎng)絡(luò)通信時。源主機通過socket(或其他)應(yīng)用程序產(chǎn)生IP報文,經(jīng)過各個OSI層層封裝,數(shù)據(jù)包以Ethernet幀的形式進入物理層。Ethernet幀包括源主機地址、IP報文、目標(biāo)地址(IP地址、port號或映射的6字節(jié)MAC地址)和須要傳送到目標(biāo)主機的其他信息。


目標(biāo)的MAC地址是哪里來的呢?這牽扯到一個ARP協(xié)議(介乎于網(wǎng)絡(luò)層和數(shù)據(jù)鏈路層的一個協(xié)議)。第一次傳送某個目的IP地址的數(shù)據(jù)的時候,先會發(fā)出一個ARP包。其MAC的目標(biāo)地址是廣播地址,里面說到:"誰是xxx.xxx.xxx.xxx這個IP地址的主人?"由于是廣播包,全部這個局域網(wǎng)的主機都收到了這個ARP請求。

收到請求的主機將這個IP地址和自己的相比較,假設(shè)不同樣就不予理會,假設(shè)同樣就發(fā)出ARP響應(yīng)包。

這個IP地址的主機收到這個ARP請求包后回復(fù)的ARP響應(yīng)里說到:"我是這個IP地址的主人"。這個包里面就包含了他的MAC地址。

以后的給這個IP地址的幀的目標(biāo)MAC地址就被確定了。


就這樣,以太網(wǎng)幀開始在數(shù)據(jù)鏈路層傳播。Ethernet幀在鏈路層基于廣播方式傳播,即網(wǎng)段內(nèi)的全部網(wǎng)卡都能觀察該幀,但僅僅有一個網(wǎng)卡通過對照6字節(jié)MAC地址發(fā)現(xiàn)與自己相符。然后它就接收該幀。而其他網(wǎng)卡則放棄該幀。(其他網(wǎng)卡也能夠接受該幀,即實際的網(wǎng)絡(luò)Sniffer,可進行信息竊取等操作)

網(wǎng)卡得到Ethernet幀后。通過網(wǎng)絡(luò)驅(qū)動程序和上層協(xié)議對其進行還原操作,即層層剝離報文頭后將數(shù)據(jù)交由目標(biāo)主機的socket(或其他)應(yīng)用程序使用。

假設(shè)我們須要原始的以太網(wǎng)幀,以便觀察與目標(biāo)主機進行通信的源主機信息,則能夠通過建立基于PF_PACKETsocket應(yīng)用程序?qū)崿F(xiàn)。PF_PACKET協(xié)議簇同意應(yīng)用程序直接獲得網(wǎng)絡(luò)驅(qū)動程序得到的數(shù)據(jù)幀信息。PF_PACKET支持SOCK_DGRAMSOCK_RAW兩種socket類型,前者利用操作系統(tǒng)處理報文頭,而后者則將以太網(wǎng)幀直接交由應(yīng)用程序處理。

須要注意到是,僅僅有root權(quán)限用戶才干使用PF_PACKET程序。

以下的代碼就可以實現(xiàn)由應(yīng)用程序直接獲得以太網(wǎng)幀的需求。

#include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <linux/if_ether.h> #include <linux/in.h>#define BUFFER_MAX 2048int main(int argc, char *argv[]){int SOCKET_SRC;char buf[BUFFER_MAX];int n_rd;if( (SOCKET_SRC = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0 ){fprintf(stderr, "create socket error.\n");exit(0);}while(1){n_rd = recvfrom(SOCKET_SRC, buf, BUFFER_MAX, 0, NULL, NULL);if (n_rd<46) {perror("recvfrom():");printf("Incomplete packet (errno is %d)\n", errno);close(SOCKET_SRC);exit(0);}/* An Ethernet frame was written to buf, frame analysis can be processed here *//* Termination control */}close(SOCKET_SRC);return 0; }


2. 數(shù)據(jù)包(以太網(wǎng)幀)分析

一個以太網(wǎng)幀(RFC894)的數(shù)據(jù)格式例如以下圖所看到的。

以太網(wǎng)幀(RFC894)格式


程序通過運行一次

n_rd = recvfrom(SOCKET_SRC, buf, BUFFER_MAX, 0, NULL, NULL);

就將上面一條以太網(wǎng)幀寫入buf中。


(1) 為了從buf中提取以太網(wǎng)報文頭,我們能夠定義例如以下結(jié)構(gòu)體。

typedef struct mac_frm_hdr {char dest_addr[6]; //destination MAC address shall be defined first.char src_addr[6];short type;}__attribute__((packed)) MAC_FRM_HDR;

定義該結(jié)構(gòu)體時,須要注意下面幾點。

a.屬性需按幀格式的出現(xiàn)順序定義

b.數(shù)據(jù)類型長度必須和幀中對應(yīng)區(qū)域的長度同樣。

c. 使用__attribute__((packed))取消編譯器自己主動優(yōu)化對齊結(jié)構(gòu)體,也是為了保證屬性長度和幀中對應(yīng)區(qū)域的長度同樣。

(2)為了提取IP報文頭。依據(jù)IP報文頭的格式。我們可定義例如以下結(jié)構(gòu)體。

typedef struct ip_hdr{ //header of IPV4#ifdef __LITTLE_ENDIAN_BIFIELDu_char ip_len:4, ip_ver:4;#elseu_char ip_ver:4, ip_len:4;#endifu_char ip_tos;u_short ip_total_len;u_short ip_id;u_short ip_flags;u_char ip_ttl;u_char ip_protocol;u_short ip_chksum;u_int32 ip_src;u_int32 ip_dest; }__attribute__((packed)) IP_HDR;

為保證各屬性長度與IP報文頭中一致,我們應(yīng)該在定義該結(jié)構(gòu)體前作例如以下聲明。

typedef int int32; typedef unsigned int u_int32; typedef unsigned char u_char; typedef unsigned short u_short;

注意事項參考定義以太網(wǎng)幀結(jié)構(gòu)體。

(3)為了提取UDP/TCP報文頭,可依據(jù)UDP/TCP報文頭格式。定義對應(yīng)結(jié)構(gòu)體,這里不作贅述。


以下是對以太網(wǎng)幀進行解析的詳細代碼。


MAC_FRM_HDR *mac_hdr; //define a Ethernet frame header IP_HDR *ip_hdr; //define a IP header char *tmp1, *tmp2; int AND_LOGIC = 0xFF;mac_hdr = buf; //buf is what we got from the socket program ip_hdr = buf + sizeof(MAC_FRM_HDR); //udp_hdr = buf + sizeof(MAC_FRM_HDR) + sizeof(IP_HDR); //if we want to analyses the UDP/TCPtmp1 = mac_hdr->src_addr; tmp2 = mac_hdr->dest_addr; /* print the MAC addresses of source and receiving host */ printf("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X==>" "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",tmp1[0]&AND_LOGIC, tmp1[1]&AND_LOGIC, tmp1[2]&AND_LOGIC,tmp1[3]&AND_LOGIC,tmp1[4]&AND_LOGIC, tmp1[5]&AND_LOGIC,tmp2[0]&AND_LOGIC, tmp2[1]&AND_LOGIC, tmp2[2]&AND_LOGIC,tmp2[3]&AND_LOGIC,tmp2[4]&AND_LOGIC, tmp2[5]&AND_LOGIC);tmp1 = (char*)&ip_hdr->ip_src; tmp2 = (char*)&ip_hdr->ip_dest; /* print the IP addresses of source and receiving host */ printf("IP: %d.%d.%d.%d => %d.%d.%d.%d",tmp1[0]&AND_LOGIC, tmp1[1]&AND_LOGIC, tmp1[2]&AND_LOGIC,tmp1[3]&AND_LOGIC,tmp2[0]&AND_LOGIC, tmp2[1]&AND_LOGIC, tmp2[2]&AND_LOGIC,tmp2[3]&AND_LOGIC); /* print the IP protocol which was used by the socket communication */ switch(ip_hdr->ip_protocol) {case IPPROTO_ICMP: LOGI("ICMP"); break;case IPPROTO_IGMP: LOGI("IGMP"); break;case IPPROTO_IPIP: LOGI("IPIP"); break;case IPPROTO_TCP:case IPPROTO_UDP:LOGI("Protocol: %s", ip_hdr->ip_protocol == IPPROTO_TCP ? "TCP" : "UDP");LOGI("Source port: %u, destination port: %u", udp_hdr->s_port, udp_hdr->d_port);break;case IPPROTO_RAW: LOGI("RAW"); break;default: printf("Unknown, please query in inclued/linux/in.h\n"); break; }

/*************************************************************************
????> Author: kleguan
??? >? 如用不當(dāng)之處,歡迎指正

??? >? 轉(zhuǎn)載請注明出處
?? ************************************************************************/



版權(quán)聲明:本文博客原創(chuàng)文章。博客,未經(jīng)同意,不得轉(zhuǎn)載。

總結(jié)

以上是生活随笔為你收集整理的基于Linux C的socketEthereal程序和Package分析 (一个)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。