python中的scapy模塊


 

 

 

模塊簡介

Scapy是一個由Python編寫的強大工具,目前很多優秀的網絡掃描攻擊工具都使用了這個模塊。也可以在自己的程序中使用這個模塊來實現對網絡數據包的發送、監聽和解析。這個模塊相對於Nmap來說,更為底層。可以更直觀的了解網絡中的各類掃描攻擊行為。

相對於Nmap來說,Scapy模塊只會把收到的數據包展示給你,並不會告訴你這個包意味着什么。

例如,當你去醫院檢查身體時,醫院會給你一份關於身體各項指標的檢查結果,而醫生也會告訴你得了什么病或者沒有任何病。那么Nmap就像是一-個醫生,它會替你搞定-切,按照它的經驗提供給你結果。而Scapy則像是一個體檢的設備, 它只會告訴你各種檢查的結果,如果你自己就是-一個經驗豐富的醫生,顯然檢查的結果要比同行的建議更值得參考。

基本用法

在Kali里邊已經集成了Scapy這個工具,我們在終端下輸入Scapy就可以啟動它了。
在這里插入圖片描述

Scapy提供了和Python一樣的交互式命令行,在這里需要說一下,接下來的實例我都會在這個命令行里運行。

Scapy的基本操作

首先使用幾個實例來演示一下Scapy的用法,在Scapy中每一個協議就是一個類。只需要實例化一個協議類,就可以創建一個該協議的數據包,例如,如果要創建一個IP類型的數據包,就可以使用如下命令。

ip = IP() 

IP數據包最重要的屬性就是源地址和目的地址,這兩個屬性可以使用src和dst來設置,例如,要構造一個發往“192.168.1.107”的數據包,可以這么寫。

ip = IP(dst="192.168.1.107")

在這里插入圖片描述
這個目標dst值可以是一個IP地址,也可以是一個網段,例如192.168.1.0/24,這時產生的就不是一個數據包,而是256個數據包。
在這里插入圖片描述
如果想要查看每個數據包,可以使用 [p for p in ip]
在這里插入圖片描述
Scapy采用分層的形式來構造數據包,通常最下面的一個協議為Ether,然后是IP,在之后是TCP或者UDP。IP()函數無法用來構造ARP請求和應答數據包,所以這時可以使用Ether(),這個函數可以設置發送方和接收方的MAC地址。那么現在來產生一個廣播數據包,執行的命令如下。

Ether(dst="ff:ff:ff:ff:ff:ff")

執行后如圖。
在這里插入圖片描述
如果要構造一個HTTP數據包,也可以使用如下這種方式。

IP()/TCP()/"GET/HTTP/1.0\r\n\r\n"

Scapy目前使用頻率最高的類要數Ether、IP、TCP和UDP,但是這些類都具有哪些屬性呢?Ether類中顯然要有源地址、目的地址和類型。IP類的屬性則復雜了許多,除了最重要的源地址和目的地址之外,還有版本、長度、協議類型、校驗和等,TCP類中需要有源端口和目的端口。這里可以使用 ls() 函數來查看一個類擁有那些屬性。

例如,使用ls(Ether())來查看Ether類的屬性。
在這里插入圖片描述
也可以看一下IP()類中的屬性。

在這里插入圖片描述
可以對里邊對應的屬性進行設置,例如,將ttl的值設置為32,可以使用如下方式。

IP(src="192.168.1.1",dst="192.168.1.107"ttl=32)

Scapy模塊中的函數

除了這些對應着協議類和它們的屬性之外,還需要一些可以完成各種功能的函數。需要注意的一點是,剛才使用的IP()的作用是產生了一個IP數據包,但是並沒有將其發送出去,因此,現在首先來看的就是如何將產生的報文發送出去,Scapy中提供了多個用來完成發送數據包的函數,首先來看一下其中的send()sendp()。這兩個函數的區別在於send()工作在第三層,而sendp()工作在第二層。簡單地說,send()是用來發送IP數據包的,而sendp()是用來發送Ether數據包的。
例如,構造一個目的地址為“192.168.1.107”的ICMP數據包,並將其發送出去,可以使用如下語句。

send(IP(dst="192.168.1.107")/ICMP())

執行結果。
在這里插入圖片描述如果成功了就會出現一個“Sent 1 packets.”的顯示

send(Ether(dst="ff:ff:ff:ff:ff:ff"))

執行結果。
在這里插入圖片描述
注:這兩個函數,只發不收

如果希望發送一個內容是隨機填充的數據包,而且又要保證這個數據包的正確性,那么可以是fuzz()函數。例如,可以使用如下命令來創建一個發往192.168.1.107的tcp數據包。

IP(dst="192.168.1.107")/fuzz(TCP())

執行結果。
在這里插入圖片描述
在Scapy中提供了三個用來發送接收數據包的函數,分別是**sr()、sr1()和srp()**其中sr()和sr1()工作在第三層,例如IP和ARP等,而srp()工作在第二層。
這里仍然向192.168.1.107發送一個ICMP數據包來比較一下sr()和send()的區別。

sr(IP(dst="192.168.1.107")/ICMP())

