tcp/ip協議學習 第四章 ARP:地址解析協議

派猴子來的救兵html

 

關於ARP的RFC文檔在此!python

ARP幹嗎的

曾經有段時間, 六七年前了吧. 本科的時候, 流行了一陣子ARP病毒攻擊, 致使整個局域網都不能上網了. 當時只據說這個東西防不住, 只要有一我的中毒, 就致使全部人上不了網. 如今也終於知道這是怎麼回事了, 也能手工讓某個同窗上不了網了, 咳咳.ubuntu

你們應該也都知道ARP是幹嗎的, 我再囉嗦一下.. 好比我訪問了百度, 百度回了包給我, 百度只知道個人IP是什麼,不知道個人MAC地址. 這個包到網關的時候, IP這一層再把數據交給下一層的鏈路層, 鏈路層不知道IP是什麼東西的, 它只認MAC地址. 因此就須要把IP轉成MAC地址, ARP請求就是作這個的.windows

就是說, 我能夠經過這個協議廣播問一下全部機器 , 誰的IP是XXX.XXX.XXX.XXX, 請把你的MAC地址告訴我. 這個IP是XXX.XXX.XXX.XXX的機器收到請求以後, 就會告訴我, XXX.XXX.XXX.XXX的MAC地址是啥啥啥.app

不幸這個是基於互相信任的, 理論上你們都會相信別人說的是正確的. 可是, 我能夠撒謊說, XXX.XXX.XXX.XXX是我, 個人MAC是啥啥啥. 而後原本應該到 XXX.XXX.XXX.XXX那裏的數據包就到我這裏來了. XXX.XXX.XXX.XXX不單單是斷網了, 我還能竊聽他的數據.socket

協議格式

要想僞造, 啊,不, 發送一個ARP請求或者應答, 必定要了解協議格式. 從RFC文件抄了一份.tcp

To communicate mappings from <protocol, address> pairs to 48.bit
Ethernet addresses, a packet format that embodies the Address
Resolution protocol is needed.  The format of the packet follows.

    Ethernet transmission layer (not necessarily accessible to
         the user):
        48.bit: Ethernet address of destination
        48.bit: Ethernet address of sender
        16.bit: Protocol type = ether_type$ADDRESS_RESOLUTION
    Ethernet packet data:
        16.bit: (ar$hrd) Hardware address space (e.g., Ethernet,
                         Packet Radio Net.)
        16.bit: (ar$pro) Protocol address space.  For Ethernet
                         hardware, this is from the set of type
                         fields ether_typ$<protocol>.
         8.bit: (ar$hln) byte length of each hardware address
         8.bit: (ar$pln) byte length of each protocol address
        16.bit: (ar$op)  opcode (ares_op$REQUEST | ares_op$REPLY)
        nbytes: (ar$sha) Hardware address of sender of this
                         packet, n from the ar$hln field.
        mbytes: (ar$spa) Protocol address of sender of this
                         packet, m from the ar$pln field.
        nbytes: (ar$tha) Hardware address of target of this
                         packet (if known).
        mbytes: (ar$tpa) Protocol address of target.

這個仍是TCP/IP協議詳解書裏面的圖好看一些, 且等我截個圖來, 呃,截歪了. arp協議,截取自是TCP/IP協議詳解this

其實裏面有些值, 像」硬件地址長度」什麼的, 是個變量, 後面的」發送端以太網地址」就是根據這個而變化 .就咱們目前的應用和環境來講, 拿這個圖就能夠啦.
這裏的長度單位是字節, 不是上一篇IP協議裏面的bit了.spa

詳細解釋我也copy一下吧. 也是出自TCP/IP協議詳解一書.設計

以太網報頭中的前兩個字段是以太網的源地址和目的地址。目的地址爲全 1的特殊地址是 廣播地址。電纜上的全部以太網接口都要接收廣播的數據幀。

兩個字節長的以太網幀類型表示後面數據的類型。對於 ARP請求或應答來講,該字段的 值爲0x0806。

形容詞hardware(硬件)和protocol(協議)用來描述 ARP分組中的各個字段。例如,一個 ARP 請求分組詢問協議地址(這裏是 IP地址)對應的硬件地址(這裏是以太網地址)。

