欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python如何使用Scapy實現(xiàn)端口探測

 更新時間:2023年10月26日 07:46:16   作者:lyshark  
Scapy 是一款使用純Python編寫的跨平臺網(wǎng)絡(luò)數(shù)據(jù)包操控工具,它能夠處理和嗅探各種網(wǎng)絡(luò)數(shù)據(jù)包,本文主要介紹了Python如何使用使用Scapy實現(xiàn)端口探測,有需要的可以參考下

Scapy 是一款使用純Python編寫的跨平臺網(wǎng)絡(luò)數(shù)據(jù)包操控工具,它能夠處理和嗅探各種網(wǎng)絡(luò)數(shù)據(jù)包。能夠很容易的創(chuàng)建,發(fā)送,捕獲,分析和操作網(wǎng)絡(luò)數(shù)據(jù)包,包括TCP,UDP,ICMP等協(xié)議,此外它還提供了許多有用的功能,例如嗅探網(wǎng)絡(luò)流量,創(chuàng)建自定義協(xié)議和攻擊網(wǎng)絡(luò)的安全測試工具。使用Scapy可以通過Python腳本編寫自定義網(wǎng)絡(luò)協(xié)議和攻擊工具,這使得網(wǎng)絡(luò)安全測試變得更加高效和精確。

讀者可自行安裝Scapy第三方庫,其次該工具依賴于PCAP接口,讀者可自行安裝npcap驅(qū)動工具包,具體的安裝細節(jié)此處就不再贅述。

安裝Scapy工具:pip install PyX matplotlib scapy

安裝Npcap驅(qū)動:https://npcap.com/dist/

1.端口掃描基礎(chǔ)

網(wǎng)絡(luò)端口掃描用于檢測目標主機上開放的網(wǎng)絡(luò)端口。端口掃描可以幫助安全專業(yè)人員識別存在的網(wǎng)絡(luò)漏洞,以及識別網(wǎng)絡(luò)上的服務(wù)和應(yīng)用程序。在進行端口掃描時,掃描程序會發(fā)送特定的網(wǎng)絡(luò)數(shù)據(jù)包,嘗試與目標主機的每個端口進行通信。如果端口處于打開狀態(tài),則掃描程序?qū)⒛軌虺晒⑦B接。否則,掃描程序?qū)⑹盏揭粭l錯誤消息,表明目標主機上的該端口未開放。

常見的端口掃描技術(shù)包括TCP連接掃描、SYN掃描、UDP掃描和FIN掃描等。其中,TCP連接掃描是最常用的一種技術(shù),它通過建立TCP連接來識別開放的端口。SYN掃描則利用TCP協(xié)議的三次握手過程來判斷端口是否開放,而UDP掃描則用于識別UDP端口是否開放。FIN掃描則是利用TCP FIN數(shù)據(jù)包來探測目標主機上的端口是否處于開放狀態(tài)。

在動手開發(fā)掃描軟件之前,我們還是要重點復(fù)習(xí)一下協(xié)議相關(guān)的內(nèi)容,這樣才能真正理解不同端口掃描方式的原理,首先是TCP協(xié)議,TCP(Transmission Control Protocol)傳輸控制協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的傳輸層協(xié)議。下圖是TCP報文格式:

TCP報文分為頭部和數(shù)據(jù)兩部分,其中頭部包含以下字段:

  • 源端口(Source Port):占用2個字節(jié),表示發(fā)送端使用的端口號,范圍是0-65535。
  • 目的端口(Destination Port):占用2個字節(jié),表示接收端使用的端口號,范圍是0-65535。
  • 序列號(Sequence Number):占用4個字節(jié),表示數(shù)據(jù)段中第一個字節(jié)的序號。TCP協(xié)議中采用序號對數(shù)據(jù)進行分段,從而實現(xiàn)可靠傳輸。
  • 確認號(Acknowledgement Number):占用4個字節(jié),表示期望收到的下一個字節(jié)的序號。TCP協(xié)議中采用確認號對接收到的數(shù)據(jù)進行確認,從而實現(xiàn)可靠傳輸。
  • 數(shù)據(jù)偏移(Data Offset):占用4個位,表示TCP頭部的長度。由于TCP頭部長度是可變的,該字段用于指示數(shù)據(jù)段從哪里開始。
  • 保留位(Reserved):占用6個位,保留用于將來的擴展。
  • 控制位(Flags):占用6個位,共有6個標志位,分別為URG、ACK、PSH、RST、SYN和FIN。其中,URG、ACK、PSH和RST標志的長度均為1位,SYN和FIN標志的長度為1位。
  • 窗口大?。╓indow Size):占用2個字節(jié),表示發(fā)送方可接受的字節(jié)數(shù)量,用于流量控制。
  • 校驗和(Checksum):占用2個字節(jié),用于檢驗數(shù)據(jù)的完整性。
  • 緊急指針(Urgent Pointer):占用2個字節(jié),表示該報文的緊急數(shù)據(jù)在數(shù)據(jù)段中的偏移量。
  • 選項(Options):可變長度,用于協(xié)商TCP參數(shù),如最大報文長度、時間戳等。

對于端口掃描來說我們需要重點關(guān)注控制位中所提到的6個標志位,這些標志是我們實現(xiàn)掃描的關(guān)鍵,如下是這些標志位的說明;

  • URG:緊急指針標志位,當URG=1時,表明緊急指針字段有效。它告訴系統(tǒng)中有緊急數(shù)據(jù),應(yīng)當盡快傳送,這時不會按照原來的排隊序列來傳送,而會將緊急數(shù)據(jù)插入到本報文段數(shù)據(jù)的最前面。
  • ACK:當ACK=1時,我們的確認序列號ack才有效,當ACK=0時,確認序號ack無效,在TCP協(xié)議中規(guī)定所有建立連接的ACK必須全部置為1。
  • PSH:當該標志位被設(shè)置時,表示TCP數(shù)據(jù)包需要立即發(fā)送給接收方,而無需等待緩沖區(qū)填滿。這個操作被稱為推送操作,即將緩沖區(qū)的數(shù)據(jù)立即推送給接收方。
  • RST:當RST=1時,表明TCP連接出現(xiàn)嚴重錯誤,此時必須釋放連接,之后重新連接,該標志又叫重置位。
  • SYN:同步序列號標志位,tcp三次握手中,第一次會將SYN=1,ACK=0,此時表示這是一個連接請求報文段,對方會將SYN=1,ACK=1,表示同意連接,連接完成之后將SYN=0。
  • FIN:在tcp四次揮手時第一次將FIN=1,表示此報文段的發(fā)送方數(shù)據(jù)已經(jīng)發(fā)送完畢,這是一個釋放鏈接的標志。

接著我們來具體看一下在TCP/IP協(xié)議中,TCP是如何采用三次握手四次揮手實現(xiàn)數(shù)據(jù)包的通信功能的,如下是一個簡單的通信流程圖;

(1) 第一次握手:建立連接時,客戶端A發(fā)送SYN包(SYN=j)到服務(wù)器B,以及初始序號X,保存在包頭的序列號(Sequence Number)字段里,并進入SYN_SEND狀態(tài),等待服務(wù)器B確認。

(2)第二次握手:服務(wù)器B收到SYN包,必須確認客戶A的SYN(ACK=j+1),同時自己也發(fā)送一個SYN包(SYN=k),即SYN+ACK包,此時服務(wù)器B進入SYN_RECV狀態(tài)。

(3) 第三次握手:客戶端A收到服務(wù)器B的SYN+ACK包,向服務(wù)器B發(fā)送確認包ACK(ACK=k+1),此包發(fā)送完畢,客戶端A和服務(wù)器B進入ESTABLISHED狀態(tài),完成三次握手。至此服務(wù)端與客戶端之間就可以傳輸數(shù)據(jù)了。

2.ICMP構(gòu)建與發(fā)送