執行結果。
在這里插入圖片描述
當禪城==產生的數據包發送出去之后,Scapy就會監聽接收到的數據包個數,answers表示對應的應答數據包。
sr()函數是Scapy的核心,它的返回值是兩個列表,第一個列表是收到了應答的包和對應的應答,多伊爾戈列表是未收到應答的包。所以使用兩個列表來保存sr()的返回值。
在這里插入圖片描述
這里使用ans和unans來保存sr()的返回值,因為發出的是一個ICMP請求數據包,而且也收到了一個應答包,所以這個發送的數據包和收到的應答包都被保存到了ans列表中,使用ans.summary()可以查看兩個數據包的內容,而unans列表為空。

sr1()函數和sr()函數作用基本一樣,但是值返回一個應答包。只需要使用一個列表就可以保存這個函數的返回值。例如,使用p來保存sr1(IP(dst=“192.168.1.107”)/ICMP())的返回值。
在這里插入圖片描述
可以使用sr1()函數來測試目標的某個端口是否開放,采用半開掃描(SYN)的辦法。

執行結果如圖所示。
在這里插入圖片描述

從上面p的值可以看出,192.168.1.107回應了發出設置了SYN標志位的TCP數據包,這表明他開放了80端口。

另外一個十分重要的函數就是sniff(),如果使用過Tcpdump,那么對這個函數的使用就不會感到陌生。通過這個函數可以在自己的程序中捕獲經過本機網卡的數據包。
在這里插入圖片描述

這里有個比較坑的地方,就是他不能實時回顯,你必須得終止嗅探他才會回顯他嗅探到的包。

這個函數強大的地方在於可以使用番薯filter對數據包進行過濾。例如,指定之捕獲與192.168.1.107有關的數據包,可以使用“host 192.168.1.107”:

sniff(filter="192.168.1.107")

同樣,也可以使用filter來過濾指定的協議,例如ICMP類型的數據包。

sniff(filter="icmp")

如果要同時滿足多個條件,可以使用“and”、“or”等關系運算符來表達:

sniff(filter=" host 192.168.1.107 and icmp")

另外兩個很重要的參數是iface、count。iface可以用來指定所要進行監聽的網卡,例如,指定eth0作為監聽網卡,就可以使用:

sniff(iface="eth0")

而count則用來指定監聽到數據包的數量,達到指定的數量就會停止監聽,例如,只監聽30個數據包:

sniff(count=30)

現在設計一個綜合性的監聽器他會在網卡eth0上監聽源地址或者目標地址為192.168.1.107的ICMP數據包,到收到3個這樣的數據包就停止:

sniff(filter="icmp and host 192.168.1.107",count=30,iface="eth0")

運行結果:
在這里插入圖片描述如果要查看這三個數據包的內容,可以使用"_",在Scapy中這個符號表示是上一條語句的執行結果。例如:

a=_
a.nsummart()

運行結果:
在這里插入圖片描述剛剛使用過的函數 pkt.summary()用來以摘要的形式顯示pkt的內容,這個摘要長度為一行。

p=IP(dst="www.baidu.com")
p.summary()

運行結果:
在這里插入圖片描述注:函數pkt.summary的作用與pkt.nsummary()相同,只是操作對象是單個數據包

Scapy模塊的常用簡單實例

由於scapy功能極為強大,可以構造目前各種常見的協議類型的數據包,因此幾乎可以使用這個模塊完成任何任務,下面看看一些簡單的應用。

使用scapy來實現一次ACK類型的端口掃描,對192.168.1.107的21、22、23、135、443、445這些端口是否被屏蔽進行掃描, 注意是屏蔽,不是關閉! 采用ACK掃描模式,可以構造一下命令方式。

ans,unans = sr(IP(dst="192.168.1.107")/TCP(dport=[21,22,23,135,443,445],flags="A"))

運行結果:
在這里插入圖片描述
正常的時候,如果一個開放的端口會回應ACK數據包,而關閉則回應RST數據包。在網絡中,一些安全設備會過濾一部分端口,這些端口不會響應來自外界的數據包一切發往這些端口的數據包都石沉大海,這些端口的狀態並非是開放或者關閉的這是網絡安全管理常用的方法。

首先查看未被過濾的端口:

 for s,r in ans:
    if s[TCP].dport == r[TCP].sport:
        print("The port "+str(s[TCP].dport)+" is unfiltered")

運行結果:
在這里插入圖片描述

編寫端口掃描器

下面使用Scapy強大的包處理功能來設計一個端口是否開放的掃描器。注意,這里還是要注意和前面例子的區別,如果-一個端口處於屏蔽狀態,那么它將不會產生任何響應報文。如果一個端口處於開放狀態,那么它在收到syn數據包之后,就會回應- -個ack數據包。反之,如果一個端口處於關閉狀態,那么它在收到syn數據包之后,就會回應-一個rst數據包。首先在Kali Linux 2中啟動一個終端,在終端中打開Python。先導入需要使用的模塊文

from scapy.all import fuzz,TCP,IP,sr #導入模塊與函數

接下來產生一個目標為“192.168.1.107”的80端口的SYN數據包,將此標志位設置為“S”:

ans,unans = sr(IP(dst="192.168.1.1")/fuzz(TCP(dport=80,flags="S"))) //指定目標地址以及端口

接下來使用循環查看,如果r[TCP].flags==18,則表示目標端口開放,若為20則為關閉狀態。

for s,r in ans:                    		#把ans的值賦給s,r並開始遍歷
	if r[TCP].flags==18:		   		#判斷返回值是否等於18
		print("This port is Open") 		#輸出判斷結果
	if r[TCP].flags==20:				#判斷返回值是否等於20
		print("This port is Closed")	#輸出判斷結果

運行結果:
在這里插入圖片描述

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM