SNIFF原理解析

SNIFF原理解析
本文出自:http://www.xfocus.org 作者: xundi (2001-10-01 15:00:00)

http://fanqiang.chinaunix.net/a5/b2/20011001/1500001382.html

2001-04-01.秋天的樹.   一 前言     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三卷本真是造福了
大家,文章的很多地方也是拜他老人家指點迷經才得以感悟。最後還要感謝雀巢咖啡,讓我得以熬
夜把這篇文章寫完,呵呵,謝謝大家。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章