首先我們先來構(gòu)建并實現(xiàn)一個ICMP數(shù)據(jù)包,在之前的文章中筆者已經(jīng)通過C語言實現(xiàn)了數(shù)據(jù)包的構(gòu)建,當然使用C語言構(gòu)建數(shù)據(jù)包是一件非常繁瑣的實現(xiàn),通過運用Scapy則可以使數(shù)據(jù)包的構(gòu)建變得很容易,ICMP數(shù)據(jù)包上層是IP頭部,所以在構(gòu)造數(shù)據(jù)包時應(yīng)先構(gòu)造IP包頭,然后再構(gòu)造ICMP包頭,如下我們先使用ls(IP)查詢一下IP包頭的結(jié)構(gòu)定義,然后再分別構(gòu)造參數(shù)。

>>> from scapy.all import *
>>> from random import randint
>>> import time
>>>
>>> uuid = randint(1,65534)
>>> ls(IP)                                                           # 查詢IP頭部定義
version    : BitField  (4 bits)                  = (4)
ihl        : BitField  (4 bits)                  = (None)
tos        : XByteField                          = (0)
len        : ShortField                          = (None)
id         : ShortField                          = (1)
flags      : FlagsField  (3 bits)                = (<Flag 0 ()>)
frag       : BitField  (13 bits)                 = (0)
ttl        : ByteField                           = (64)
proto      : ByteEnumField                       = (0)
chksum     : XShortField                         = (None)
src        : SourceIPField                       = (None)
dst        : DestIPField                         = (None)
options    : PacketListField                     = ([])
>>>
>>> ip_header = IP(dst="192.168.1.1",ttl=64,id=uuid)           # 構(gòu)造IP數(shù)據(jù)包頭
>>> ip_header.show()                                           # 輸出構(gòu)造好的包頭
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 64541
  flags     =
  frag      = 0
  ttl       = 64
  proto     = ip
  chksum    = None
  src       = 192.168.1.101
  dst       = 192.168.1.1
  \options   \

>>> ip_header.summary()
'192.168.1.101 > 192.168.1.1 ip'

上述代碼中我們已經(jīng)構(gòu)造了一個IP包頭,接著我們還需要構(gòu)造一個ICMP包頭,該包頭的構(gòu)造可以使用ICMP()并傳入兩個參數(shù),如下則是構(gòu)造好的一個ICMP包頭。

>>> ICMP()
<ICMP  |>
>>>
>>> icmp_header = ICMP(id=uuid, seq=uuid)
>>>
>>> icmp_header
<ICMP  id=0xfc1d seq=0xfc1d |>
>>> icmp_header.show()
###[ ICMP ]###
  type      = echo-request
  code      = 0
  chksum    = None
  id        = 0xfc1d
  seq       = 0xfc1d

接著我們需要將上述兩個包頭粘貼在一起,通過使用/將來給你這進行拼接,并在icmp_header后面增加我們所有發(fā)送的數(shù)據(jù)包字符串,最終將構(gòu)造好的數(shù)據(jù)包存儲至packet變量內(nèi),此時輸入packet.summary()即可查看構(gòu)造的數(shù)據(jù)包字符串。

>>> packet = ip_header / icmp_header / "hello lyshark"
>>>
>>> packet
<IP  id=64541 frag=0 ttl=64 proto=icmp dst=192.168.1.1 |<ICMP  id=0xfc1d seq=0xfc1d |<Raw  load='hello lyshark' |>>>
>>>
>>> packet.summary()
'IP / ICMP 192.168.1.101 > 192.168.1.1 echo-request 0 / Raw'
>>>

