當前位置:編程學習大全網 - 源碼下載 - 以太網數據幀的監聽與分析

以太網數據幀的監聽與分析

程序源代碼如下:

程序1 利用WinPcap函數庫函數解析捕獲數據包的以太幀頭

程序名:AnalyzeETH_WinPcap.CPP

程序名:AnalyzeETH_WinPcap.CPP

程序2 利用WinPcap函數庫函數解析捕獲的IPv4數據報包頭

程序名:AnalyzeIPv4_WinPcap.CPP

程序名:AnalyzeIPv4_WinPcap.CPP

程序3 利用WinPcap函數庫函數解析捕獲的IPv6數據報包頭

程序名:AnalyzeIPv6_WinPcap.CPP

程序名:AnalyzeIPv4_WinPcap.CPP

程序4 利用WinPcap函數庫函數解析捕獲的TCP數據報包頭

程序名:AnalyzeTCP_WinPcap.CPP

程序名:AnalyzeTCP_WinPcap.CPP

程序5 利用WinPcap函數庫函數解析捕獲的UDP數據報包頭

程序名:AnalyzeUDP_WinPcap.CPP

程序名:AnalyzeUDP_WinPcap.CPP

程序6 利用WinPcap函數庫函數發送TCP SYN幀數據報,進行SYN洪水攻擊

註意:本程序僅供學習參考,請不要在Internet網絡上使用!

程序名:AnalyzeUDP_WinPcap.CPP

程序名:AnalyzeUDP_WinPcap.CPP

程序7 利用原始套接字捕獲並解析IPv4數據包

程序名:AnalyzeIPv4_WINSOCK.CPP

程序名:AnalyzeIPv4_WINSOCK.CPP

程序8 利用原始套接字捕獲並解析雙協議棧下IPv6數據包

程序名:AnalyzeIPv6_WINSOCK.CPP

程序名:AnalyzeIPv6_WINSOCK.CPP

程序9 利用原始套接字捕獲並解析TCP數據包

程序名:AnalyzeTCP_WINSOCK.CPP

程序名:AnalyzeTCP_WINSOCK.CPP

程序10 利用原始套接字捕獲並解析UDP數據包

程序名:AnalyzeUDP_WINSOCK.CPP

程序名:AnalyzeUDP_WINSOCK.CPP

程序11 利用原始套接字發送TCP SYN幀,對目標主機進行SYN洪水攻擊

程序名:SYNFlood_WINSOCK.CPP

註意:本程序僅供學習參考,請不要在Internet網絡上使用!

程序名:SYNFlood_WINSOCK.CPP

程序12 采集局域網內若幹臺主機網絡數據並分析網絡流量的綜合應用程序

可執行程序:LANSecrutiny.exe

程序運行情況:

程序主要源代碼:LANScrutinyDlg.cpp

完整程序全部源代碼:LANSecrutiny.rar

編說明如下:

1.結構體說明

在程序中,我們將要進行分析的各數據包頭格式用結構體進行定義。這樣便於對數據

包的解析,使每個字段清楚易懂。

以太幀頭格式結構體,***14個字節:

typedef struct ether_header {

unsigned char ether_dhost[6]; //目的MAC地址

unsigned char ether_shost[6]; //源MAC地址

unsigned short ether_type; //協議類型

}ETHHEADER,*PETHHEADER;

IPv4報頭格式結構體,***20個字節:

typedef struct ipv4_header {

unsigned char ver_ihl; //版本 (4 bits) + 首部長度 (4 bits)

unsigned char tos; //服務類型

unsigned short tlen; //數據報總長度

unsigned short identification; //標識

unsigned short flags_fo; //標誌 (3 bits) + 片偏移 (13 bits)

unsigned char ttl; //生存時間

unsigned char proto; //協議

unsigned short crc; //首部校驗和

u_char ip_src[4]; //源IP地址

u_char ip_dst[4]; //目的IP地址

}IPHEADER,*PIPHEADER;

IPv6報頭格式結構體,***40個字節:

typedef struct ipv6_header {

u_char ver_tf; //版本號(4 bit)

u_char traffic; //優先級(8 bit)

u_short label; //流標識(20 bit)

u_char length[2]; //報文長度(16 bit)

u_char next_header; //下壹頭部(8 bit)

u_char limits; //跳數限制(8 bit)

u_char Srcv6[16]; //源IPv6地址(128 bit)

u_char Destv6[16]; //目的IPv6地址(128 bit)

}IPv6_HEADER,*PIPv6_HEADER;

