Python3實現TCP埠掃描器

本文來自 高海峰對 玄魂工作室 的投稿

作者:高海峰 QQ:543589796

在滲透測試的初步階段通常我們都需要對攻擊目標進行信息搜集,而埠掃描就是信息搜集中至關重要的一個步驟。通過埠掃描我們可以了解到目標主機都開放了哪些服務,甚至能根據服務猜測可能存在某些漏洞。 TCP埠掃描一般分為以下幾種類型:

  1. TCP connect掃描:也稱為全連接掃描,這種方式直接連接到目標埠,完成了TCP三次握手的過程,這種方式掃描結果比較準確,但速度比較慢而且可輕易被目標系統檢測到。
  2. TCP SYN掃描:也稱為半開放掃描,這種方式將發送一個SYN包,啟動一個TCP會話,並等待目標響應數據包。如果收到的是一個RST包,則表明埠是關閉的,而如果收到的是一個SYN/ACK包,則表示相應的埠是打開的。
  3. Tcp FIN掃描:這種方式發送一個表示拆除一個活動的TCP連接的FIN包,讓對方關閉連接。如果收到了一個RST包,則表明相應的埠是關閉的。
  4. TCP XMAS掃描:這種方式通過發送PSH、FIN、URG、和TCP標誌位被設為1的數據包。如果收到了一個RST包,則表明相應的埠是關閉的。

下面我們將使用Python3 實現TCP全連接埠掃描器,下面進入編程環節。

編碼實戰

全連接掃描方式的核心就是針對不同埠進行TCP連接,根據是否連接成功來判斷埠是否打開,現在我們來實現一個最簡單的埠掃描器:

#!/usr/bin/python3# -*- coding: utf-8 -*-from socket import *def portScanner(host,port): try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) print("[+] %d open" % port) s.close() except: print("[-] %d close" % port)def main(): setdefaulttimeout(1) for p in range(1,1024): portScanner("192.168.0.100",p)if __name__ == "__main__": main()

這段代碼的核心就是portScanner函數,從其中的內容可以看出,只是進行了簡單的TCP連接,如果連接成功則判斷為埠打開,否則視為關閉。 我們來看一下運行結果:

這樣的掃描看起來效率太低了,實際也確實很慢,因為我們設置了默認的超時時間為1秒,這要是掃描10000個埠,豈不是要等到花都謝了? 最簡單的辦法就是用多線程來提高效率,雖然python的多線程有點太弱了,不過至少可以利用我們等待的時間去干點別的。另外之前掃描的埠比較多, 顯示的信息我們看起來不方便,這次我們只顯示我們關心的打開的埠,並將打開埠的數量在掃描結束的時候顯示出來。

#!/usr/bin/python3# -*- coding: utf-8 -*-from socket import *import threadinglock = threading.Lock()openNum = 0threads = []def portScanner(host,port): global openNum try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) lock.acquire() openNum+=1 print("[+] %d open" % port) lock.release() s.close() except: passdef main(): setdefaulttimeout(1) for p in range(1,1024): t = threading.Thread(target=portScanner,args=("192.168.0.100",p)) threads.append(t) t.start() for t in threads: t.join() print("[*] The scan is complete!") print("[*] A total of %d open port " % (openNum))if __name__ == "__main__": main()

運行看一下效果,如下圖:

這下看起來是不是方便多了?至此效率上的問題解決了,現在我們還需要為掃描器增加一個 參數解析的功能,這樣才能看起來像個樣子,總不能每次都改代碼來修改掃描目標和埠吧!

參數解析我們將用python3自帶的標準模塊argparse,這樣我們就省去了自己解析字元串的麻煩! 下面來看代碼:

#!/usr/bin/python3# -*- coding: utf-8 -*-from socket import *import threadingimport argparselock = threading.Lock()openNum = 0threads = []def portScanner(host,port): global openNum try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) lock.acquire() openNum+=1 print("[+] %d open" % port) lock.release() s.close() except: passdef main(): p = argparse.ArgumentParser(description="Port scanner!.") p.add_argument("-H", dest="hosts", type=str) args = p.parse_args() hostList = args.hosts.split(",") setdefaulttimeout(1) for host in hostList: print("Scanning the host:%s......" % (host)) for p in range(1,1024): t = threading.Thread(target=portScanner,args=(host,p)) threads.append(t) t.start() for t in threads: t.join() print("[*] The host:%s scan is complete!" % (host)) print("[*] A total of %d open port " % (openNum))if __name__ == "__main__": main()

看一下運行效果,如下圖:

至此我們的埠掃描器就基本完成了,雖然功能比較簡單,旨在表達埠掃描器的基本實現思路! 至於更詳細的功能可以基於這個基本結構來逐步完善!

小結

本節主要講解了Python3實現一個簡單的埠掃描器的過程,本次實驗採用了Tcp全連接的方式,不斷嘗試連接主機的埠來判斷埠的開放情況,雖然存在一些缺點, 不過這種方式最適合初學者學習,至於更複雜的方式以後學習起來也不會很難。想舉一反三的朋友可以根據協議和埠的對照關係來完成掃描時同時輸出協議, 這樣看起來會更好一些,至於更詳細的功能就留給大家做練習了!

查看完整系列教程,請關注我的微信訂閱號(xuanhun521,下方二維碼),回復「python」。問題討論請加qq群:Hacking (1群):303242737 Hacking (2群):147098303。

點擊打開二維碼

玄魂工作室-精彩不斷


推薦閱讀:

使用文本挖掘實現站點個性化推薦
Python黑帽編程 3.4 跨越VLAN
【記錄】Python批量修改文件名
Python騷操作 | 用python爆破某會員網站

TAG:Python | 网络编程 | 玄魂工作室 |