當我們構(gòu)造好一個數(shù)據(jù)包后,下一步則是需要將該數(shù)據(jù)包發(fā)送出去,對于發(fā)送數(shù)據(jù)包Scapy中提供了多種發(fā)送函數(shù),如下則是不同的幾種發(fā)包方式,當我們呢最常用的還是sr1()該函數(shù)用于發(fā)送數(shù)據(jù)包并只接受回顯數(shù)據(jù)。

  • send(pkt):發(fā)送三層數(shù)據(jù)包,但不會受到返回的結(jié)果
  • sr(pkt):發(fā)送三層數(shù)據(jù)包,返回兩個結(jié)果,分別是接收到響應(yīng)的數(shù)據(jù)包和未收到響應(yīng)的數(shù)據(jù)包
  • sr1(pkt):發(fā)送三層數(shù)據(jù)包,僅僅返回接收到響應(yīng)的數(shù)據(jù)包
  • sendp(pkt):發(fā)送二層數(shù)據(jù)包
  • srp(pkt):發(fā)送二層數(shù)據(jù)包,并等待響應(yīng)
  • srp1(pkt):發(fā)送第二層數(shù)據(jù)包,并返回響應(yīng)的數(shù)據(jù)包

此處我們就以sr1()函數(shù)作為演示目標,通過構(gòu)造數(shù)據(jù)包并調(diào)用sr1()將該數(shù)據(jù)包發(fā)送出去,并等待返回響應(yīng)數(shù)據(jù)到respon變量內(nèi),此時通過對該變量進行解析即可得到當前ICMP的狀態(tài)。

>>> respon = sr1(packet,timeout=3,verbose=0)
>>> respon
<IP  version=4 ihl=5 tos=0x0 len=41 id=26086 flags= frag=0 ttl=64 proto=icmp chksum=0x9137 src=192.168.1.1 dst=192.168.1.101 |<ICMP  type=echo-reply code=0 chksum=0x177d id=0xfc1d seq=0xfc1d |<Raw  load='hello lyshark' |<Padding  load='\x00\x00\x00\x00\x00' |>>>>
>>>
>>> respon[IP].src
'192.168.1.1'
>>>
>>> respon[IP].ttl
64
>>> respon.fields
{'options': [], 'version': 4, 'ihl': 5, 'tos': 0, 'len': 41, 'id': 26086, 'flags': <Flag 0 ()>, 'frag': 0, 'ttl': 64, 'proto': 1, 'chksum': 37175, 'src': '192.168.1.1', 'dst': '192.168.1.101'}

上述流程就是一個簡單的ICMP的探測過程,我們可以將這段代碼進行組合封裝實現(xiàn)ICMP_Ping函數(shù),該函數(shù)只需要傳入一個IP地址即可返回特定地址是否在線,同時我們使用ipaddress.ip_network則可生成一整個C段中的地址信息,并配合threading啟用多線程,則可實現(xiàn)一個簡單的主機存活探測工具,完整代碼如下所示;

from scapy.all import *
from random import randint
import time,ipaddress,threading
import argparse
import logging

def ICMP_Ping(addr):
    RandomID=randint(1,65534)
    packet = IP(dst=addr, ttl=64, id=RandomID) / ICMP(id=RandomID, seq=RandomID) / "hello lyshark"
    respon = sr1(packet,timeout=3,verbose=0)
    if respon:
        print("[+] 存活地址: {}".format(str(respon[IP].src)))

if __name__== "__main__":
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    #net = ipaddress.ip_network("192.168.1.0/24")
    parser = argparse.ArgumentParser()
    parser.add_argument("-a","--addr",dest="addr",help="指定一個IP地址或范圍")
    args = parser.parse_args()
    if args.addr:
        net = ipaddress.ip_network(str(args.addr))
        for item in net:
            t = threading.Thread(target=ICMP_Ping,args=(str(item),))
            t.start()
    else:
        parser.print_help()

讀者可自行運行上述程序片段,并傳入main.py -a 192.168.9.0/24表示掃描整個C段,并輸出存活主機列表,其中logging模塊則用于指定只有錯誤提示才會輸出,其他的警告忽略。掃描結(jié)果如下圖所示;

接著我們繼續(xù)實現(xiàn)路由追蹤功能,跟蹤路由原理是IP路由每經(jīng)過一個路由節(jié)點TTL值會減一,假設(shè)TTL值為0時數(shù)據(jù)包還沒有到達目標主機,那么該路由則會回復(fù)給目標主機一個數(shù)據(jù)包不可達,由此我們就可以獲取到目標主機的IP地址,我們首先構(gòu)造一個數(shù)據(jù)包,并設(shè)置TTL值為1,將該數(shù)據(jù)包發(fā)送出去即可看到回顯主機的IP信息。