硬件類型字段表示硬件地址的類型。它的值爲 1即表示以太網地址。協議類型字段表示要 映射的協議地址類型。它的值爲 0x0800即表示 IP地址。它的值與包含 IP數據報的以太網數據 幀中的類型字段的值相同,這是有意設計的(參見圖 2-1)。

接下來的兩個 1字節的字段,硬件地址長度和協議地址長度分別指出硬件地址和協議地址 的長度,以字節爲單位。對於以太網上 IP地址的 ARP請求或應答來講,它們的值分別爲 6和4。 操做字段指出四種操做類型,它們是 ARP請求(值

(值爲3)和RARP應答(值爲4)(咱們在第5章討論RARP)。這個字段必需的,由於 ARP請求 和ARP應答的幀類型字段值是相同的。

接下來的四個字段是發送端的硬件地址(在本例中是以太網地址)、發送端的協議地址 (IP地址)、目的端的硬件地址和目的端的協議地址。注意,這裏有一些重複信息:在以太網的數據幀報頭中和 ARP請求數據幀中都有發送端的硬件地址。

對於一個 ARP請求來講,除目的端硬件地址外的全部其餘的字段都有填充值。當系統收到一份目的端爲本機的 ARP請求報文後,它就把硬件地址填進去,而後用兩個目的端地址分 別替換兩個發送端地址,並把操做字段置爲 2,最後把它發送回去。

來段程序吧

其它也沒啥好說的了, 先來段程序吧.

廣播一個ARP請求, 問一下網關的MAC地址是多少. 運行環境是ubuntu12.04. osx上面是不行的. 聽說windows也不行. 搜索了很久, 也不知道mac上面怎麼搞.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
廣播一個ARP請求, 問一下網關的MAC地址是多少.
運行環境是ubuntu12.04.
osx上面是不行的. 聽說windows也不行. 搜索了很久, 也不知道mac上面怎麼搞.
'''

import socket
import struct


def main():
    st = struct.Struct('!6s 6s h h h b b h 6s 4s 6s 4s')

    GATEWAY = '192.168.1.1'
    MYIP = '192.168.1.8'
    MYMAC = '20:c9:d0:88:96:3f'

    dst_ethernet_addr = ''.join(
        [chr
         (int(e, 16))
         for e in 'FF:FF:FF:FF:FF:FF'.split(':')])
    protocol_type = 0x0806
    hw_addr_space = 1
    protocol_addr_space = 0x800
    hw_addr_length = 6
    protocol_addr_length = 4
    op = 1
    my_mac = ''.join([chr(int(e, 16)) for e in MYMAC.split(':')])
    my_ip = socket.inet_aton(MYIP)
    target_hw_addr = ''.join(
        [chr
         (int(e, 16))
         for e in '00:00:00:00:00:00'.split(':')])
    des_ip = socket.inet_aton(GATEWAY)
    data = (
        dst_ethernet_addr,
        my_mac,
        protocol_type,
        hw_addr_space,
        protocol_addr_space,
        hw_addr_length,
        protocol_addr_length,
        op,
        my_mac,
        my_ip,
        target_hw_addr,
        des_ip,
        )
    packed_data = st.pack(*data)

    s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.SOCK_RAW)
    s.bind(('eth0', socket.SOCK_RAW))

    # 下面這樣也行, 不知道區別.
    #http://sock-raw.org/papers/sock_raw 這個應該能夠參考
    #s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
    #s.bind(('eth0',0))

    r = s.send(packed_data)
    print r
    return

if __name__ == '__main__':
    main()

抓包結果, 這裏已經忽略了以太網首部的14個字節. 是從上圖中的"硬件類型"開始的.

% sudo tcpdump -nn -vvv -x -c1 arp   
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
19:28:43.209235 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.1.1 tell 192.168.1.8, length 28
    0x0000:  0001 0800 0604 0001 20c9 d088 963f c0a8
    0x0010:  0108 0000 0000 0000 c0a8 0101
1 packet captured
1 packet received by filter
0 packets dropped by kernel

ARP攻擊

上面的代碼簡單改一下就能夠作ARP攻擊了.

對網關作一個ARP應答. op改成2, 表明ARP應答. 而後把 "以太網源地址"和"發送端以太網地址"都寫本身的. IP地址寫要攻擊的人. OVER

相關文章
相關標籤/搜索