TCP報頭格式結構體,***20個字節:

typedef struct tcp_header {

WORD SourPort; //源端口號

WORD DestPort; //目的端口號

DWORD SeqNo; //序號

DWORD AckNo; //確認序號

BYTE HLen; //首部長度(保留位)

BYTE Flag; //標識(保留位)

WORD Window; //窗口大小

WORD ChkSum; //校驗和

WORD UrgPtr; //緊急指針

}TCPHEADER,*PTCPHEADER;

UDP報頭格式結構體,***8個字節:

typedef struct udp_header {

u_short sport; //源端口號

u_short dport; //目的端口號

u_short len; //數據報長度

u_short crc; //校驗和

}UDPHEADER,*PUDPHEADER;

2.程序說明

程序1 利用WinPcap函數庫函數解析捕獲數據包的以太幀頭

程序名:AnalyzeETH_WinPcap.htm

該程序通過利用WinPcap提供的捕獲數據包函數,對網絡中的數據包進行采集分析。

WinPcap中提供的函數pcap_open_live()可以獲取網絡適配器,通過函數pcap_loop(pcap_t*

p,int cnt,pcap_handle dispatch_handle,u_char* user)直接深入到數據鏈路層進行網絡數據的捕

獲,將捕獲的數據傳到函數dispatch_handle(u_char *,const pcap_pkthdr *header,const u_char

*pkt_data)中,該函數的參數pkt_data指向的即是捕獲的數據包。這樣,我們可以捕獲局域

網內數據鏈路層的以太幀,並按照以太幀頭格式對數據包進行解析,以獲得以太幀頭中的有

關信息。同時將捕獲數據存入磁盤中。通過該程序,可以分析出局域網內傳輸的各類網絡層

數據包的情況。程序完整代碼詳見程序1(AnalyzeETH_WinPcap.CPP)。

程序2 利用WinPcap函數庫函數解析捕獲的IPv4數據報包頭

程序名:AnalyzeIPv4_WinPcap.CPP

該程序同樣通過WinPcap提供的函數,獲取網絡適配器,利用函數pcap_loop(pcap_t*

p,int cnt,pcap_handle dispatch_handle,u_char* user)捕獲數據包。並將捕獲的數據傳到函數

dispatch_handle(u_char *,const pcap_pkthdr *header,const u_char *pkt_data)中,在該函數中

對以太幀包進行過濾,將以太幀頭中協議類型字段(ether_type)中值為0x0800的數據包進

行解析,即可得到整個IPv4分組的信息,其中從IPv4數據報頭開始的前20個字節為IPv4

包頭信息字段。同時將解析出的相關數據字段存入磁盤中。通過該程序,可以分析局域網內

各主機的網絡使用情況。程序完整代碼詳見程序2(AnalyzeIPv4_WinPcap.CPP)。

程序3 利用WinPcap函數庫函數解析捕獲的IPv6數據報包頭

程序名:AnalyzeIPv6_WinPcap.CPP

由於WinPcap提供的函數可以深入到數據鏈路層去捕獲數據包,因此無論是IPv4數據

包還是IPv6數據包都是被封裝在以太幀頭中,因此都能夠被捕獲。本程序利用WinPcap提

供的函數,實現了過濾捕獲並解析在純IPv6環境或雙協議棧環境下傳輸的IPv6數據包。捕

獲的數據包以太幀頭中協議類型(ether_type)字段值為0x86DD,則該數據包為純IPv6環

境下傳輸的IPv6數據包,將隨後的40個字節按照IPv6包頭格式解析,即可得到IPv6包頭

中攜帶的信息。對捕獲的數據包進行過濾,在過濾出的IPv4數據包中分析IPv4包頭,其中

proto字段值為0x29的數據包即為雙協議棧下IPv6數據包,於是將IPv4包頭後的40個字

節按照IPv6包頭格式解析,即可得到IPv6包頭中攜帶的信息。同樣,解析過程都在函數

dispatch_handle(u_char *,const pcap_pkthdr *header,const u_char *pkt_data)中進行。

if(eth_header->Etype[0]==0x86 && eth_header->Etype[1]==0xDD) {

//純IPv6環境下傳輸的IPv6數據包

}

else if(eth_header->Etype[0]==0x08 && eth_header->Etype[1]==0x00) {

if(ip_header->prote==0x29) {

//雙協議棧環境下傳輸的IPv6數據包

}

}

該程序還進壹步對IPv6中封裝的TCP、ICMPv6、UDP包頭進行了解析,其中TCP、