>>> from scapy.all import *
>>> from random import randint
>>> import time
>>>
>>> RandomID=randint(1,65534)
>>> packet = IP(dst="104.193.88.77", ttl=1, id=RandomID) / ICMP(id=RandomID, seq=RandomID) / "hello"
>>> respon = sr1(packet,timeout=3,verbose=0)
>>>
>>> respon
<IP  version=4 ihl=5 tos=0xc0 len=61 id=14866 flags= frag=0 ttl=64 proto=icmp chksum=0xbc9a src=192.168.1.1 dst=192.168.1.2 |<ICMP  type=time-exceeded code=ttl-zero-during-transit chksum=0xf4ff reserved=0 length=0 unused=None |<IPerror  version=4 ihl=5 tos=0x0 len=33 id=49588 flags= frag=0 ttl=1 proto=icmp chksum=0x4f79 src=192.168.1.2 dst=104.193.88.77 |<ICMPerror  type=echo-request code=0 chksum=0x30c4 id=0xc1b4 seq=0xc1b4 |<Raw  load='hello' |>>>>>

關(guān)于如何實現(xiàn)路由跟蹤,具體來說一開始發(fā)送一個TTL1的數(shù)據(jù)包,這樣到達第一個路由器的時候就已經(jīng)超時了,第一個路由器就會返回一個ICMP通知,該通知包含了對端的IP地址,這樣就能夠記錄下所經(jīng)過的第一個路由器的地址。接著將TTL值加1,讓其能夠安全的通過第一個路由器,而第二個路由器的的處理過程會自動丟包,發(fā)通包超時通知,這樣記錄下第二個路由器IP,由此能夠一直進行下去,直到這個數(shù)據(jù)包到達目標主機,由此打印出全部經(jīng)過的路由器。

將上述跟蹤過程自動化,就可以完成數(shù)據(jù)包的跟蹤,其Python代碼如下所示。

from scapy.all import *
from random import randint
import time,ipaddress,threading
from optparse import OptionParser
import logging

def TraceRouteTTL(addr):
    for item in range(1,128):
        RandomID=randint(1,65534)
        packet = IP(dst=addr, ttl=item, id=RandomID) / ICMP(id=RandomID, seq=RandomID)
        respon = sr1(packet,timeout=3,verbose=0)
        if respon != None:
            ip_src = str(respon[IP].src)
            if ip_src != addr:
                print("[+] --> {}".format(str(respon[IP].src)))
            else:
                print("[+] --> {}".format(str(respon[IP].src)))
                return 1
        else:
            print("[-] --> TimeOut")
        time.sleep(1)

if __name__== "__main__":
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    parser = OptionParser()
    parser.add_option("-a","--addr",dest="addr",help="指定一個地址或范圍")
    (options,args) = parser.parse_args()
    if options.addr:
        TraceRouteTTL(str(options.addr))
    else:
        parser.print_help()

讀者可自行運行上述程序片段,并傳入main.py --addr 104.193.88.77表示跟蹤從本機到目標104.193.88.77主機所經(jīng)過的路由器地址信息,并將掃描結(jié)果輸出如下圖所示;

3.TCP全連接掃描

TCP Connect 掃描又叫做全連接掃描,它是一種常用的端口掃描技術(shù)。在這種掃描中,掃描程序向目標主機發(fā)送TCP連接請求包(SYN包),如果目標主機回應(yīng)了一個TCP連接確認包(SYN-ACK包),則說明該端口處于開放狀態(tài)。否則,如果目標主機回應(yīng)了一個TCP復(fù)位包(RST包)或者沒有任何響應(yīng),則說明該端口處于關(guān)閉狀態(tài)。這種掃描技術(shù)的優(yōu)點是準確性高,因為它可以在不建立實際連接的情況下確定目標主機的端口狀態(tài)。但是,缺點是這種掃描技術(shù)很容易被目標主機的防火墻或入侵檢測系統(tǒng)檢測到。

