前言
上篇文章主要寫了利用scapy實現ping掃描,這篇文章主要是利用scapy模塊實現內網ARP掃描
實現過程
上篇文章中介紹了通過scapy來偽造包,那么ARP包的偽造過程這里不再詳述,說一工具的簡單整體流程
1.首先,實現單個IP的ARP包的發送和接收
2.其次,實現多進程同時多個ARP包的發送和接收
整體的實現流程與上個腳本的實現較為相似
單進程ARP包
包的構造:
1
2
|
def scapy_arp_one(ip_address, queue = None ): Packet = Ether(dst = 'FF:FF:FF:FF:FF:FF' ) / ARP(op = 1 , hwdst = '00:00:00:00:00:00:' , pdst = ip_address) |
請求包的發送:
1
|
arp = srp(Packet, timeout = 0.2 , verbose = False ) |
返回包的接收
1
2
3
4
5
6
7
8
|
try : reply_list = arp[ 0 ].res if queue is None : return reply_list[ 0 ][ 1 ].getlayer(ARP).fields[ 'hwsrc' ] else : queue.out((ip_address, reply_list[ 0 ][ 1 ].getlayer(ARP).fields[ 'hwsrc' ])) except : return |
這里采用隊列的模式,主要是為了后面多進程同時發送做準備,涉及到ARP包的接受。這里我簡單描述一下ARP包接受的情況,當我們發送ARP廣播包的之后,我們就會接受到一個返回包。所以正確的情況就是,一個發送包一個接收包,一個發送包一個接收包,所以這里采用隊列的方式,一個一個IP地址的接收,并使用列表進行存儲,然后過濾ARP把內容,接收ARP中的硬件MAC地址
完整代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:Ameng, jlx-love.com from scapy. all import * import sys def scapy_arp_one(ip_address, queue = None ): Packet = Ether(dst = 'FF:FF:FF:FF:FF:FF' ) / ARP(op = 1 , hwdst = '00:00:00:00:00:00:' , pdst = ip_address) arp = srp(Packet, timeout = 0.2 , verbose = False ) try : reply_list = arp[ 0 ].res if queue is None : return reply_list[ 0 ][ 1 ].getlayer(ARP).fields[ 'hwsrc' ] else : queue.out((ip_address, reply_list[ 0 ][ 1 ].getlayer(ARP).fields[ 'hwsrc' ])) except : return if __name__ = = '__main__' : scapy_arp_one(sys.argv[ 1 ]) |
進一步完善
那么既然我們已經了解了使用ARP進行基本的發包和收包,那么我們接下來就來編寫一個能夠掃描整個網段的ARP檢測
理一下思路,首先,我們需要將ip地址編程一個網段中的所有ip,可以借助ipaddress模塊實現,其次我們知道我們接收響應包是一對的,所以我們可以從一對一對的響應包中接收我們需要的目標IP和源MAC地址,其次就是優化代碼,輸出結果,這里我不再采用sys模塊進行傳參,而是采用一個新的模塊optparse,具體使用方法可以百度百科
完整代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:Ameng, jlx-love.com import time from scapy. all import * import ipaddress import optparse def scapy_arp_scan(network, ifname): net = ipaddress.ip_network(network) ip_addr = [] for ip in net: ip = str (ip) ip_addr.append(ip) time.sleep( 1 ) Packet = Ether(dst = 'FF:FF:FF:FF:FF:FF' ) / ARP(op = 1 , hwdst = '00:00:00:00:00:00' , pdst = ip_addr) arp = srp(Packet, iface = ifname, timeout = 1 , verbose = False ) arp_list = arp[ 0 ].res IP_MAC_LIST = [] for n in range ( len (arp_list)): IP = arp_list[n][ 1 ][ 1 ].fields[ 'psrc' ] MAC = arp_list[n][ 1 ][ 1 ].fields[ 'hwsrc' ] IP_MAC = [IP, MAC] IP_MAC_LIST.append(IP_MAC) return IP_MAC_LIST if __name__ = = '__main__' : t1 = time.time() parser = optparse.OptionParser( '用法: python3 scapy_arp_scan.py --network 掃描網段 --ifname 網卡名稱' ) parser.add_option( '--network' , dest = 'network' , type = 'string' , help = '掃描網段' ) parser.add_option( '--ifname' , dest = 'ifname' , type = 'string' , help = '網卡名稱' ) (options, args) = parser.parse_args() network = options.network ifname = options.ifname if network = = None or ifname = = None : print (parser.usage) else : active_ip_mac = scapy_arp_scan(network, ifname) print ( '存活的IP地址及對應MAC:' ) for ip, mac in active_ip_mac: print (ip, mac) t2 = time.time() print ( '所用時間為:{}' . format ( int (t2 - t1))) |
運行結果
到此這篇關于python使用scapy模塊實現ARP掃描的過程的文章就介紹到這了,更多相關python實現ARP掃描內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://www.cnblogs.com/Jleixin/p/14300063.html