Python黑帽第三篇文章將分享網絡掃描基礎知識,編程實現IP及埠掃描器、實現多線程C段掃描器。本文參考了《Python絕技》書籍和i春秋ADO老師的課程內容,這裡真心推薦大家去學習ichunqiu課程,同時也結合作者的編程經驗進行講解。希望這篇基礎文章對您有所幫助,更希望大家提高安全意識,也歡迎大家討論。
娜璋AI安全之家於2020年8月18日開通,將專注於Python和安全技術,主要分享Web滲透、系統安全、CVE復現、威脅情報分析、人工智慧、大數據分析、惡意代碼檢測等文章。真心想把自己近十年的所學所做所感分享出來,與大家一起進步。
聲明:本人堅決反對利用教學方法進行惡意攻擊的行為,一切錯誤的行為必將受到嚴懲,綠色網絡需要我們共同維護,更推薦大家了解技術背後的原理,更好地進行安全防護。雖然作者是一名安全小白,但會保證每一篇文章都會很用心地撰寫,希望這些基礎性文章對你有所幫助,在安全路上一起前行。
文章目錄
一.Python多線程
二.編程實現ping掃描
三.檢測IP存活地址
四.編程實現埠掃描器
五.多線程+Queue實現C段掃描
一.Python多線程1.進程和線程進程:是程序的一次執行,每個進程都有自己的地址空間、內存、數據棧及其他記錄運行軌跡的輔助數據。
線程:所有的線程都運行在同一個進程當中,共享相同的運行環境。線程有開始、順序執行和結束三個部分。
由於單線程效率低,程序中往往要引入多線程編程。計算機的核心是CPU,它承擔了所有的計算任務,它就像一座工廠,時刻運行著。假定工廠的電力有限,一次只能供給一個車間使用。也就是說,一個車間開工的時候,其他車間都必須停工。背後的含義就是,單個CPU一次只能運行一個任務。
進程就好比工廠的車間,它代表CPU所能處理的單個任務。任一時刻,CPU總是運行一個進程,其他進程處於非運行狀態。一個車間裡,可以有很多工人。他們協同完成一個任務。線程就好比車間裡的工人,一個進程可以包括多個線程。
2.thread模塊Python thread模塊可以調用下述函數實現多線程開啟。它將產生一個新線程,在新的線程中用指定的參數和可選的kwargs來調用這個函數。
注意:使用這個方法時,一定要加time.sleep()函數,否則每個線程都可能不執行。此方法還有一個缺點,遇到較複雜的問題時,線程數不易控制。
輸出結果如下圖所示:
3.threading模塊thread模塊存在一些缺點,尤其是線程數不能被控制。下面使用threading解決線程數可控制的問題。
輸出結果如下圖所示,三個線程同時發生。
多線程threading方法能夠控制線程數,例如想寫成requests模塊,獲取網站的status_code狀態碼。
輸出結果如下圖所示:
二.編程實現ping掃描上述代碼簡單講解了thread和threading模塊的多線程使用。但實際應用中有什麼用呢?我們可以通過它對所有C段的地址進行掃描,ping探測其是否存活,代碼如下。
如果輸入的ip地址為本機127.0.0.1,則輸出正常連通結果,如下所示。
如果輸入的ip地址為本機220.0.0.1,則提示超時,如下圖所示。
接著思考:如何對一個C段網址進行ping探測呢?
基本思路是設計一個循環,如果主機不存在,返回的是timeout;如果主機存在,則包含TTL字樣,這裡以TTL為判斷標準,從而判斷存活的數據。
輸出結果為「UP」。
三.檢測IP存活地址接下來我們嘗試檢測ichunqiu網站的ip地址存活情況。首先,調用ping命令檢測該網站的ip地址,即:117.23.xx.xx。(該部分參考i春秋ADO老師,再次感謝)
這裡將ping_check()函數設置一個傳遞參數,對應ip地址,對它進行探測;通過thread線程實現ip地址存活性探測,能探測到很多存活的主機。
輸出結果如下圖所示,其中IP值也被識別出來。
問題:在多線程編程中,幾個線程是同時啟動,所以輸出也是輸出在一行,那怎麼才能換行輸出呢?這裡使用系統輸出解決。
按行輸出結果,如下圖所示:
四.編程實現埠掃描器當我們拿到某個網站通過需要掃描它開放的埠,比如通過在線工具TScan掃描結果如下圖所示,開放了80、443、8080、7777等埠。那我們是否能通過Python編寫代碼實現呢?類似於NMAP的功能。
1.socket方法Python掃描埠可以通過socket通訊實現,通過建立TCP套接字,向埠發送TCP SYN數據包, 並等待TCP ACK相應,從而確定該埠是否開放。
完整代碼:
import optparseimport socketfrom socket import *
def connScan(tgtHost, tgtPort): try: conn = socket(AF_INET, SOCK_STREAM) conn.connect((tgtHost, tgtPort)) print(' [+] %d/tcp open ' % tgtPort) except Exception as err: print(' [-] %d/tcp closed' % tgtPort) finally: conn.close() def portScan(tgtHost, tgtPorts): try: tgtIP = gethostbyname(tgtHost) print(tgtIP) except: print("[-] Cannot resolve '%s': Unknown host" % tgtHost) try: tgtName = gethostbyaddr(tgtIP) print("[+] Scan Results for: " + tgtName[0]) except: print("[+] Scan Results for: " + tgtIP) setdefaulttimeout(1) for tgtPort in tgtPorts: print(" Scanning port " + tgtPort) connScan(tgtHost, int(tgtPort))
def main(): parser = optparse.OptionParser("usage%prog "+ \ "-H <target host> -p <target port>") parser.add_option('-H', dest='tgtHost', type='string', \ help='specify target host') parser.add_option('-p', dest='tgtPort', type='string', \ help='specify target port[s] separated by comma')
(options, args) = parser.parse_args() tgtHost = options.tgtHost tgtPorts = str(options.tgtPort).split(',') if (tgtHost==None) or (tgtPorts[0]==None): print('[-] You must specify a target host and port[s].')
portScan(tgtHost, tgtPorts) if __name__ == '__main__': main()該代碼使用了optparse參數定義,包括需要掃描的host和需要掃描的埠,運行結果如下圖所示,成功將開放的埠80、443、777、9080識別出來。
同樣,我們也可以簡單編寫上述代碼,自定義IP埠序列進行掃描。
輸出結果如下:
2.telnetlib方法接下來我們參考Dahlhin大神的文章,補充Python內置模塊telnetlib,它同樣可以完成埠檢測任務。
輸出結果同樣是80埠開放,我們可以擴大掃描的範圍,但其速度非常慢。
3.多線程掃描引入多線程threading模塊實現多線程掃描,此時我們僅顯示開放著的埠。
import telnetlibimport threadingimport queue
def get_ip_status(ip): server = telnetlib.Telnet() for port in range(20,10000): try: server.open(ip,port) print('{0} port {1} is open'.format(ip, port)) except Exception as err: pass finally: server.close() def check_open(q): try: while True: ip = q.get_nowait() get_ip_status(ip) except queue.Empty as e: pass
if __name__ == '__main__': host = ['210.40.xx.xx'] q = queue.Queue() for ip in host: q.put(ip) threads = [] for i in range(10): t = threading.Thread(target=check_open,args=(q,)) t.start() threads.append(t) for t in threads: t.join()五.Queue實現C段掃描雖然threading解決了線程數可控問題,但是面對複雜問題的時候,比如生產者和消費者問題,仍然不能很好地解決。
生產者-消費者問題和Queue模塊:
生產者和消費者問題
生產者生產貨物,將貨物放到隊列數據中,生產者在生產這些貨物時,它的時間是不確定的;當生存者將貨物交給消費者,消耗的時間也是不確定的;由於兩個時間都不確定,多線程編程存在一定問題。這裡引入Queue模塊解決該問題(Python3引入庫為queue,Python2為Queue)。
輸出結果如下所示:
生產者利用Queue將所有數據貨物按順序放入Queue,接著消費者依次取出Queue中的數據。接著實現C段掃描。
import threadingimport queueimport sysfrom subprocess import Popen, PIPE
class DoRun(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self._queue = queue
def run(self): while not self._queue.empty(): ip = self._queue.get() check_ping = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE, shell=True) data = check_ping.stdout.read() data = data.decode("gbk") if 'TTL' in data: sys.stdout.write(ip+' is UP.\n') def main(): threads = [] threads_count = 100 q = queue.Queue() for i in range(1, 255): q.put('210.40.81.' + str(i))
for i in range(threads_count): threads.append(DoRun(q))
for i in threads: i.start()
for i in threads: i.join()
if __name__ == '__main__': main()最終輸出結果如下圖所示,通過該代碼可以實現檢測某網站ip段的存活情況。
六.總結希望這篇文章對你有所幫助,這是Python黑帽第三篇博客,編程實現了IP及埠掃描器、實現多線程C段掃描器。後續作者也將繼續深入學習,製作一些常用的小工具供大家交流,當然你也可以和NMAP這類工具對比,但Python有時候能讓你集成更強大且自由的工具。
最後,真誠地感謝您關注「娜璋之家」公眾號,也希望我的文章能陪伴你成長,希望在技術路上不斷前行。文章如果對你有幫助、有感悟,就是對我最好的回報,且看且珍惜!再次感謝您的關注,也請幫忙宣傳下「娜璋之家」,哈哈~初來乍到,還請多多指教。
前文欣賞(連結可以點擊):
想家嘍 o(╥﹏╥)o
(By:娜璋AI安全之家2020-09-17 夜於武漢)
參考文獻:
《安全之路Web滲透技術及實戰案例解析》陳老師
《Python絕技運用Python成為黑客》Connor老師
https://www.bilibili.com/video/av29479068
https://www.bilibili.com/video/av57850011
https://www.cnblogs.com/dachenzi/p/8676104.html