天天看點

嗅探的基本原理[轉載]

一 前言

  SNIFF真是一個古老的話題,關于在網絡上采用SNIFF來擷取敏感資訊已經不是什麼新鮮事,也不乏很多成功的案例,那麼,SNIFF究竟是什麼呢?SNIFF就是嗅探器,就是竊聽器,SNIFF靜悄悄的工作在網絡的底層,把你的秘密全部記錄下來。看過威爾史密斯演的《全民公敵》嗎?SNIFF就象裡面精巧的竊聽器一樣,讓你防不勝防。

  SNIFF可以是軟體,也可以是硬體,既然是軟體那就要分平台,有WINDOWS下的、UNXI 下的等,硬體的SNIFF稱為網絡分析儀,反正不管硬體軟體,目标隻有一個,就是擷取在網絡上傳輸的各種資訊。本文僅僅介紹軟體的SNIFF。

  當你舒适的坐在家裡,惬意的享受網絡給你帶來的便利,收取你的EMAIL,購買你喜歡的物品的時候,你是否會想到你的朋友給你的信件,你的信用卡帳号變成了一個又一個的資訊包在網絡上不停的傳送着,你是否曾經這些資訊包會通過網絡流入别人的機器呢?你 的擔憂不是沒有道理的,因為SNIFF可以讓你的擔憂變成實實在在的危險。就好象一個人躲在你身後偷看一樣。。。。。。

二 網絡基礎知識

 “網絡基礎知識”,是不是聽起來有點跑題了?雖然聽起來這和我們要談的SNIFF沒什麼關系,可是還是要說一說的,萬丈高樓平地起,如果連地基都沒打好,怎麼蓋樓?!如果你對網絡還不是十厘清楚的話,最好能靜下心來好好看看,要知道,這是基礎的基礎,在這裡我隻是簡單的說一下,免得到時候有人迷糊,詳細的最好能夠自己去找書看看。

(1)TCP/IP體系結構

  開放系統互連(OSI)模型将網絡劃分為七層模型,分别用以在各層上實作不同的功能,這七層分别為:應用層、表示層、會話層、傳輸層、網絡層、資料鍊路層及實體層。而TCP/IP體系也同樣遵循這七層标準,隻不過在某些OSI功能上進行了壓縮,将表示層及會話層合并入應用層中,是以實際上我們打交道的TCP/IP僅僅有5層而已,網絡上的分層結構決定了在各層上的協定分布及功能實作,進而決定了各層上網絡裝置的使用。實際上很多成功的系統都是基于OSI模型的,如:如幀中繼、ATM、ISDN等。

   TCP/IP的網絡體系結構(部分)

-----------------------------------

| SMTP | DNS | HTTP | FTP | TELNET| 應用層

-----------------------------------

|    TCP    |   UDP      |  傳輸層

-----------------------------------

|  IP  |   ICMP   | ARP RARP | 網絡層 

------------------------

| IEEE 802 以太網 SLIP/PPP PDN etc| 資料鍊路層

-----------------------------------

|    網卡 電纜 雙絞線 etc    | 實體層

-----------------------------------

  從上面的圖中我們可以看出,第一層實體層和第二層資料鍊路層是TCP/IP的基礎,而TCP/IP本身并不十分關心低層,因為處在資料鍊路層的網絡裝置驅動程式将上層的協定和實際的實體接口隔離開來。網絡裝置驅動程式位于媒體通路子層(MAC)。         

           

(2)網絡上的裝置                          

中繼器:中繼器的主要功能是終結一個網段的信号并在另一個網段再生該信号,一句話,就是簡單的放大而已,工作在實體層上。   

網 橋:網橋使用MAC實體位址實作中繼功能,可以用來分隔網段或連接配接部分異種網絡,工作在資料鍊路層。

路由器:路由器使用網絡層位址(IP,X.121,E.164等),主要負責資料包的路由尋徑,也能處理實體層和資料鍊路層上的工作。

網 關:主要工作在網絡第四層以上,主要實作收斂功能及協定轉換,不過很多時候網關都被用來描述任何網絡互連裝置。

(3)TCP/IP與以太網

  以太網和TCP/IP可以說是互相相成的,可以說兩者的關系幾乎是密不可分,以太網在一二層提供實體上的連線,而TCP/IP工作在上層,使用32位的IP位址,以太網則使用48位的MAC位址,兩者間使用ARP和RARP協定進行互相轉換。從我們上面TCP/IP的模型圖中可以清楚的看到兩者的關系。

  載波監聽/沖突檢測(CSMA/CD)技術被普遍的使用在以太網中,所謂載波監聽是指在以太網中的每個站點都具有同等的權利,在傳輸自己的資料時,首先監聽信道是否空閑,如果空閑,就傳輸自己的資料,如果信道被占用,就等待信道空閑。而沖突檢測則是為了防止發生兩個站點同時監測到網絡沒有被使用時而産生沖突。以太網采用廣播機制,所有與網絡連接配接的工作站都可以看到網絡上傳遞的資料。

  為了加深你的了解,我們來看看下面的圖,一個典型的在以太網中客戶與伺服器使用

TCP/IP協定的通信。

使用者程序 FTP客戶 <-------------------------> FTP伺服器  應用層

| |

核心中的協定棧 TCP <-------------------------> TCP  傳輸層

| |

核心中的協定棧 IP <-------------------------> IP  網絡層

| |

以太網驅動程式 <-------------------------> 以太網驅動程式  資料鍊路層

──────------------------------------- 

以太網

  唆唆了這麼多,有人煩了吧?相信我,這是基礎的基礎,可以說是說得是很簡單拉 ,如果需要,拿出個幾十萬字來說上面的内容,我想也不嫌多,好了,讓我們進入下一節,sniff的原理。

三 SNIFF的原理

 要知道在以太網中,所有的通訊都是廣播的,也就是說通常在同一個網段的所有網絡接口都可以通路在實體媒體上傳輸的所有資料,而每一個網絡接口都有一個唯一的硬體位址,這個硬體位址也就是網卡的MAC位址,大多數系統使用48比特的位址,這個位址用來表示網絡中的每一個裝置,一般來說每一塊網卡上的MFC位址都是不同的,每個網卡廠家得到一段位址,然後用這段位址配置設定給其生産的每個網卡一個位址。在硬體位址和IP位址間使用ARP和RARP協定進行互相轉換。

  在正常的情況下,一個網絡接口應該隻響應這樣的兩種資料幀:

   1.與自己硬體位址相比對的資料幀。                       

   2.發向所有機器的廣播資料幀。

 在一個實際的系統中,資料的收發是由網卡來完成的,網卡接收到傳輸來的資料,網卡内的單片程式接收資料幀的目的MAC位址,根據計算機上的網卡驅動程式設定的接收模式判斷該不該接收,認為該接收就接收後産生中斷信号通知CPU,認為不該接收就丢掉不管,是以不該接收的資料網卡就截斷了,計算機根本就不知道。CPU得到中斷信号産生中斷,作業系統就根據網卡的驅動程式設定的網卡中斷程式位址調用驅動程式接收資料,驅動程式接收資料後放入信号堆棧讓作業系統處理。而對于網卡來說一般有四種接收模式:

   廣播方式:該模式下的網卡能夠接收網絡中的廣播資訊。             

   多點傳播方式:設定在該模式下的網卡能夠接收多點傳播資料。                                 

   直接方式:在這種模式下,隻有目的網卡才能接收該資料。   

   混雜模式:在這種模式下的網卡能夠接收一切通過它的資料,而不管該資料是否是傳給它的。

 好了,現在我們總結一下,首先,我們知道了在以太網中是基于廣播方式傳送資料的, 也就是說,所有的實體信号都要經過我的機器,再次,網卡可以置于一種模式叫混雜模式(promiscuous),在這種模式下工作的網卡能夠接收到一切通過它的資料,而不管實際上資料的目的位址是不是他。這實際上就是我們SNIFF工作的基本原理:讓網卡接收一切他所能接收的資料。

(圖一)

 我們來看一個簡單的例子,如圖一所示,機器A、B、C與集線器HUB相連接配接,集線器HUB通過路由器Router通路外部網絡。這是一個很簡單也很常見的情況,比如說在公司大樓裡,我所在的網絡部辦公室裡的幾台機器通過集線器連接配接,而網絡部、開發部、市場部也是同樣如此,幾個部門的集線器通過路由器連接配接。還是回到我們的圖一上來,值得注意的一點是機器A、B、C使用一個普通的HUB連接配接的,不是用SWITCH,也不是用ROUTER,使用SWITCH和ROUTER的情況要比這複雜得多。

 我們假設一下機器A上的管理者為了維護機器C,使用了一個FTP指令向機器C進行遠端登陸,那麼在這個用HUB連接配接的網絡裡資料走向過程是這樣的。首先機器A上的管理者輸入的登陸機器C的FTP密碼經過應用層FTP協定、傳輸層TCP協定、網絡層IP協定、資料鍊路層上的以太網驅動程式一層一層的包裹,最後送到了實體層,我們的網線上。接下來資料幀送到了HUB上,現在由HUB向每一個接點廣播由機器A發出的資料幀,機器B接收到由HUB廣播發出的資料幀,并檢查在資料幀中的位址是否和自己的位址相比對,發現不是發向自己的後把這資料幀丢棄,不予理睬。而機器C也接收到了資料幀,并在比較之後發現是發現自己的

,接下來他就對這資料幀進行分析處理。

 在上面這個簡單的例子中,機器B上的管理者如果很好奇,他很想知道究竟登陸機器C上FTP密碼是什麼?那麼他要做的很簡單,僅僅需要把自己機器上的網卡置于混雜模式,并對接收到的資料幀進行分析,進而找到包含在資料幀中的密碼資訊。

