詞語(yǔ)解釋
嗅探 sniff。嗅探器可以竊聽(tīng)網(wǎng)絡(luò)上流經(jīng)的數(shù)據(jù)包。
用集線器hub組建的網(wǎng)絡(luò)是基于共享的原理的,
局域網(wǎng)內(nèi)所有的計(jì)算機(jī)都接收相同的數(shù)據(jù)包,
而網(wǎng)卡構(gòu)造了硬件的“過(guò)濾器“
通過(guò)識(shí)別MAC地址過(guò)濾掉和自己無(wú)關(guān)的信息,
嗅探程序只需關(guān)閉這個(gè)過(guò)濾器,
將網(wǎng)卡設(shè)置為“混雜模式“就可以進(jìn)行嗅探
用交換機(jī)switch組建的網(wǎng)絡(luò)是基于“交換“原理的
,交換機(jī)不是把數(shù)據(jù)包發(fā)到所有的端口上,
而是發(fā)到目的網(wǎng)卡所在的端口。
這樣嗅探起來(lái)會(huì)麻煩一些,嗅探程序一般利用“ARP欺騙“的方法
,通過(guò)改變MAC地址等手段,欺騙交換機(jī)將數(shù)據(jù)包發(fā)給自己,
嗅探分析完畢再轉(zhuǎn)發(fā)出去
一 前言
SNIFF真是一個(gè)古老的話題,關(guān)于在網(wǎng)絡(luò)上采用SNIFF來(lái)獲取敏感信息已經(jīng)不是什么新鮮事,也不乏很多成功的案例,那么,SNIFF究竟是什么呢?SNIFF就是嗅探器,就是竊聽(tīng)器,SNIFF靜悄悄的工作在網(wǎng)絡(luò)的底層,把你的秘密全部記錄下來(lái)?催^(guò)威爾史密斯演的《全民公敵》嗎?SNIFF就象里面精巧的竊聽(tīng)器一樣,讓你防不勝防。
SNIFF可以是軟件,也可以是硬件,既然是軟件那就要分平臺(tái),有WINDOWS下的、UNXI下的等,硬件的SNIFF稱為網(wǎng)絡(luò)分析儀,反正不管硬件軟件,目標(biāo)只有一個(gè),就是獲取在網(wǎng)絡(luò)上傳輸?shù)母鞣N信息。本文僅僅介紹軟件的SNIFF。
當(dāng)你舒適的坐在家里,愜意的享受網(wǎng)絡(luò)給你帶來(lái)的便利,收取你的EMAIL,購(gòu)買你喜歡的物品的時(shí)候,你是否會(huì)想到你的朋友給你的信件,你的信用卡帳號(hào)變成了一個(gè)又一個(gè)的信息包在網(wǎng)絡(luò)上不停的傳送著,你是否曾經(jīng)這些信息包會(huì)通過(guò)網(wǎng)絡(luò)流入別人的機(jī)器呢?你的擔(dān)憂不是沒(méi)有道理的,因?yàn)镾NIFF可以讓你的擔(dān)憂變成實(shí)實(shí)在在的危險(xiǎn)。就好像一個(gè)人躲在你身后偷看一樣。。。。。。
二 網(wǎng)絡(luò)基礎(chǔ)知識(shí)
“網(wǎng)絡(luò)基礎(chǔ)知識(shí)”,是不是聽(tīng)起來(lái)有點(diǎn)跑題了?雖然聽(tīng)起來(lái)這和我們要談的SNIFF沒(méi)什么關(guān)系,可是還是要說(shuō)一說(shuō)的,萬(wàn)丈高樓平地起,如果連地基都沒(méi)打好,怎么蓋樓?!如果你對(duì)網(wǎng)絡(luò)還不是十分清楚的話,最好能靜下心來(lái)好好看看,要知道,這是基礎(chǔ)的基礎(chǔ),在這里我只是簡(jiǎn)單的說(shuō)一下,免得到時(shí)候有人迷糊,詳細(xì)的最好能夠自己去找書看看。
(1)TCP/IP體系結(jié)構(gòu)
開(kāi)放系統(tǒng)互連(OSI)模型將網(wǎng)絡(luò)劃分為七層模型,分別用以在各層上實(shí)現(xiàn)不同的功能,這七層分別為:應(yīng)用層、表示層、會(huì)話層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層及物理層。而TCP/IP體系也同樣遵循這七層標(biāo)準(zhǔn),只不過(guò)在某些OSI功能上進(jìn)行了壓縮,將表示層及會(huì)話層合并入應(yīng)用層中,所以實(shí)際上我們打交道的TCP/IP僅僅有5層而已,網(wǎng)絡(luò)上的分層結(jié)構(gòu)決定了在各層上的協(xié)議分布及功能實(shí)現(xiàn),從而決定了各層上網(wǎng)絡(luò)設(shè)備的使用。實(shí)際上很多成功的系統(tǒng)都是基于OSI模型的,如:如幀中繼、ATM、ISDN等。
TCP/IP的網(wǎng)絡(luò)體系結(jié)構(gòu)(部分)
從上面的圖中我們可以看出,第一層物理層和第二層數(shù)據(jù)鏈路層是TCP/IP的基礎(chǔ),而TCP/IP本身并不十分關(guān)心低層,因?yàn)樘幵跀?shù)據(jù)鏈路層的網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序?qū)⑸蠈拥膮f(xié)議和實(shí)際的物理接口隔離開(kāi)來(lái)。網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序位于介質(zhì)訪問(wèn)子層(MAC)。2)網(wǎng)絡(luò)上的設(shè)備 中繼器:中繼器的主要功能是終結(jié)一個(gè)網(wǎng)段的信號(hào)并在另一個(gè)網(wǎng)段再生該信號(hào),一句話,就是簡(jiǎn)單的放大而已,工作在物理層上!
網(wǎng) 橋:網(wǎng)橋使用MAC物理地址實(shí)現(xiàn)中繼功能,可以用來(lái)分隔網(wǎng)段或連接部分異種網(wǎng)絡(luò),工作在數(shù)據(jù)鏈路層。
路由器:路由器使用網(wǎng)絡(luò)層地址(IP,X.121,E.164等),主要負(fù)責(zé)數(shù)據(jù)包的路由尋徑,也能處理物理層和數(shù)據(jù)鏈路層上的工作。
網(wǎng) 關(guān):主要工作在網(wǎng)絡(luò)第四層以上,主要實(shí)現(xiàn)收斂功能及協(xié)議轉(zhuǎn)換,不過(guò)很多時(shí)候網(wǎng)關(guān)都被用來(lái)描述任何網(wǎng)絡(luò)互連設(shè)備。
。3)TCP/IP與以太網(wǎng)
以太網(wǎng)和TCP/IP可以說(shuō)是相互相成的,可以說(shuō)兩者的關(guān)系幾乎是密不可分,以太網(wǎng)在一二層提供物理上的連線,而TCP/IP工作在上層,使用32位的IP地址,以太網(wǎng)則使用48位的MAC地址,兩者間使用ARP和RARP協(xié)議進(jìn)行相互轉(zhuǎn)換。從我們上面TCP/IP的模型圖中可以清楚的看到兩者的關(guān)系。
載波監(jiān)聽(tīng)/沖突檢測(cè)(CSMA/CD)技術(shù)被普遍的使用在以太網(wǎng)中,所謂載波監(jiān)聽(tīng)是指在以太網(wǎng)中的每個(gè)站點(diǎn)都具有同等的權(quán)利,在傳輸自己的數(shù)據(jù)時(shí),首先監(jiān)聽(tīng)信道是否空閑,如果空閑,就傳輸自己的數(shù)據(jù),如果信道被占用,就等待信道空閑。而沖突檢測(cè)則是為了防止發(fā)生兩個(gè)站點(diǎn)同時(shí)監(jiān)測(cè)到網(wǎng)絡(luò)沒(méi)有被使用時(shí)而產(chǎn)生沖突。以太網(wǎng)采用廣播機(jī)制,所有與網(wǎng)絡(luò)連接的工作站都可以看到網(wǎng)絡(luò)上傳遞的數(shù)據(jù)。
為了加深你的理解,我們來(lái)看看下面的圖,一個(gè)典型的在以太網(wǎng)中客戶與服務(wù)器使用TCP/IP協(xié)議的通信
以太網(wǎng)
唆唆了這么多,有人煩了吧?相信我,這是基礎(chǔ)的基礎(chǔ),可以說(shuō)是說(shuō)得是很簡(jiǎn)單拉,如果需要,拿出個(gè)幾十萬(wàn)字來(lái)說(shuō)上面的內(nèi)容,我想也不嫌多,好了,讓我們進(jìn)入下一節(jié),sniff的原理。
三 SNIFF的原理
要知道在以太網(wǎng)中,所有的通訊都是廣播的,也就是說(shuō)通常在同一個(gè)網(wǎng)段的所有網(wǎng)絡(luò)接口都可以訪問(wèn)在物理媒體上傳輸?shù)乃袛?shù)據(jù),而每一個(gè)網(wǎng)絡(luò)接口都有一個(gè)唯一的硬件地址,這個(gè)硬件地址也就是網(wǎng)卡的MAC地址,大多數(shù)系統(tǒng)使用48比特的地址,這個(gè)地址用來(lái)表示網(wǎng)絡(luò)中的每一個(gè)設(shè)備,一般來(lái)說(shuō)每一塊網(wǎng)卡上的MFC地址都是不同的,每個(gè)網(wǎng)卡廠家得到一段地址,然后用這段地址分配給其生產(chǎn)的每個(gè)網(wǎng)卡一個(gè)地址。在硬件地址和IP地址間使用ARP和RARP協(xié)議進(jìn)行相互轉(zhuǎn)換。
在正常的情況下,一個(gè)網(wǎng)絡(luò)接口應(yīng)該只響應(yīng)這樣的兩種數(shù)據(jù)幀:
1.與自己硬件地址相匹配的數(shù)據(jù)幀。 2.發(fā)向所有機(jī)器的廣播數(shù)據(jù)幀。
在一個(gè)實(shí)際的系統(tǒng)中,數(shù)據(jù)的收發(fā)是由網(wǎng)卡來(lái)完成的,網(wǎng)卡接收到傳輸來(lái)的數(shù)據(jù),網(wǎng)卡內(nèi)的單片程序接收數(shù)據(jù)幀的目的MAC地址,根據(jù)計(jì)算機(jī)上的網(wǎng)卡驅(qū)動(dòng)程序設(shè)置的接收模式判斷該不該接收,認(rèn)為該接收就接收后產(chǎn)生中斷信號(hào)通知CPU,認(rèn)為不該接收就丟掉不管,所以不該接收的數(shù)據(jù)網(wǎng)卡就截?cái)嗔耍?jì)算機(jī)根本就不知道。CPU得到中斷信號(hào)產(chǎn)生中斷,操作系統(tǒng)就根據(jù)網(wǎng)卡的驅(qū)動(dòng)程序設(shè)置的網(wǎng)卡中斷程序地址調(diào)用驅(qū)動(dòng)程序接收數(shù)據(jù),驅(qū)動(dòng)程序接收數(shù)據(jù)后放入信號(hào)堆棧讓操作系統(tǒng)處理。而對(duì)于網(wǎng)卡來(lái)說(shuō)一般有四種接收模式:
廣播方式:該模式下的網(wǎng)卡能夠接收網(wǎng)絡(luò)中的廣播信息!〗M播方式:設(shè)置在該模式下的網(wǎng)卡能夠接收組播數(shù)據(jù)。
直接方式:在這種模式下,只有目的網(wǎng)卡才能接收該數(shù)據(jù);祀s模式:在這種模式下的網(wǎng)卡能夠接收一切通過(guò)它的數(shù)據(jù),而不管該數(shù)據(jù)是否是傳給它的。
好了,現(xiàn)在我們總結(jié)一下,首先,我們知道了在以太網(wǎng)中是基于廣播方式傳送數(shù)據(jù)的,也就是說(shuō),所有的物理信號(hào)都要經(jīng)過(guò)我的機(jī)器,再次,網(wǎng)卡可以置于一種模式叫混雜模式(promiscuous),在這種模式下工作的網(wǎng)卡能夠接收到一切通過(guò)它的數(shù)據(jù),而不管實(shí)際上數(shù)據(jù)的目的地址是不是他。這實(shí)際上就是我們SNIFF工作的基本原理:讓網(wǎng)卡接收一切他所能接收的數(shù)據(jù)。
我們來(lái)看一個(gè)簡(jiǎn)單的例子,如圖一所示,機(jī)器A、B、C與集線器HUB相連接,集線器HUB通過(guò)路由器Router訪問(wèn)外部網(wǎng)絡(luò)。這是一個(gè)很簡(jiǎn)單也很常見(jiàn)的情況,比如說(shuō)在公司大樓里,我所在的網(wǎng)絡(luò)部辦公室里的幾臺(tái)機(jī)器通過(guò)集線器連接,而網(wǎng)絡(luò)部、開(kāi)發(fā)部、市場(chǎng)部也是同樣如此,幾個(gè)部門的集線器通過(guò)路由器連接。還是回到我們的圖一上來(lái),值得注意的一點(diǎn)是機(jī)器A、B、C使用一個(gè)普通的HUB連接的,不是用SWITCH,也不是用ROUTER,使用SWITCH和ROUTER的情況要比這復(fù)雜得多。
我們假設(shè)一下機(jī)器A上的管理員為了維護(hù)機(jī)器C,使用了一個(gè)FTP命令向機(jī)器C進(jìn)行遠(yuǎn)程登陸,那么在這個(gè)用HUB連接的網(wǎng)絡(luò)里數(shù)據(jù)走向過(guò)程是這樣的。首先機(jī)器A上的管理員輸入的登陸機(jī)器C的FTP口令經(jīng)過(guò)應(yīng)用層FTP協(xié)議、傳輸層TCP協(xié)議、網(wǎng)絡(luò)層IP協(xié)議、數(shù)據(jù)鏈路層上的以太網(wǎng)驅(qū)動(dòng)程序一層一層的包裹,最后送到了物理層,我們的網(wǎng)線上。接下來(lái)數(shù)據(jù)幀送到了HUB上,現(xiàn)在由HUB向每一個(gè)接點(diǎn)廣播由機(jī)器A發(fā)出的數(shù)據(jù)幀,機(jī)器B接收到由HUB廣播發(fā)出的數(shù)據(jù)幀,并檢查在數(shù)據(jù)幀中的地址是否和自己的地址相匹配,發(fā)現(xiàn)不是發(fā)向自己的后把這數(shù)據(jù)幀丟棄,不予理睬。而機(jī)器C也接收到了數(shù)據(jù)幀,并在比較之后發(fā)現(xiàn)是發(fā)現(xiàn)自己的,接下來(lái)他就對(duì)這數(shù)據(jù)幀進(jìn)行分析處理。
在上面這個(gè)簡(jiǎn)單的例子中,機(jī)器B上的管理員如果很好奇,他很想知道究竟登陸機(jī)器C上FTP口令是什么?那么他要做的很簡(jiǎn)單,僅僅需要把自己機(jī)器上的網(wǎng)卡置于混雜模式,并對(duì)接收到的數(shù)據(jù)幀進(jìn)行分析,從而找到包含在數(shù)據(jù)幀中的口令信息。
四 做一個(gè)自己的sniff
在上一節(jié)里,我們已經(jīng)知道了SNIFF的基本原理是怎么一回事,這一節(jié)我們來(lái)親自動(dòng)手做一個(gè)自己的sniff,畢竟,用程序代碼來(lái)說(shuō)話比什么都要來(lái)得真實(shí),也容易加深理解。
回頭想一想我們上面說(shuō)的原理,我們要做的事情有幾件:
1. 把網(wǎng)卡置于混雜模式。 2. 捕獲數(shù)據(jù)包! 3.分析數(shù)據(jù)包。
注:下面的源代碼取至Chad Renfro的<< Basic Packet-SnifferConstruction from the Ground Up>>一文中
/************************Tcp_sniff_2.c********************/
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
8.#include
9.#include "headers.h"
#define INTERFACE "eth0"
/*Prototype area*/
10.int Open_Raw_Socket(void);
11.int Set_Promisc(char *interface, intsock);
12.int main() {
13.int sock, bytes_recieved, fromlen;
14.char buffer[65535];
15.struct sockaddr_in from;
16.struct ip *ip;
17.struct tcp *tcp;
18.sock = Open_Raw_Socket();
19. Set_Promisc(INTERFACE, sock);
20. while(1)
22. {
23. fromlen = sizeof from;
24. bytes_recieved = recvfrom(sock, buffer, sizeofbuffer, 0, (struct sockaddr *)&from, &fromlen);
25. printf("
Bytes received :::%5d
",bytes_recieved);
26. printf("Source address :::%s
",inet_ntoa(from.sin_addr));
27. ip = (struct ip *)buffer;
/*See if this is a TCP packet*/
28. if(ip->ip_protocol == 6) {
29. printf("IP header length :::%d
",ip->ip_length);
30. printf("Protocol :::%d
",ip->ip_protocol);
31. tcp = (struct tcp *)(buffer +(4*ip->ip_length));
32. printf("Source port :::%d
",ntohs(tcp->tcp_source_port));
33. printf("Dest port :::%d
",ntohs(tcp->tcp_dest_port));
34. }
35. }
36.}
37.int Open_Raw_Socket() {
38. int sock;
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0){
/*Then the socket was not created properly and must die*/
40. perror("The raw socket was not created");
41. exit(0);
42. };
43. return(sock);
44. }
45.int Set_Promisc(char *interface, int sock ) {
46. struct ifreq ifr;
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1);
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) {
/*Could not retrieve flags for the interface*/
49. perror("Could not retrive flags for the interface");
50. exit(0);
51. }
52. printf("The interface is ::: %s
", interface);
53. perror("Retrieved flags from interface successfully");
54. ifr.ifr_flags |= IFF_PROMISC;
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {
/*Could not set the flags on the interface */
56. perror("Could not set the PROMISC flag:");
57. exit(0);
58. }
59. printf("Setting interface ::: %s ::: to promisc",interface);
60. return(0);
61. }
/***********************EOF**********************************/
上面這段程序中有很詳細(xì)的注解,不過(guò)我想還是有必要說(shuō)一說(shuō),首先第10行--intOpen_Raw_Socket(void); 是我們的自定義函數(shù),具體內(nèi)容如下:
37.int Open_Raw_Socket() {
38. int sock;
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0){
/*Then the socket was not created properly and must die*/
40. perror("The raw socket was not created");
41. exit(0);
42. };
43. return(sock);
44. }
第39行 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
這里我們調(diào)用了socket函數(shù),使創(chuàng)建了了一個(gè)原始套接口,使之收到TCP/IP信息包。
接下來(lái)第11行-int Set_Promisc(char *interface, intsock),這也是我們的自定義函數(shù),目的是把網(wǎng)卡置于混雜模式,具體內(nèi)容如下:
45.int Set_Promisc(char *interface, int sock ) {
46. struct ifreq ifr;
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1);
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) {
/*Could not retrieve flags for the interface*/
49. perror("Could not retrive flags for the interface");
50. exit(0);
51. }
52. printf("The interface is ::: %s
", interface);
53. perror("Retrieved flags from interface successfully");
54. ifr.ifr_flags |= IFF_PROMISC;
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {
/*Could not set the flags on the interface */
56. perror("Could not set the PROMISC flag:");
57. exit(0);
58. }
59. printf("Setting interface ::: %s ::: to promisc",interface);
60. return(0);
61. }
首先 struct ifreq ifr; 定一了一個(gè)ifrreg的結(jié)構(gòu)ifr,接下來(lái)strncpy(ifr.ifr_name,interface,strnlen(interface)+1);,就是把我們網(wǎng)絡(luò)設(shè)備的名字填充到ifr結(jié)構(gòu)中,在這里#define INTERFACE "eth0" ,讓我們?cè)偻驴?ioctl(sock, SIOCGIFFLAGS,&ifr),SIOCGIFFLAGS請(qǐng)求表示需要獲取接口標(biāo)志,現(xiàn)在到了第54行,在我們成功的獲取接口標(biāo)志后把他設(shè)置成混雜模式,ifr.ifr_flags|= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS,&ifr)。OK,現(xiàn)在我們所說(shuō)的第一步已經(jīng)完成--------把網(wǎng)卡置于混雜模式。
現(xiàn)在進(jìn)入第二步,捕獲數(shù)據(jù)包。從第20行開(kāi)始,我們進(jìn)入了一個(gè)死循環(huán),while(1),在第24行,recvfrom(sock,buffer, sizeof buffer, 0, (struct sockaddr *)&from,&fromlen),這個(gè)函數(shù)要做的就是接收數(shù)據(jù),冰把接收到的數(shù)據(jù)放入buffer中。就是這么簡(jiǎn)單,已經(jīng)完成了我們要捕獲數(shù)據(jù)包的任務(wù)。
到了第三步,分析數(shù)據(jù)包。27行,ip = (struct ip*)buffer,使我們?cè)陬^文件中的IP結(jié)構(gòu)對(duì)應(yīng)于所接收到的數(shù)據(jù),接下來(lái)判斷在網(wǎng)絡(luò)層中是否使用的是TCP協(xié)議,if(ip->ip_protocol== 6) ,如果答案是,tcp信息包從整個(gè)IP/TCP包 buffer +(4*ip->ip_length) 地址處開(kāi)始,所以31行 tcp = (struct tcp*)(buffer +(4*ip->ip_length)),然后對(duì)應(yīng)結(jié)構(gòu)把你所需要的信息輸出。
/*************************headers.h**************************/
/*structure of an ip header*/
struct ip {
unsigned int ip_length:4; /*little-endian*/
unsigned int ip_version:4;
unsigned char ip_tos;
unsigned short ip_total_length;
unsigned short ip_id;
unsigned short ip_flags;
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_cksum;
unsigned int ip_source; unsigned int ip_dest;
};
/* Structure of a TCP header */
struct tcp {
unsigned short tcp_source_port;
unsigned short tcp_dest_port;
unsigned int tcp_seqno;
unsigned int tcp_ackno;
unsigned int tcp_res1:4, /*little-endian*/
tcp_hlen:4,
tcp_fin:1,
tcp_syn:1,
tcp_rst:1,
tcp_psh:1,
tcp_ack:1,
tcp_urg:1,
tcp_res2:2;
unsigned short tcp_winsize;
unsigned short tcp_cksum;
unsigned short tcp_urgent;
};
/*********************EOF***********************************/
從上面的分析我們可以清楚的認(rèn)識(shí)到,認(rèn)識(shí)一個(gè)SNIFF需要對(duì)TCP/IP協(xié)議有著詳細(xì)的了解,否則你根本無(wú)法找到你需要的信息。有了上面的基礎(chǔ),你可以自己來(lái)做一個(gè)你需要的SNIFF了。
掃碼付費(fèi)即可復(fù)制
XNIDS | p2p終結(jié)者 | 漏洞 | 中國(guó)知網(wǎng) | SNAT | 邏輯接口 | DMZ | 頻率校正突發(fā)脈沖序列 | 抽樣 | 射頻同軸電纜 | 直撥卡 | 廣電總局 |