UDP包頭格式與IPv4版本中的相同。

通過該程序,可以捕獲不同網絡環境下封裝的IPv6數據包,並進行分析。完整代碼詳

見程序3(AnalyzeIPv6_WinPcap.CPP)。

程序4 利用WinPcap函數庫函數解析捕獲的TCP數據報包頭

程序名:AnalyzeTCP_WinPcap.CPP

該程序通過利用WinPcap提供的函數pcap_loop(pcap_t* p,int cnt,pcap_handle

dispatch_handle,u_char* user)將數據包捕獲。並在dispatch_handle(u_char *,const pcap_pkthdr

*header,const u_char *pkt_data)中通過編寫代碼實現解析。由於pkt_data中存放的是整個以

太幀,因此只要將指針跳到TCP包頭開始處,然後按照TCP包頭格式解析就可以讀出其中

信息。程序中在解析數據包的同時,將解析結果存放到磁盤文件中。該程序通過對TCP包

頭的解析,並進行分析,可以推斷網絡中是否存在某些網絡攻擊行為。完整代碼詳見程序4

(AnalyzeTCP_WinPcap.CPP)。

程序5 利用WinPcap函數庫函數解析捕獲的UDP數據報包頭

程序名:AnalyzeUDP_WinPcap.CPP

該程序與AnalyzeTCP.CPP程序基本壹樣,通過利用WinPcap提供的函數pcap_loop

(pcap_t* p,int cnt,pcap_handle dispatch_handle,u_char* user)將數據包捕獲,並在

dispatch_handle(u_char *,const pcap_pkthdr *header,const u_char *pkt_data)中通過編寫代碼

實現解析。只要將指針改為跳到UDP包頭開始處,然後按照UDP包頭格式解析就可以讀出

其中信息。程序中在解析數據包的同時,將解析結果存放到磁盤文件中。完整代碼詳見程序

5(AnalyzeUDP_WinPcap.CPP)。

程序6 利用WinPcap函數庫函數發送TCP SYN幀數據報,進行SYN洪水攻擊

程序名:SYNFlood_WinPcap.CPP

功能強大的WinPcap函數庫不但能夠捕獲網絡中的數據,還能利用它提供的函數,發

送自己構造數據鏈路層的數據報。因此,在本程序中,我們自己構造了壹個SYN幀TCP數

據報,並將其封裝到我們自己構造的IP報頭和以太幀頭中,其中IP報頭中的源IP地址(程

序中設為1.1.1.1)和以太幀頭中的源MAC地址(程序中設為

0x00,0x00,0x00,0x00,0x00,0x00)都是偽造的不存在的地址。將大量請求聯接的數據報源源

不斷地發送到目標主機,而對方無法把回應數據報傳回源主機,這樣就實現了對主機進行

SYN洪水攻擊了。程序中的關鍵在於,封裝在數據報中的校驗和必須正確,否則目標主機

不會做任何反映。因此,程序中實現了壹個計算校驗和的函數,用於計算IP報頭和TCP報

頭中的校驗和字段。校驗和函數代碼如下:

inline USHORT checksum(USHORT *buffer, int size) {

unsigned long cksum=0;

while(size >1) {

cksum+=*buffer++;

size -=sizeof(USHORT);

}

if(size )

cksum += *(UCHAR*)buffer;

cksum = (cksum >> 16) + (cksum & 0xffff);

cksum += (cksum >>16);

return (USHORT)(~cksum);

}

在計算IP校驗和時,buffer中存放的是IP報頭數據,而在計算TCP校驗和時,buffer

中存放的是TCP偽頭部和TCP頭部數據。

將構造好的數據報通過函數pcap_sendqueue_queue(pcap_send_queue *squeue,struct

pcap_pkthdr *pktheader,u_char *pktdata)放到發送隊列中,再利用函數

pcap_sendqueue_transmit(pcap_t *outdesc, pcap_send_queue *squeue,int sync)向目標主機發送。

即可實現SYN Flood攻擊。完整代碼詳見程序6(SYNFlood_WinPcap.CPP)。

程序7 利用原始套接字捕獲並解析IPv4數據包

程序名:AnalyzeIPv4_WINSOCK.CPP

該程序通過使用原始套接字過濾並捕獲IPv4數據包,並對捕獲數據包進行解析。程序

分為三部分,其中在函數InitWinsock2()內初始化Winsock2。在函數BindSocket()內,

利用winsock2提供的函數WSASocket()建立套接字,由於只有原始套接字可以深入到網

