交換型網(wǎng)絡(luò)環(huán)境嗅探原理及LINUX下的實(shí)現(xiàn)
1. 以太網(wǎng)嗅探原理
以太網(wǎng)環(huán)境下的嗅探本身是比較簡(jiǎn)單的,只要網(wǎng)卡能設(shè)置成混雜模式且有數(shù)據(jù)包到達(dá)網(wǎng)卡,則可用多種方法捕獲數(shù)據(jù)包并進(jìn)行各種協(xié)議分析。在LINUX下可用RAW套接字,SOCK_PACKET套接字, LIBPCAP函數(shù)包等方法捕獲數(shù)據(jù)包,典型的應(yīng)用程序如TCPDUMP, LINUX_SNIFFER等。
在共享型以太網(wǎng)中,上述兩個(gè)條件顯然是滿足的。所有的主機(jī)都連接到HUB,而HUB對(duì)數(shù)據(jù)包傳輸形式是廣播。這意味著發(fā)給某個(gè)主機(jī)的數(shù)據(jù)包也會(huì)被其它所有主機(jī)的網(wǎng)卡所收到。因此在這樣的環(huán)境中,任何設(shè)置成混雜模式的主機(jī),都可以捕獲發(fā)送給其它主機(jī)的數(shù)據(jù)包,從而竊聽(tīng)網(wǎng)絡(luò)上的所有通信。
在交換型以太網(wǎng)中,上述條件2是不滿足的。所有的主機(jī)連接到SWITCH,SWITCH比HUB更聰明,它知道每臺(tái)計(jì)算機(jī)的MAC地址信息和與之相連的特定端口,發(fā)給某個(gè)主機(jī)的數(shù)據(jù)包會(huì)被SWITCH從特定的端口送出,而不是象HUB那樣,廣播給網(wǎng)絡(luò)上所有的機(jī)器。這種傳輸形式使交換型以太網(wǎng)的性能大大提高,同時(shí)還有一個(gè)附加的作用:使傳統(tǒng)的嗅探器無(wú)法工作。
綜上所述,交換型網(wǎng)絡(luò)環(huán)境嗅探的核心問(wèn)題是:如何使本不應(yīng)到達(dá)的數(shù)據(jù)包到達(dá)本地。通常的方法有MAC洪水包和ARP欺騙。其中MAC洪水包是向交換機(jī)發(fā)送大量含有虛構(gòu)MAC地址和IP地址的IP包,使交換機(jī)無(wú)法處理如此多的信息,致使交換機(jī)就進(jìn)入了所謂的"打開(kāi)失效"模式,也就是開(kāi)始了類似于集線器的工作方式,向網(wǎng)絡(luò)上所有的機(jī)器廣播數(shù)據(jù)包。(具體實(shí)現(xiàn)請(qǐng)參閱Dsniff中的macof)本文中,我們將要詳細(xì)分析ARP欺騙模式。
2. 相關(guān)協(xié)議數(shù)據(jù)包格式
以太數(shù)據(jù)包格式:
類型0800 :IP數(shù)據(jù)包
類型0806 :ARP數(shù)據(jù)包
ARP數(shù)據(jù)包格式:
ARP數(shù)據(jù)包簡(jiǎn)化格式
為了論述的簡(jiǎn)潔性,我們把ARP數(shù)據(jù)包格式做一些簡(jiǎn)化。 目的端MAC地址 源MAC地址 ARP包類型 發(fā)送端MAC地址 發(fā)送端IP地址 目的端MAC地址 目的端IP地址
3. 實(shí)驗(yàn)環(huán)境
為了更清楚的描述交換網(wǎng)絡(luò)的嗅探原理,我們建立一個(gè)虛構(gòu)的交換網(wǎng)絡(luò)環(huán)境, 在下面的論述中將用到這些數(shù)據(jù).
4. ARP協(xié)議原理
在以太網(wǎng)中傳輸?shù)臄?shù)據(jù)包是以太包,而以太包的尋址是依據(jù)其首部的物理地址(MAC地址)。僅僅知道某主機(jī)的邏輯地址(IP地址)并不能讓內(nèi)核發(fā)送一幀數(shù)據(jù)給此主機(jī),內(nèi)核必須知道目的主機(jī)的物理地址才能發(fā)送數(shù)據(jù)。ARP協(xié)議的作用就是在于把邏輯地址變換成物理地址,也既是把32bit的IP地址變換成48bit的以太地址。
每一個(gè)主機(jī)都有一個(gè)ARP高速緩存,此緩存中記錄了最近一段時(shí)間內(nèi)其它IP地址與其MAC地址的對(duì)應(yīng)關(guān)系。如果本機(jī)想與某臺(tái)主機(jī)通信,則首先在ARP高速緩存中查找此臺(tái)主機(jī)的IP和MAC信息,如果存在,則直接利用此MAC地址構(gòu)造以太包;如果不存在,則向本網(wǎng)絡(luò)上每一個(gè)主機(jī)廣播一個(gè)ARP請(qǐng)求包,其意義是"如果你有此IP地址,請(qǐng)告訴我你的MAC地址",目的主機(jī)收到此請(qǐng)求包后,發(fā)送一個(gè)ARP響應(yīng)包,本機(jī)收到此響應(yīng)包后,把相關(guān)信息記錄在ARP高速緩存中,以下的步驟同上。
可以看出,ARP協(xié)議是有缺點(diǎn)的,第三方主機(jī)可以構(gòu)造一個(gè)ARP欺騙包,而源主機(jī)卻無(wú)法分辨真假。
5. ARP欺騙原理
假設(shè)B(2.2.2.2)要與A(1.1.1.1)通信,且B的ARP高速緩存中沒(méi)有關(guān)于A的MAC信息,則B發(fā)出ARP請(qǐng)求包。
此時(shí),B的ARP高速緩存中關(guān)于A的記錄為(1.1.1.1 <-- --> 04:04:04),則B向A發(fā)IP包實(shí)際上是發(fā)到我的主機(jī)(4.4.4.4,04:04:04)。同理,如果我進(jìn)一步欺騙A,讓A的ARP高速緩存中關(guān)于B的記錄為(2.2.2.2 <-- --> 04:04:04), 則A向B發(fā)IP包實(shí)際上也是發(fā)到我的主機(jī)(4.4.4.4,04:04:04)。最后,我讓本機(jī)打開(kāi)數(shù)據(jù)包轉(zhuǎn)發(fā),也既是充當(dāng)路由器,則A,B之間能正常通信,但我能全部捕獲到相關(guān)數(shù)據(jù)。
以上討論的是欺騙兩臺(tái)主機(jī),如果我能讓局域網(wǎng)中每一臺(tái)主機(jī)的ARP高速緩存中關(guān)于其它任意一個(gè)主機(jī)所對(duì)應(yīng)的MAC地址都為我的MAC地址(04:04:04:04),則本局域網(wǎng)中所有數(shù)據(jù)包我都能捕獲到!
6. 程序設(shè)計(jì)思路
使用到的函數(shù)包
libpcap : 捕獲ARP數(shù)據(jù)包。
libnet : 獲得本機(jī)的MAC地址和IP地址;構(gòu)造和發(fā)送ARP欺騙包。
這兩個(gè)的函數(shù)包的使用在網(wǎng)上資料很多,本文中不介紹。
主要數(shù)據(jù)結(jié)構(gòu)
程序中有兩個(gè)全局變量,MYIP代表本機(jī)的IP地址,MYMAC代表本機(jī)的MAC地址。
程序中維護(hù)一個(gè)存放主機(jī)信息的鏈表:
typedef struct host HOST;
struct host
{
unsigned long ip; // IP地址
unsigned char mac[6]; // MAC地址
int mac_flag; // 0:MAC為空,1:MAC不為空
HOST * next;
};
#p#掌握本局域網(wǎng)中每一臺(tái)主機(jī)的IP地址和MAC地址信息。
利用libpcap捕獲網(wǎng)絡(luò)中的ARP請(qǐng)求/應(yīng)答包,最大限度的提取相關(guān)信息。如在第五節(jié)中的B對(duì)A的ARP請(qǐng)求包,我們可以提取出關(guān)于B的完整信息(2.2.2.2,02:02:02),也獲得了關(guān)于A的部分信息(1.1.1.1,null)。在知道網(wǎng)絡(luò)中有主機(jī)A的情況下,我們可以構(gòu)造并發(fā)送對(duì)A的ARP請(qǐng)求包,捕獲A的ARP應(yīng)答包,從而完整掌握A的信息。同理,我們也可以捕獲TCP/UDP等數(shù)據(jù)包,從中提取信息。
創(chuàng)建一個(gè)向鏈表增加主機(jī)信息的函數(shù):add_host(ip,mac), 每收到一個(gè)ARP請(qǐng)求/應(yīng)答包,都執(zhí)行add_host( )兩次:add_host(發(fā)送端IP,發(fā)送端MAC),add_host(目的端IP,目的端MAC)。
在收到ARP應(yīng)答包時(shí),首先檢查發(fā)送端的IP和MAC,如果IP不是自己的,但MAC是自己的,則說(shuō)明此應(yīng)答包是本機(jī)構(gòu)造的ARP欺騙包,程序忽略。
對(duì)于正常的ARP請(qǐng)求包和應(yīng)答包,add_host(ip, mac )中IP或MAC只要有一個(gè)是自己的(ip == MYIP || mac ==MYMAC),則程序忽略。顯然,沒(méi)有必要自己欺騙自己。
add_host(ip,mac)遍歷主機(jī)鏈表,如果IP存在,且MAC不空,則把MAC地址寫入;如果不存在,則增加一個(gè)HOST節(jié)點(diǎn),寫入IP地址,如果MAC不空,則也把MAC地址寫入。 注意到這樣一個(gè)情況:在ARP請(qǐng)求包中,目的MAC地址是沒(méi)有意義的,所以我們只寫入IP地址,而MAC地址用NULL來(lái)表示。這是我們收集網(wǎng)絡(luò)拓樸結(jié)構(gòu)的一種被動(dòng)方法。
函數(shù)add_host( )邏輯設(shè)計(jì)MYIP = IP(d),MYMAC = MAC(d)
代碼如下:
void add_host(u_long ip, u_char * mac)
{
HOST * new = NULL;
HOST * cur = NULL;
if( (ip == MYIP) || (mac && mac_equal(mac, MYMAC)) )
return;
//遍歷鏈表查詢IP地址
for(cur = head; cur; cur = cur->next)
{
if( ip == cur->ip )
{
if( mac ) // MAC地址不空,則寫入
{
memcpy(cur->mac, mac, ETHER_ADDR_LEN);
cur->mac_flag = 1;
}
return;
}
}
if(cur == NULL) // 鏈表中沒(méi)有此IP地址
{
new = (HOST *)malloc(sizeof(HOST));
new->ip = ip;
if( mac )
{
memcpy(new->mac, mac, ETHER_ADDR_LEN);
new->mac_flag = 1;
}
else
new->mac_flag = 0;
new->next = NULL;
if(! head) // 把新節(jié)點(diǎn)加入鏈表
{
head = new;
tail = new;
}
else
{
tail->next = new;
tail = new;
}
}
return;
}
周期性的向局域網(wǎng)中每一臺(tái)主機(jī)發(fā)送ARP欺騙包。
創(chuàng)建一個(gè)發(fā)送ARP欺騙包的函數(shù)send_fake_arp_packet(),遍歷主機(jī)鏈表的每一個(gè)IP地址,如果此IP地址的MAC地址已知,則遍歷主機(jī)鏈表中其它IP地址,以其它IP地址和本機(jī)的MAC地址為發(fā)送端,以選中的IP地址和MAC地址為目的端,構(gòu)造并發(fā)送ARP應(yīng)答欺騙包;如果此IP地址的MAC地址未知,則以本機(jī)IP地址和MAC地址為發(fā)送端,以選中的IP地址為目的端,構(gòu)造并發(fā)送正常的ARP請(qǐng)求包。注意,這是我們收集網(wǎng)絡(luò)拓樸結(jié)構(gòu)的一種主動(dòng)方法。
【編輯推薦】