全連接掃描需要客戶端與服務(wù)器之間直接建立一次完整的握手,該方式掃描速度慢效率低,我們需要使用Scapy構(gòu)造完整的全連接來實現(xiàn)一次探測,在使用該工具包時讀者應(yīng)該注意工具包針對flags所代指的標識符RA/AR/SA含義,這些標志是Scapy框架中各種數(shù)據(jù)包的簡寫,此外針對數(shù)據(jù)包的定義有以下幾種;

  • F:FIN 結(jié)束,結(jié)束會話
  • S:SYN 同步,表示開始會話請求
  • R:RST 復(fù)位,中斷一個連接
  • P:PUSH 推送,數(shù)據(jù)包立即發(fā)送
  • A:ACK 應(yīng)答
  • U:URG 緊急
  • E:ECE 顯式擁塞提醒回應(yīng)
  • W:CWR 擁塞窗口減少

實現(xiàn)全鏈接掃描我們封裝并實現(xiàn)一個tcpScan()函數(shù),該函數(shù)接收兩個參數(shù)一個掃描目標地址,一個掃描端口列表,通過對數(shù)據(jù)包的收發(fā)判斷即可獲取特定主機開放狀態(tài);

from scapy.all import *
import argparse
import logging

def tcpScan(target,ports):
    for port in ports:
        # S 代表發(fā)送SYN報文
        send=sr1(IP(dst=target)/TCP(dport=port,flags="S"),timeout=2,verbose=0)
        if (send is None):
            continue
        # 如果是TCP數(shù)據(jù)包
        elif send.haslayer("TCP"):
            # 是否是 SYN+ACK 應(yīng)答
            if send["TCP"].flags == "SA":
                # 發(fā)送ACK+RST數(shù)據(jù)包完成三次握手
                send_1 = sr1(IP(dst=target) / TCP(dport=port, flags="AR"), timeout=2, verbose=0)
                print("[+] 掃描主機: %-13s 端口: %-5s 開放" %(target,port))
            elif send["TCP"].flags == "RA":
                print("[+] 掃描主機: %-13s 端口: %-5s 關(guān)閉" %(target,port))

if __name__ == "__main__":
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    # 使用方式: main.py -H 192.168.1.10 -p 80,8080,443,445
    parser = argparse.ArgumentParser()
    parser.add_argument("-H","--host",dest="host",help="輸入一個被攻擊主機IP地址")
    parser.add_argument("-p","--port",dest="port",help="輸入端口列表 [80,443,135]")
    args = parser.parse_args()
    if args.host and args.port:
        tcpScan(args.host,eval(args.port))
    else:
        parser.print_help()

運行上述代碼片段,并傳入59.110.117.109地址以及,端口80,8080,443,445程序?qū)⒁来螔呙柽@些端口,并輸出如下圖所示;

4.SYN半開放掃描

TCP SYN掃描又稱半開式掃描,該過程不會和服務(wù)端建立完整的連接,其原理是利用了TCP協(xié)議中的一個機制,即在TCP三次握手過程中,客戶端發(fā)送SYN包到服務(wù)端,服務(wù)端回應(yīng)SYN+ACK包給客戶端,最后客戶端回應(yīng)ACK包給服務(wù)端。如果服務(wù)端回應(yīng)了SYN+ACK包,說明該端口是開放的;如果服務(wù)端回應(yīng)了RST包,說明該端口是關(guān)閉的。

TCP SYN掃描的優(yōu)點是不會像TCP Connect掃描那樣建立完整的連接,因此不會留下大量的日志,可以有效地隱藏掃描行為。缺點是在掃描過程中會產(chǎn)生大量的半連接,容易被IDS/IPS等安全設(shè)備檢測到,而且可能會對目標主機造成負擔(dān)。

SYN掃描不會和服務(wù)端建立完整的連接,從而能夠在一定程度上提高掃描器的效率,該掃描方式在代碼實現(xiàn)上和全連接掃描區(qū)別不大,只是在結(jié)束到服務(wù)端響應(yīng)數(shù)據(jù)包之后直接發(fā)送RST包結(jié)束連接,上述代碼只需要進行簡單修改,將send_1處改為R標志即可;