四 做一個自己的sniff

 在上一節裡,我們已經知道了SNIFF的基本原理是怎麼一回事,這一節我們來親自動手做一個自己的sniff,畢竟,用程式代碼來說話比什麼都要來得真實,也容易加深了解。

回頭想一想我們上面說的原理,我們要做的事情有幾件:

1. 把網卡置于混雜模式。                             

2. 捕獲資料包。       

3.分析資料包。

注:下面的源代碼取至Chad Renfro的<< Basic Packet-SnifferConstruction from the

Ground Up>>一文中

1.#include  

2.#include  

3.#include

4.#include

5.#include

6.#include

7.#include  

8.#include

9.#include "headers.h"

#define INTERFACE "eth0"

 

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("/nBytes received :::%5d/n",bytes_recieved);

26. printf("Source address :::%s/n",inet_ntoa(from.sin_addr));

27. ip = (struct ip *)buffer;

28. if(ip->ip_protocol == 6) {

29. printf("IP header length :::%d/n",ip->ip_length);

30. printf("Protocol :::%d/n",ip->ip_protocol);

31. tcp = (struct tcp *)(buffer +(4*ip->ip_length));

32. printf("Source port :::%d/n",ntohs(tcp->tcp_source_port));

33. printf("Dest port :::%d/n",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){

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)) {  

49. perror("Could not retrive flags for the interface");

50. exit(0);

51. } 

52. printf("The interface is ::: %s/n", interface);  

53. perror("Retrieved flags from interface successfully");

54. ifr.ifr_flags |= IFF_PROMISC;  

55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {  

 

56. perror("Could not set the PROMISC flag:");

57. exit(0);    

58. }

59. printf("Setting interface ::: %s ::: to promisc",interface);

60. return(0);

61. }

  上面這段程式中有很詳細的注解,不過我想還是有必要說一說,首先第10行--intOpe

n_Raw_Socket(void); 是我們的自定義函數,具體内容如下:

37.int Open_Raw_Socket() {    

38. int sock;

39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0){

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) {

這裡我們調用了socket函數,使建立了了一個原始套接口,使之收到TCP/IP資訊包。

  接下來第11行-int Set_Promisc(char *interface, intsock),這也是我們的自定義函數,目的是把網卡置于混雜模式,具體内容如下:

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)) {  

49. perror("Could not retrive flags for the interface");

50. exit(0);

51. } 

52. printf("The interface is ::: %s/n", interface);  

53. perror("Retrieved flags from interface successfully");

54. ifr.ifr_flags |= IFF_PROMISC;  

55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {  

 

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; 定一了一個ifrreg的結構ifr,接下來strncpy(ifr.ifr_name,interface,strnlen(interface)+1);,就是把我們網絡裝置的名字填充到ifr結構中,在這裡#define INTERFACE "eth0" ,讓我們再往下看,ioctl(sock, SIOCGIFFLAGS,&ifr) ,SIOCGIFFLAGS請求表示需要擷取接口标志,現在到了第54行,在我們成功的擷取接口标志 後把他設定成混雜模式,ifr.ifr_flags|= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS,&i fr)。OK,現在我們所說的第一步已經完成--------把網卡置于混雜模式。

  現在進入第二步,捕獲資料包。從第20行開始,我們進入了一個死循環,while(1),在第24行,recvfrom(sock,buffer, sizeof buffer, 0, (struct sockaddr *)&from,&fromlen),這個函數要做的就是接收資料,冰把接收到的資料放入buffer中。就是這麼簡單,已經完成了我們要捕獲資料包的任務。

  到了第三步,分析資料包。27行,ip = (struct ip*)buffer,使我們在頭檔案中的IP結構對應于所接收到的資料,接下來判斷在網絡層中是否使用的是TCP協定,if(ip->ip_ protocol== 6) ,如果答案是,tcp資訊包從整個IP/TCP包 buffer +(4*ip->ip_length) 位址處開始,是以31行 tcp = (struct tcp*)(buffer +(4*ip->ip_length)),然後對應結 構把你所需要的資訊輸出。

 

struct ip {   

unsigned int ip_length:4;  

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;  

};

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,

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;

};

 從上面的分析我們可以清楚的認識到,認識一個SNIFF需要對TCP/IP協定有着詳細的了解,否則你根本無法找到你需要的資訊。有了上面的基礎,你可以自己來做一個你需要的SNIFF了。

五 常用的SNIFF

 很少有原因會讓你自己親自動手來做一個自己的SNIFF,除非你是想了解他的原理,或者是其他一些特别的原因,比如你要在某個特殊的環境攔截一些特殊的資料包。下面我們就來看看一些在網絡上經常使用的SNIFF。

(1)windows環境下

  windows環境下當然是大名鼎鼎的netxray以及snifferpro了,實際上很多人都是用他在windows環境下抓包來分析,不過我想很少有人笨到去在别人的機器上安裝一個圖形界面的SNIFF,除非他和管理者很熟悉........netxray的使用就不多說了,反正windows下的東西就是click,click,click,非常的友善使用者。

