您好,登錄后才能下訂單哦!
怎么在python中利用scapy模塊實現一個ping掃描功能?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
1.首先我們應該編寫出能夠像單個IP發送ICMP包并接受回包的代碼
2.其次我們應該開啟多進程,從而讓該腳本可以快速掃描整個網段的主機存活情況
單進程發包
首先我們需要導入scapy模塊,這里要強調一下,scapy的v2版本的導入與別的模塊導入方式不同,需要特殊的書寫方式,否則scapy模塊中的某些功能將無法使用
from scapy.all import * from random import randint
接下來需要構造我們的包,即我們要發送的ICMP包,首先了解一下scapy包的偽造
對于scapy我們可以直接輸入scapy進入一個交互模式,其實這個交互模式本質也還是python,我們來看一下包
讀者可以看看我構造的這個包,我寫了三個協議層,第一寫其實是mac地址,如果我們只輸入Ether,那么就是默認的結果,這里的mac就是默認廣播形式,第二個我寫的是IP,也就是IP層的設置,可以發現其中的一些已經填寫了默認值,我們要設置的其實主要就的dst,即目的地址,當然其他的想改一下也是可以的,比如說把ttl生存周期改成128,這也是沒毛病的,第三個我寫的是TCP,即我發送的包是TCP包,其中也有一些默認值,我們看到有個window,這個其實就是程序的進程號。
那么既然我們是ping包,我們就使用ICMP包,那么我們來看一下ICMP包
看到ICMP的值更少一些,其中type表示這個包是請求包還是回應包。
那我們既然知道如何構造包了,那就動手構造一個
def scapy_ping_one(host): id_ip = randint(1, 65535) id_ping = randint(1, 65535) seq_ping = randint(1, 65535) packet = IP(dst=host, ttl=128, id=id_ip) / ICMP(id=id_ping, seq=seq_ping) / b'I am Ameng'
這里我設置的id號其實不設置也可以,這個就是標識包的信息,后面的字節流也可以不填寫,不影響結果
既然構造完了,那么我們就要發送,如何發送呢?這就用到了scapy中的一個函數sr
sr() 函數是用來發送數據包和接收應答。該函數返回一對數據包及其應答,還有無應答的數據包。 sr1() 函數是一種變體,用來返回一個應答數據包。發送的數據包必須是第3層報文(IP,ARP等)。 srp() 則是使用第2層報文(以太網,802.3等)
這里使用sr1()
ping = sr1(packet, timeout=0.2, verbose=False)
介紹一下參數,其實看名字前兩個沒什么問題,我這里主要說一下第三個參數,第三個參數的意思是說關閉詳細信息,因為我們只看結果,這樣界面更整潔
到這里發送單個包并接受單個包的ping代碼已經實現,整體代碼如下:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:Ameng jlx-love.com from scapy.all import * from random import randint def scapy_ping_one(host): id_ip = randint(1, 65535) id_ping = randint(1, 65535) seq_ping = randint(1, 65535) packet = IP(dst=host, ttl=128, id=id_ip) / ICMP(id=id_ping, seq=seq_ping) / b'I am Ameng' ping = sr1(packet, timeout=0.2, verbose=False) if ping: os._exit(3) if __name__ == '__main__': scapy_ping_one(sys.argv[1])
這里主要是將單進程的代碼實現多進程,那么我們什么時候會用到多進程呢?我們一般都是判斷一個網段有哪些主機存活,所以我們一般的輸入格式都是這樣子的,比如:192.168.10.0/24,所以我們首先需要將用戶的這個輸入變成一個這個網段的各個地址,這里用到ipaddress模塊,可以自動實現這個功能
其次我們需要開啟多個進程來同時進行不同ip地址的ping檢測,所以我們引入multiprocessing模塊,開啟多個進程。
代碼如下:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:Ameng jlx-love.com import time import multiprocessing from scapy_ping_one import scapy_ping_one from scapy.all import * import ipaddress def scapy_ping_scan(network): net = ipaddress.ip_network(network) ip_processes = {} for ip in net: ip_addr = str(ip) ping_one = multiprocessing.Process(target = scapy_ping_one, args = (ip_addr,)) ping_one.start() ip_processes[ip_addr] = ping_one ip_list = [] for ip, process in ip_processes.items(): if process.exitcode == 3: ip_list.append(ip) else: process.terminate() return sorted(ip_list) if __name__ == '__main__': import time t1 = time.time() active_ip = scapy_ping_scan(sys.argv[1]) print('存活的ip地址:') for ip in active_ip: print(ip) t2 = time.time() print('所用時間為:{}s'.format(int(t2 - t1)))
到此,一個簡單的ping掃描即可實現
運行結果
看完上述內容,你們掌握怎么在python中利用scapy模塊實現一個ping掃描功能的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。