from scapy.all import *
import argparse
import logging

def tcpSynScan(target,ports):
    for port in ports:
        # S 代表發(fā)送SYN報文
        send=sr1(IP(dst=target)/TCP(dport=port,flags="S"),timeout=2,verbose=0)
        if (send is None):
            continue
        # 如果是TCP數(shù)據(jù)包
        elif send.haslayer("TCP"):
            # 是否是 SYN+ACK 應(yīng)答
            if send["TCP"].flags == "SA":
                # 發(fā)送ACK+RST數(shù)據(jù)包完成三次握手
                send_1 = sr1(IP(dst=target) / TCP(dport=port, flags="AR"), timeout=2, verbose=0)
                print("[+] 掃描主機: %-13s 端口: %-5s 開放" %(target,port))
            elif send["TCP"].flags == "RA":
                print("[+] 掃描主機: %-13s 端口: %-5s 關(guān)閉" %(target,port))
            else:
                print("[+] 掃描主機: %-13s 端口: %-5s 關(guān)閉" %(target,port))

if __name__ == "__main__":
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    # 使用方式: main.py -H 192.168.1.10 -p 80,8080,443,445
    parser = argparse.ArgumentParser()
    parser.add_argument("-H","--host",dest="host",help="輸入一個被攻擊主機IP地址")
    parser.add_argument("-p","--port",dest="port",help="輸入端口列表 [80,443,135]")
    args = parser.parse_args()
    if args.host and args.port:
        tcpSynScan(args.host,eval(args.port))
    else:
        parser.print_help()

同理,我們分別傳入被掃描主機IP地址以及需要掃描的端口號列表,當掃描結(jié)束后即可輸出如下圖所示的結(jié)果;

5.UDP無狀態(tài)掃描

UDP 無狀態(tài)掃描是一種常見的網(wǎng)絡(luò)掃描技術(shù),其基本原理與TCP SYN掃描類似。不同之處在于UDP協(xié)議是無連接的、無狀態(tài)的,因此無法像TCP一樣建立連接并進行三次握手。

UDP 無狀態(tài)掃描的基本流程如下:

  • 客戶端向服務(wù)器發(fā)送帶有端口號的UDP數(shù)據(jù)包,如果服務(wù)器回復(fù)了UDP數(shù)據(jù)包,則目標端口是開放的。
  • 如果服務(wù)器返回了一個ICMP目標不可達的錯誤和代碼3,則意味著目標端口處于關(guān)閉狀態(tài)。
  • 如果服務(wù)器返回一個ICMP錯誤類型3且代碼為1,2,3,9,1013的數(shù)據(jù)包,則說明目標端口被服務(wù)器過濾了。
  • 如果服務(wù)器沒有任何相應(yīng)客戶端的UDP請求,則可以斷定目標端口可能是開放或被過濾的,無法判斷端口的最終狀態(tài)。

讀者需要注意,UDP 無狀態(tài)掃描可能會出現(xiàn)誤報或漏報的情況。由于UDP協(xié)議是無連接的、無狀態(tài)的,因此UDP端口不可達錯誤消息可能會被目標主機過濾掉或者由于網(wǎng)絡(luò)延遲等原因無法到達掃描主機,從而導(dǎo)致掃描結(jié)果不準確。

from scapy.all import *
import argparse
import logging