(2)UNUX環境下

 UNUX環境下的sniff可以說是百花齊放,一抓就是一大把,如sniffit,snoop,tcpdump,dsniff等都是比較常見的,他們都有一個好處就是釋出源代碼,可以讓你研究,當然也都是免費的:)

1. sniffit

  sniffit可以運作在Solaris、SGI和Linux等平台上,由LawrenceBerkeley Laboratory 實驗室開發的一個免費的網絡監聽軟體。最近Sniffit0.3.7也推出了NT版本,并也支援WINDOWS2000.

使用方法:

-v 顯示版本資訊

-a 以ASCII形式将監聽的結果輸出。

-A 在進行記錄時,所有不可列印的字元都用代替

-b 等同于同時使用參數-t & -s。    

-d 将監聽所得内容以十六進制方式顯示在目前終端 

-p 記錄連接配接到的包,0為所有端口。預設為0。   

-P protocol選擇要檢查的協定,預設為TCP。可能的選擇有IP、TCP、ICMP、UDP和他們的組合。

-s 指定sniffer 檢查從 發送的資料包。 -t 指定sniffer檢查發送到的資料包。

-i 進入互動模式   

-l 設定資料包大小,default是300位元組   

注:參數可以用@來表示一個IP範圍,比如 -t 192.168.@ -t和-s隻适用于TCP/UDP資料包,對于ICMP和IP也進行解釋。但如果隻選擇了-p參數,則隻用于TCP和UDP包。

舉例說明:

#sniffit -a -p 21 -t xxx.xxx.xxx.xxx

監聽流向機器xxx.xxx.xxx.xxx的21端口(FTP)的資訊,并以ASCII顯示

#sniffit -d -p 23 -b xxx.xxx.xxx.xxx

監聽所有流出或流入機器xxx.xxx.xxx.xxx的23端口(telnet)的資訊,并以16進制顯示

你可以在這裡找到sniffithttp://reptile.rug.ac.be/~coder/sniffit/sniffit.html

2. snoop

 snoop預設情況安裝在Solaris下,是一個用于顯示網絡交通的程式,不過SNIFF是把雙刃劍,既然管理者能用他來監視自己的網絡,當然一個心懷惡意的入侵者也可以用他來SNIFF自己感興趣的内容。值得一提的是,SNOOP被發現存在一個緩沖區溢出漏洞,當以導緻入侵者以運作snoop(通常為root)的身份遠端進入系統。這是題外話,暫且就此打住。

使用方法:

[ -a ] # Listen to packets on audio

[ -d device ] # settable to le?, ie?, bf?, tr?

[ -s snaplen ] # Truncate packets

[ -c count ] # Quit after count packets

[ -P ] # Turn OFF promiscuous mode

[ -D ] # Report dropped packets

[ -S ] # Report packet size

[ -i file ] # Read previously captured packets

[ -o file ] # Capture packets in file

[ -n file ] # Load addr-to-name table from file

[ -N ] # Create addr-to-name table

[ -t r|a|d ] # Time: Relative, Absolute or Delta

[ -v ] # Verbose packet display

[ -V ] # Show all summary lines

[ -p first[,last] ] # Select packet(s) to display

[ -x offset[,length] ] # Hex dump from offset for length

[ -C ] # Print packet filter code

例如:

#snoop -o saved A B

監聽機器A與B的談話,并把内容存儲于檔案saved中

3. tcpdump

 tcpdmp也算是一個很有名氣的網絡監聽軟體,FREEBSD還把他附帶在了系統上,是一個被很多UNIX高手認為是一個專業的網絡管理工具。

使用方法:

  tcpdump采用指令行方式,它的指令格式為:

tcpdump [ -adeflnNOpqStvx ][ -c 數量 ][ -F 檔案名 ][ -i網絡接口 ][ -r 檔案名][

-s snaplen ][ -T 類型 ][ -w 檔案名 ][表達式]

1. tcpdump的選項介紹

-a    将網絡位址和廣播位址轉變成名字;

-d    将比對資訊包的代碼以人們能夠了解的彙編格式給出;

-dd    将比對資訊包的代碼以c語言程式段的格式給出;

-ddd   将比對資訊包的代碼以十進制的形式給出;

-e    在輸出行列印出資料鍊路層的頭部資訊;

-f    将外部的Internet位址以數字的形式列印出來;

-l    使标準輸出變為緩沖行形式;

-n    不把網絡位址轉換成名字;

-t    在輸出的每一行不列印時間戳;

-v   輸出一個稍微詳細的資訊,例如在ip包中可以包括ttl和服務類型的資訊;

-vv    輸出詳細的封包資訊;

-c    在收到指定的包的數目後,tcpdump就會停止;

-F    從指定的檔案中讀取表達式,忽略其它的表達式;

-i    指定監聽的網絡接口;