絡層捕獲數據包,因此WSASocket(int af,int type,int protocol,LPWSAPROTOCOL_INFO

lpPorotocolInfo,GROUP g,DWORD dwFlags)中參數type要設為SOCK_RAW。因為是捕獲

IP數據包,參數protocol設為IPPROTO_IP。然後將套接字進行綁定。這樣就可以對網絡進

行監聽,捕獲網絡中的IPv4數據包了。在函數RecieveIPv4()函數中,對捕獲的數據進行

解析。完整代碼詳見程序AnalyzeIPv4_WINSOCK.CPP。

程序8 利用原始套接字捕獲並解析雙協議棧下IPv6數據包

程序名:AnalyzeIPv6_WINSOCK.CPP

該程序通過使用原始套接字過濾並捕獲雙協議棧下IPv6數據包,並對捕獲數據包進行

解析。與程序AnalyzeIPv4_WINSOCK.CPP壹樣,本程序分為四部分,分別完成初始化套接

字,建立並綁定套接字,捕獲數據包並分析。因為IPv6數據包封裝在IPv4包頭中,因此套

接字按IPv4套接字的建立,即WSASocket(int af,int type,int

protocol,LPWSAPROTOCOL_INFO lpPorotocolInfo,GROUP g,DWORD dwFlags)中參數af

設為AF_INET,參數type要設為SOCK_RAW。因為是捕獲IP數據包,參數protocol設為

IPPROTO_IP。完整代碼詳見程序AnalyzeIPv6_WINSOCK.CPP。

程序9 利用原始套接字捕獲並解析TCP數據包

程序名:AnalyzeTCP_WINSOCK.CPP

該程序通過使用原始套接字過濾並捕獲TCP數據包,並對捕獲數據包進行解析。與程

序AnalyzeIPv4_WINSOCK.CPP壹樣,對套接字進行初始化、建立並綁定後,在RecieveTCP

()函數中獲取TCP數據包字段,按照TCP包頭格式解析,可獲取完整的TCP數據包數據。

完整代碼詳見程序AnalyzeTCP_WINSOCK.CPP。

程序10 利用原始套接字捕獲並解析UDP數據包

程序名:AnalyzeUDP_WINSOCK.CPP

該程序通過使用原始套接字過濾並捕獲UDP數據包,並對捕獲數據包進行解析。與程

序AnalyzeTCP_WINSOCK.CPP壹樣,對套接字進行初始化、建立並綁定後,在RecieveTCP

()函數中獲取TCP數據包字段,按照TCP包頭格式解析,可獲取完整的TCP數據包數據。

完整代碼詳見程序AnalyzeUDP_WINSOCK.CPP。

程序11 利用原始套接字發送TCP SYN幀,對目標主機進行SYN洪水攻擊

程序名:SYNFlood_WINSOCK.CPP

本程序利用原始套接字發送TCP數據包,對目標主機進行SYN Flood攻擊。程序中函

數socket(AF_INET,SOCK_RAW,IPPROTO_IP);將套接字設為原始套接字。並通過函數

setsockopt(SOCKET s,int level,int optname,const char*optval,int optlen);設置頭包含選項,其中

IP_HDRINCL是IPPROTO_IP選項級別,若將IP_HDRINCL選項設為TRUE,發送函數會

將IPv4頭包含在自己發送的數據前面,因此,在調用壹個Winsock發送函數時,必須在數

據前面包含完整的IPv4頭。與WinPcap不同的是,原始套接字只能深入到網絡層,故只需

構造IPv4包頭和TCP包頭。將構造好的、計算出正確校驗和的數據包放入緩沖區,通過sendto

(SOCKET s,const char *buf,int len,int flags,const struct sockaddr *to,int tolen)向目標主機發

送,即達到攻擊目的。

程序12 采集局域網內若幹臺主機網絡數據並分析網絡流量的綜合應用程序

程序名:LANSecrutiny

本程序分為幾個模塊:探測局域網內運行主機;後臺采用動態鏈表存放采集到所需的

網絡數據;圖示局域網及每臺主機的網絡流量隨時間的折線變化;監聽結束後多線程進行數

據存盤。

探測局域網內運行主機

要對局域網內主機進行監聽,采集其網絡數據,首先必須知道局域網內正在運行的主

機。為迅速獲得主機是否處於運行狀態的消息,只要向局域網內所有主機發送ARP數據包,

並根據回應的數據報分析,即可得到答案。因為壹局域網的網關和子網掩碼是已知的,因此,