def udpScan(target,ports):
    for port in ports:
        udp_scan_resp = sr1(IP(dst=target)/UDP(dport=port),timeout=5,verbose=0)
        if (str(type(udp_scan_resp))=="<class 'NoneType'>"):
             print("[+] 掃描主機: %-13s 端口: %-5s 關(guān)閉" %(target,port))
        elif(udp_scan_resp.haslayer(UDP)):
            if(udp_scan_resp.getlayer(TCP).flags == "R"):
                print("[+] 掃描主機: %-13s 端口: %-5s 開放" %(target,port))
        elif(udp_scan_resp.haslayer(ICMP)):
            if(int(udp_scan_resp.getlayer(ICMP).type)==3 and int(udp_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                 print("[+] 掃描主機: %-13s 端口: %-5s 關(guān)閉" %(target,port))

if __name__ == "__main__":
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    parser = argparse.ArgumentParser()
    parser.add_argument("-H","--host",dest="host",help="")
    parser.add_argument("-p","--port",dest="port",help="")
    args = parser.parse_args()
    if args.host and args.port:
        udpScan(args.host,eval(args.port))
    else:
        parser.print_help()

運行上述代碼,并傳入不同的參數(shù),即可看到如下圖所示的掃描結(jié)果,讀者需要注意因為UDP的特殊性導(dǎo)致端口掃描無法更精確的判定;

到此這篇關(guān)于Python如何使用Scapy實現(xiàn)端口探測的文章就介紹到這了,更多相關(guān)Python Scapy端口探測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python入門教程(四十一)Python的NumPy數(shù)組索引

    Python入門教程(四十一)Python的NumPy數(shù)組索引

    這篇文章主要介紹了Python入門教程(四十一)Python的NumPy數(shù)組索引,數(shù)組索引是指使用方括號([])來索引數(shù)組值,numpy提供了比常規(guī)的python序列更多的索引工具,除了按整數(shù)和切片索引之外,數(shù)組可以由整數(shù)數(shù)組索引、布爾索引及花式索引,需要的朋友可以參考下
    2023-05-05
  • Python 定義只讀屬性的實現(xiàn)方式

    Python 定義只讀屬性的實現(xiàn)方式

    這篇文章主要介紹了Python 定義只讀屬性的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Python實現(xiàn)的簡單讀寫csv文件操作示例

    Python實現(xiàn)的簡單讀寫csv文件操作示例

    這篇文章主要介紹了Python實現(xiàn)的簡單讀寫csv文件操作,結(jié)合實例形式分析了Python使用csv模塊針對csv文件進行讀寫操作的相關(guān)實現(xiàn)技巧與注意事項,需要的朋友可以參考下
    2018-07-07
  • 淺談Python淺拷貝、深拷貝及引用機制

    淺談Python淺拷貝、深拷貝及引用機制

    本篇文章主要介紹了Python淺拷貝、深拷貝及引用機制,詳細的介紹了淺拷貝、深拷貝的介紹和區(qū)別,有興趣的可以了解一下。
    2016-12-12
  • Python2中的raw_input() 與 input()

    Python2中的raw_input() 與 input()

    這篇文章主要介紹了Python2中的raw_input() 與 input(),本文分析了它們的內(nèi)部實現(xiàn)和不同之處,并總結(jié)了什么情況下使用哪個函數(shù),需要的朋友可以參考下
    2015-06-06
  • Python使用vars輕松獲取對象屬性

    Python使用vars輕松獲取對象屬性

    vars?是?Python?內(nèi)置函數(shù)之一,它主要用于返回對象的?__dict__?屬性,本文將詳細介紹?vars?函數(shù)的用法,包括其基本語法、應(yīng)用場景等,有需要的可以參考下
    2024-12-12
  • python 中使用yagmail 發(fā)送郵件功能

    python 中使用yagmail 發(fā)送郵件功能

    這篇文章主要介紹了python 中使用yagmail 發(fā)送郵件功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • 解決Ubuntu pip 安裝 mysql-python包出錯的問題

    解決Ubuntu pip 安裝 mysql-python包出錯的問題

    今天小編就為大家分享一篇解決Ubuntu pip 安裝 mysql-python包出錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • 詳解Python 3D引擎Ursina如何繪制立體圖形

    詳解Python 3D引擎Ursina如何繪制立體圖形

    Python有一個不錯的3D引擎——Ursina。本文就來手把手教你認識Ursina并學(xué)會繪制立體圖形,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • python八皇后問題的解決方法

    python八皇后問題的解決方法

    這篇文章主要為大家詳細介紹了python八皇后問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09

最新評論