-r    從指定的檔案中讀取包(這些包一般通過-w選項産生);

-w    直接将包寫入檔案中,并不分析和列印出來;

-T   将監聽到的包直接解釋為指定的類型的封包,常見的類型有rpc和snmp

2. tcpdump的表達式介紹

 表達式是一個正規表達式,tcpdump利用它作為過濾封包的條件,如果一個封包滿足表達 式的條件,則這個封包将會被捕獲。如果沒有給出任何條件,則網絡上所有的資訊包将會被截獲。

 在表達式中一般如下幾種類型的關鍵字,一種是關于類型的關鍵字,主要包括host,net,port,例如 host 210.27.48.2,指明 210.27.48.2是一台主機,net 202.0.0.0指明 202.0.0.0是一個網絡位址,port 23指明端口号是23。如果沒有指定類型,預設的類型是host.

  第二種是确定傳輸方向的關鍵字,主要包括src , dst ,dst or src, dstand src ,這些關鍵字指明了 傳輸的方向。舉例說明,src 210.27.48.2,指明ip包中源位址是210.27. 48.2 , dst net 202.0.0.0 指明目的網絡位址是202.0.0.0 。如果沒有指明方向關鍵字,則預設是src ordst關鍵字。

  第三種是協定的關鍵字,主要包括fddi,ip,arp,rarp,tcp,udp等類型。Fddi指明是在FDDI(分布式光纖資料接口網絡)上的特定的網絡協定,實際上它是"ether"的别名,fddi和ether具有類似的源位址和目的位址,是以可以将fddi協定包當作ether的包進行處理和分析。其他的幾個關鍵字就是指明了監聽的包的協定内容。如果沒有指定任何協定,則tcpdump将會監聽所有協定的資訊包。

  除了這三種類型的關鍵字之外,其他重要的關鍵字如下:gateway,broadcast,less,greater,還有三種 邏輯運算,取非運算是 `not ` `! `,與運算是`and`,`&&`;或運算 是`or` ,`||`。

舉例使用:

#tcpdump host AAA.BBB.CCC.DDD

将監聽IP位址為AAA.BBB.CCC.DDD的機器的通話

#tcpdump tcp port 23 host AAA.BBB.CCC.DDD

将監聽IP位址為AAA.BBB.CCC.DDD的機器的23端口的通話

4. dsniff

 之是以要談談dsniff,是因為他不僅僅是一個sniff,在他的整個套件包中,包含了很多其它有用的工具,如arpspoof,dnsspoof,macof,tcpkill等等,SNIFF的手段更加的多樣和複雜化。dsniff是由DugSong開發的你可以在他的首頁上找到這個工具。 目前dsniff支援OpenBSD (i386),Redhat Linux (i386), 和Solaris (sparc). 并且在FreeBSD, Debian Linux, Slackware Linux, AIX,和HP-UX上也能運轉得很好。但是dsniff需要幾個其他的第三方軟體進行支援,他們分别是,BerkeleyDB ,OpenSSL, libpcap, libnet,libnids 。如果條件允許的話,你最好能夠親自讀一讀dsniff的源代碼,你可以在http://naughty.monkey.org/~dugsong/ 找到dsniff。

六 深入sniff

 單純的sniff的功能始終是局限的,是以在大多數的情況下,sniff往往和其他手段結合起來使用,sniff和spoof已及其他技術手段結合在一起對網絡構成的危害是巨大的。單純的sniff好比缺了一隻腿,無法發揮大的作用,例如在sniff原理一節中我們讨論的例子裡,我一再的強調我們使用的是一個普通的HUB進行連接配接是有原因的,如果我們把在圖一中的HUB用一個switch代替,那情況就要複雜一些了,如圖二所示:

圖(二)

 在圖二中,我們的機器A、B、C與Switch相連接配接,而Switch通過路由器Router通路外部網絡。我們先來了解Switch的工作原理:

  在我們圖一中的 HUB隻是簡單地把所接收到的信号通過所有端口(除了信号來的那個口)重複發送出去不同,而圖二中的Switch卻可以檢查每一個收到的資料包,并對資料包進行相應的處理。在Switch内儲存着每一個網段上所有節點的實體位址,隻允許必要的網絡流量通過Switch。舉例來說,當Switch接收到一個資料包之後,根據自身儲存的網絡位址表檢查資料包内包含的發送和接收方位址。如果接收方位于發送方網段,該資料包就會被 Switch丢棄,不能通過交換機傳送到其它的網段;如果接收方和發送方位于兩個不同的網段,該資料包就會被Switch轉發到目标網段。這樣,通過交換機的過濾和轉發,可以有效避免網絡廣播風暴,減少誤包和錯包的出現。順便說一句,現在Switch和HUB的價格相去無幾,是以hub正逐漸被網絡交換機取代。

 現在回到我們的例子中來,在圖二中仍然和圖一一樣,我們假設機器A上的管理者為了維 護機器C,使用了一個FTP指令向機器C進行遠端登陸,那麼在這裡,資料是這樣走的:首先 機器A上的管理者輸入的登陸機器C的FTP密碼經過應用層FTP協定、傳輸層TCP協定、網絡層 IP協定、資料鍊路層上的以太網驅動程式一層一層的包裹,最後送到了實體層,我們的網 線上。接下來資料幀送到了Switch上,而Switch檢查資料幀中的目的位址,并在他自身儲存的網絡位址表中知道了他應該把這資料幀發到機器C那裡,于是,接下來機器C接收到了從A發來的資訊,發現他是發給自己的資訊,于是進行分析處理。

 OK,現在我們機器B上的管理者的好奇心隻能深深的埋藏在心裡了,因為資料包根本就沒有經過他,就算他把自己的網卡設定成混雜模式也是有力無處使。

 在了解在一個Switch環境下原理後,我們結合一些手段去設法sniff,是的,我們可以做到這一點,有許多的手段可以讓管理者B滿足他的好奇心,在下面我會提出幾個辦法,當然隻是其中的一些辦法而已。

1 ARP Spoof

  在基于IP通信的内部網中,我們可以使用 ARP Spoof的手段,了解什麼是ARPSpoof的前提你先要明白一下什麼是ARP和RARP協定,什麼是MAC位址,什麼又是IP位址。ARP協定是位址轉換協定,RARP被稱為反向位址轉換協定,他們負責把IP位址和MAC位址進行互相轉換對應。

  ARP Spoof 攻擊的根本原理是因為計算機中維護着一個 ARP高速緩存,并且這個ARP高速緩存是随着計算機不斷的發出ARP請求和收到ARP響應而不斷的更新的,ARP高速緩存的目的是把機器的IP位址和MAC位址互相映射。你可以使用 arp指令來檢視你自己的 ARP高速緩存。現在設想一下,一個Switch工作在資料鍊路層,他根據MAC位址來轉發他所接收的資料包,而電腦維護的ARP 高速緩存卻是動态的......你想到什麼了嗎?

  為了加深了解,現在給我們的機器編上号,機器A:IP位址為 10.0.0.1,MAC位址為 20-53-52-43-00-01 ,機器B:IP位址為 10.0.0.2 ,MAC位址為20-53-52-43-00-02,機器C:IP位址為 10.0.0.3 ,MAC位址為20-53-52-43-00-03 。現在機器B上的管理者是個聰明的家夥,他向機器A發出一個 ARP Reply(協定沒有規定一定要等ARP Request出現才 能發送ARPReply,也沒有規定一定要發送過ARP Request才能接收ARPReply),其中的目的IP位址為10.0.0.1,目的MAC位址為20-53-52-43-00-01 ,而源IP位址為10.0.0.3,源MAC位址為20-53-52-43-00-02 ,好了,現在機器A更新了他的 ARP高速緩存,并相信了IP位址為10. 0.0.3的機器的MAC位址是20-53-52-43-00-02 。當機器A上的管理者發出一條FTP指令時---ftp10.0.0.3,資料包被送到了Switch,Switch檢視資料包中的目的位址,發現MAC為20-53-52-43-00-02,于是,他把資料包發到了機器B上。再設想一下,如果不想影響A和C之間的通信該怎麼辦?你可以同時欺騙他們雙方,來一個 man-in-middle 。

 當然,在實際的操作中你還需要考慮到一些其他的事,比如某些作業系統在會主動的發送ARP請求包來更新相應的ARP入口等。

2. MAC Flooding

 在上面我們曾經提到過,Switch之是以能夠由資料包中目的MAC位址判斷出他應該把資料包發送到那一個端口上是根據他本身維護的一張位址表。這張位址表可能是動态的也可能是靜态的,這要看Switch的廠商和Switch的型号來定,對于某些Switch來說,他維護的是一張動态的位址表,并且位址表的大小是有上限的,比如 3comSuperstack Switch 3300 (3c16981 Hardware v.1 Softwarev.2.10)就是這樣一種Switch,我們可以通過發送大量錯誤的位址資訊而使SWITCH維護的位址表“溢出”,進而使他變成廣播模式來達到我們要sniff 機器A與機器C之間的通信的目的。

3. Fake the MAC address

 僞造MAC位址也是一個常用的辦法,不過這要基于你網絡内的Switch是動态更新其位址表,這實際上和我們上面說到的ARP Spoof有些類似,隻不過現在你是想要Switch相信你,而不是要機器A相信你。因為Switch是動态更新其位址表的,你要做的事情就是告訴Switch:HI,我是機器C。換成技術上的問題你隻不過需要向Switch發送僞造過的資料包,其中源MAC位址對應的是機器C的MAC位址,現在Switch就把機器C和你的端口對應起來了。不過其中存在一個問題,現在機器C也會說了:HI,Switch老大,我才是機器C呢!,現在你該怎麼辦?切,還用問!讓他說不了話就可以了,DOS還是其他什麼,随便你了......

4. ICMP Router Advertisements

  這主要是由ICMP路由器發現協定(IRDP)的缺陷引起的,在Windows95、98、2000及SunOS、Solaris2.6等系統中,都使用了IRDP協定,SunOS系統隻在某些特定的情況下使用該協定,而Windows95,Windows95b, Windows98, Windows98se, 和Windows2000都是預設的使用IRDP協定。IRDP協定的主要内容就是告訴人們誰是路由器,設想一下,一個HACK利用IRDP宣稱自己是路由器的情況會有多麼的糟糕!所有相信HACK的請求的機器把他們所有的資料都發送給HACK所控制的機器.........

5. ICMP Redirect

 所謂ICMP重定向,就是指告訴機器向另一個不同的路由發送他的資料包,ICMP重定向通常使用在這樣的場合下,假設A與B兩台機器分别位于同一個實體網段内的兩個邏輯子網内,而A和B都不知道這一點,隻有路由器知道,當A發送給B的資料到達路由器的時候,路由器會向A送一個ICMP重定向包裹,告訴A:HI,别再送資料給我轉交了,你就直接送到B那裡就可以了。設想一下,一個hack完全可以利用這一點,使得A發送給B的資料經過他。

 上面提到的這些方法隻不是其中的一些,為了配合sniff能夠工作得更有效率,還有其他許多的辦法,其實sniff的目的說穿了隻有一個,就是抓包,從抓包這個概念上引伸下去,所有為了能夠抓到網絡上的資訊包而采用的技術都可以歸入sniff,單純的sniff是沒有什麼效率的。你還能想到什麼嗎?進攻路由器,在路由器上放置sniff......,在系統核心中植入sniff......等等。

七 如何防止SNIFF

 防止sniff最有效的手段就是進行合理的網絡分段,并在網絡中使用交換機和網橋,在理想的情況下使每一台機器都擁有自己的網絡段,當然這會使你的網絡建設費用增加很多,是以你可以盡量使互相信任的機器屬于同一個網段,使他們互相之間不必擔心sniff的存在。并在網段于網段間進行硬體屏障。你也可以使用加密技術對你在網絡中傳送的敏感資料如戶ID或密碼,你的銀行帳号,商業機密等進行加密,你可以選用SSH等加密手段。為了防止ARP欺騙,你可以使用永久的ARP緩存條目,反正上面的攻擊手段和原理你也看了,你就反過來想想該怎麼辦好了。不過有盾必有矛,平時的安全意識才是最重要的。

 (注:以下關于AntiSniff的介紹取至backend翻譯整理的L0pht AntiSniff技術文檔一文)

  當你做做層層保護後,你還是懷疑自己的網絡上存在sniff該怎麼辦?L0pht小組為了探測sniff專門釋出了一個軟體 AntiSniff,當然這個軟體不是免費的:),AntiSniff工具用于檢測區域網路中是否有機器處于混雜模式,AntiSniff Version1.x被設計為運作在以太網的Windows系統中,提供了簡單易用的圖形使用者界面,AntiSniffVersion1.x 主要工作在非交換環境下的本地網段中,如果運作在交換環境下其功能将大打折扣。AntiSniffVer 2.0将不但能在本地網段中,而且能夠穿過路由器和交換機進行工作。

◆ 作業系統類特殊測試

Linux 核心測試

 舊版本的Linux核心存在一個奇怪的特性,可被用于确定機器是否處于混雜模式。在正常情形下,網卡會過濾和丢棄那些目标位址不是本機MAC位址或以太網廣播位址的資料包。如果資料包的目标位址為本機以太網位址或廣播位址,将傳送給核心進行處理,因為其認為該以太網資料幀包含了本機的正确IP位址或該網絡廣播位址。如果網卡處于混雜模式,則每個資料包都會傳遞給作業系統進行分析或處理。許多版本的Linux核心隻檢查資料包中的IP位址以确定是否存放到IP堆棧中進行處理。為了利用這一點,AntiSniff構造一個無效以太網位址而IP位址有效的資料包。對于使用了這些核心版本和處于混雜模式的Linux系統,由于隻檢查到IP位址有效而将其接收并存放到相應堆棧中。通過在這個僞造的以太網資料幀中構造一個ICMPECHO請求,這些系統會傳回響應包(如果處于混雜模式)或忽略(如果不處于混雜模式),進而暴露其工作模式。當僞造的以太網資料幀中的IP位址設定為網絡廣播位址時這個測試非常有效。AntiSniff的使用者可以修改僞造的以太網址,預設值為66:66:66:66:66:66。

NetBSD

 許多NetBSD核心具有與上述Linux核心相同的特性,不過僞造以太網資料幀中的IP位址必須設為廣播位址。