我們可以計算出這壹局域網的IP地址範圍。在本程序中,我們利用WinPcap提供的發送數

據報函數pcap_sendpacket(pcap_t *adhandle,unsigned char*sendbuf,int size),向所有主機分別

發送自己構造的請求ARP數據報,捕獲回應的ARP數據報並解析,即可獲知網內運行主機

的MAC地址及IP地址。詳細代碼見程序13中LANSecrutinyDlg.CPP文件內SendARPtoGetIP

()函數。

利用此方法,可使該程序在不同網段使用,增強了程序的靈活性。

采用動態鏈表存放采集到的網絡數據

為使程序具有良好的伸縮性,能根據網絡數據采集情況動態的分配內存,不致造成內

存浪費或內存空間過小的情況發生。在本程序中,我們將采集的所需數據存放到鏈表中。在

函數dispatch_handle(u_char *,const pcap_pkthdr *header,const u_char *pkt_data)中,我們按

照前述幾個程序中對數據報解析的方法,將捕獲數據報個報頭中的所需數據提取出來,並存

入壹個鏈表節點中。然後將該存放完數據的節點插入到鏈表的結尾處。

本程序設計為可以將IPv4數據報數據和IPv6數據報數據存放如同壹鏈表中,而IPv4

地址為32位,IPv6地址為128位。因此我們將節點中存放IP地址的元素設置為壹個有17

個元素的數組,將數組的第壹個元素IPaddr[0]作為判斷值。如果是IPv4數據報,則IPaddr[0]

的值為0,並將IPv4地址放入隨後的4個元素中,如果是IPv6數據報,則IPaddr[0]的值為

1,並將IPv6地址放入隨後的16個元素中。

由於ICANN為0~1023端口各命名了壹個端口名。因此,我們在程序中,通過函數

getportname()為有端口名的端口查找其端口名,這樣便進壹步了解數據包的高層協議類型。

void getportname(int portn,char portch[],char *protocol) {

if(getservbyport(htons(portn),protocol)!=NULL) {

strcpy(portch,getservbyport(htons(portn),protocol)->s_name);

}

else

sprintf(portch,"%d",portn);

}

在該函數中,我們將捕獲的端口號值portn和協議類型protocol傳入,通過Winsock2提供的

函數getservbyport()將找到的端口名傳回給節點元素portch。

通過該程序將捕獲的數據報中重要數據存放入鏈表中,我們可以清楚的了解被監聽主

機與外界交流的時間、類型以及對放地址等情況。完整代碼詳見程序LANSecrutiny中

dispatcher_handler()函數。

采用多線程技術進行數據存盤

由於程序中我們設計成為每臺被監聽主機產生兩根鏈表存放進、出數據,因此對n臺

主機進行監聽時,會產生2*n條鏈表。為解決多條鏈表存盤問題,我們采用多線程技術,這

樣能使各條鏈表的存盤工作不相互影響,避免了由於壹條鏈表在存盤過程中出現錯誤而使其

後其它鏈表無法再進行存盤,從而造成采集數據的丟失。存盤時,我們將鏈表中壹個節點拷

貝到臨時節點中,再進行保存,這樣避免了存盤時由於某些原因造成對鏈表的破壞而影響存

盤工作。詳細代碼見程序LANSecrutiny中SavePacket()函數。

圖示網絡流量

通過圖示的方法,能使我們更快的了解網絡流量狀況。因此在程序中我們設計了對整

個局域網機每臺主機的網絡流量圖示。

在程序中,為將流量用折線方式繪制出來,我們設計了壹個數組,用於存放流量值,

其中,第壹個元素存放當前時間流量值,第二個元素存放前壹秒流量值,以此類推,第n

個元素存放n秒前流量。這樣,在繪圖時就能將不同時間的流量用折線連接起來。

在函數OnTimer()中加入以下代碼:

if(postion[0]>=360) postion[0]=358;

for(i=125;i>0;i--) postion[i]=postion[i-1];

在函數OnPaint()中加入以下代碼:

for(i=0;i<125;i++) {

MoveToEx(hdc,15+i*5,385-postion[i],NULL);

LineTo(hdc,15+(i+1)*5,385-postion[i+1]); }

完整代碼詳見程序LANSecrutiny中AnalyzeDlg.CPP內各函數。

以上程序還有很多不足之處,懇請指正。謝謝!

  • 上一篇:股票中BBL是什麽意思
  • 下一篇:龍珠大冒險格鬥技巧
  • copyright 2024編程學習大全網