SNIFF原理解析

回覆文章
tony
文章: 585
註冊時間: 2012-02-26, 07:04
聯繫:

SNIFF原理解析

未閱讀文章 tony »

一 前言

  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-Sniffer Construction 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, int sock); 
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, sizeof buffer, 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;
/*See if this is a TCP packet*/
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) {
/*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\n", 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**********************************/

  

  上面這段程式中有很詳細的注解,不過我想還是有必要說一說,首先第10行--int Open_Raw_Socket(void); 是我們的自定義函數,具體內容如下:

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

這裏我們調用了socket函數,使創建了了一個原始套介面,使之收到TCP/IP資訊包。

  接下來第11行-int Set_Promisc(char *interface, int sock),這也是我們的自定義函數,目的是把網卡置于混雜模式,具體內容如下:
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\n", 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; 定一了一個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, &ifr)。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)),然後對應結構把你所需要的資訊輸出。
/*************************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***********************************/



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


五 常用的SNIFF

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

(1)windows環境下

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

(2)UNUX環境下

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

1. sniffit

  sniffit可以運行在Solaris、SGI和Linux等平臺上,由Lawrence Berkeley Laboratory 實驗室開發的一個免費 的網路監聽軟體。最近Sniffit 0.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進制顯示

你可以在這裏找到sniffit http://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, dst and src ,這些關鍵字指明了 傳輸的方向。舉例說明,src 210.27.48.2 ,指明ip包中源地址是210.27.48.2 , dst net 202.0.0.0 指明目的 網路位址是202.0.0.0 。如果沒有指明方向關鍵字,則缺省是src or dst關鍵字。    

  第三種是協定的關鍵字,主要包括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需要幾個其他的第三方軟體進行支援,他們分別是,Berkeley DB ,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 的手段,瞭解什麽是ARP Spoof的前提你先要明白一下什麽是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出現才 能發送ARP Reply,也沒有規定一定要發送過ARP Request才能接收ARP Reply),其中的目的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命令時---ftp 10.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來說,他維護的是一張動態的位址表,幷且位址表的大小是有上限的,比如 3com Superstack Switch 3300 (3c16981 Hardware v.1 Software v.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)的缺陷引起的,在Windows 95、98、2000及SunOS、Solaris 2.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 Version 1.x被設計爲運行在乙太網的Windows系統中,提供了簡單易用的圖形用戶介面,AntiSniff Version 1.x 主要工作在非交換環境下的本地網段中,如果運行在交換環境下其功能將大打折扣。AntiSniff Ver 2.0 將不但能在本地網段中,而且能够穿過路由器和交換機進行工作。

◆ 作業系統類特殊測試

Linux 內核測試

  舊版本的Linux內核存在一個奇怪的特性,可被用于確定機器是否處于混雜模式。 在正常情形下,網卡會過濾和丟弃那些目標位址不是本機MAC位址或乙太網廣播位址 的資料包。如果資料包的目標位址爲本機乙太網位址或廣播位址,將傳送給內核進行 處理,因爲其認爲該乙太網資料幀包含了本機的正確IP地址或該網路廣播地址。如果 網卡處于混雜模式,則每個資料包都會傳遞給作業系統進行分析或處理。許多版本的 Linux內核只檢查資料包中的IP位址以確定是否存放到IP堆叠中進行處理。爲了利用 這一點,AntiSniff構造一個無效乙太網位址而IP位址有效的資料包。對于使用了這 些內核版本和處于混雜模式的Linux系統,由于只檢查到IP位址有效而將其接收幷存 放到相應堆叠中。通過在這個僞造的乙太網資料幀中構造一個ICMP ECHO請求,這些 系統會返回回應包(如果處于混雜模式)或忽略(如果不處于混雜模式),從而暴露其工 作模式。當僞造的乙太網資料幀中的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 Ver 1.x的web網站。

◆ DNS 測試

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

◆ 網路和主機回應時間測試

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

  根據以上要點,AntiSniff Ver 1.x 首先利用ICMP ECHO請求及回應計算出需要 檢測機器的回應時間基準和平均值。在得到這個資料後,立刻向本地網路發送大量的 僞造資料包。與此同時再次發送測試資料包以確定平均回應時間的變化值。非混雜模 式的機器的回應時間變化量會很小,而混雜模式的機器的回應時間變化量則通常會有 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運轉的根本原理,文章參考了大量的資料,牽涉到直接引用的已經注明出處和作者,非常的感謝他們。在此還要感謝 W.Richhard.Stevens,雖然其人已逝,但留下的TCP/IP三卷本真是造福了大家,文章的很多地方也是拜他老人家指點迷經才得以感悟。
回覆文章

誰在線上

正在瀏覽這個版面的使用者:沒有註冊會員 和 1 位訪客