Windows 95/98/NT

 根據對網絡驅動程式頭檔案的了解,可以知道當處于混雜模式時,Microsoft的作業系統會确切地檢查每個包的以太網位址。如果與網卡的以太網位址比對,将作為目标IP位址為本機的資料包存放到相應堆棧中處理。可以被利用的一點是系統對以太網廣播包的分析。在正常情形下,例如機器工作在非混雜模式下,網卡隻向系統核心傳輸那些目标以太網址與其比對或為以太網廣播位址(ff:ff:ff:ff:ff:ff)的資料包。如果機器處于混雜模式下,網絡驅動程式仍然會檢查每個資料包的以太網位址,但檢查是否為廣播包時卻隻檢查頭8位位址是否為0xff。是以,為了使處于混雜模式的系統傳回響應資訊,AntiSniff構造以太網位址為ff:00:00:00:00:00且含有正确目标IP位址的資料包,當Microsoft的作業系統接收到這個資料包時,将根據網絡驅動程式檢查到的細微差别而傳回響應包(如果處于混雜模式)或丢棄這個資料包(如果處于非混雜模式)。

 需要注意的是,這個檢查與使用的網絡驅動程式有關。Microsoft預設的網絡驅動程式具有以上特性,大多數的廠商為了保持相容性也繼承了這些特性。不過有些網卡會在其硬體層中檢查以太網位址的頭8位,是以可能會無論系統真正的狀态是什麼都總是傳回正值。關于這類網卡和驅動程式請通路AntiSniff Ver1.x的web網站。

◆ DNS 測試

 進行DNS測試的原因是許多攻擊者使用的網絡資料收集工具都對IP位址進行反向DNS解析,因為他們希望根據域名尋找更有價值的主機。例如joepc1.foo.bar對攻擊者的吸引力往往不如payroll.foo.bar這種商業域名。此時這些工具就由被動型網絡工具變為主動型網絡工具了。而不監聽網絡通訊的機器不會試圖反向解析資料包中的IP位址。為了利用這一點,AntiSniff Ver1.x使自身處于混雜模式下,向網絡發送虛假目标IP位址的資料包,然後監聽是否有機器發送該虛假目标IP位址的反向DNS查詢。僞造資料包的以太網位址、檢查目标、虛假目标IP位址可由使用者定制。

◆ 網絡和主機響應時間測試

 這種測試已被證明是最有效的。它能夠發現網絡中處于混雜模式的機器,而不管其作業系統是什麼。警告,這個測試會在很短的時間内産生巨大的網絡通訊流量。進行這種測試的理由是不處于混雜模式的網卡提供了一定的硬體底層過濾機制。也就是說,目标位址非本地(廣播位址除外)的資料包将被網卡的固件丢棄。在這種情況下,驟然增加、但目标位址不是本地的網絡通訊流量對作業系統的影響隻會很小。而處于混雜模式下的機器則缺乏此類底層的過濾,驟然增加、但目标位址不是本地的網絡通訊流量會對該機器造成較明顯 的影響(不同的作業系統/核心/使用者方式會有不同)。這些變化可以通過網絡通訊流量工具監視到。

  根據以上要點,AntiSniff Ver 1.x 首先利用ICMPECHO請求及響應計算出需要檢測機器的響應時間基準和平均值。在得到這個資料後,立刻向本地網絡發送大量的僞造資料包。與此同時再次發送測試資料包以确定平均響應時間的變化值。非混雜模式的機器的響應時間變化量會很小,而混雜模式的機器的響應時間變化量則通常會有1-4個數量級。為了對付攻擊者和入侵者們最常用的多種工具,AntiSniff進行了三種網絡飽和度測試:SIXTYSIX、TCPSYN和THREEWAY。

     *SIXTYSIX測試構造的資料包資料全為0x66。這些資料包不會被非混雜模式的機器接收,同時友善使用常見的網絡監聽/分析工具(如tcpdump和snoop等)記錄和捕獲。

     *TCPSYN測試構造的資料包包含有效的TCP頭和IP頭,同時TCP标志域的SYN位被設定。

    *THREEWAY測試采取的原理基本上與TCPSYN一樣,但更複雜些。在這種測試中兩個實際不存在的機器間多次建立完整的TCP三方握手通訊。它能夠更好地欺騙那些駭客工具。

  AntiSniff Ver 1.x中能夠通過以上三種資料包測試發現正處于混雜模式機器的測試方法最好周期性地進行和與以前的資料比較。響應時間測試第一次運作的資料還能夠用于分析一個大型網絡在flooding和非flooding狀态時的性能,并幫助工程師調整網絡性能。一旦确信本地網絡已運作在正常(沒有未經允許而處于混雜模式的機器)狀态,就應該設定AntiSniff工具周期性運作。隻要發現某台機器性能(響應時間)發生數量級的變化,一般就能确定其正處于混雜模式。這種方法不需比較兩台獨立系統間的性能資料,而隻需比較同一台機器不同時候的資料就能确定該機器是否處于混雜模式。

八 結尾

 本文旨在向你描述sniff的基本原理,為的是要使你不僅僅能夠了解什麼是sniff而已,而是要明白sniff運轉的根本原理

繼續閱讀