Python程序設計-安全滲透測試模塊-Scapy模塊

簡介

  • Scapy是一個由Python語言編寫的強大工具,它是大量程序編寫人員最喜愛的一個網絡模塊。目前很多優秀的網絡掃描和攻擊工具都使用了這個模塊。
  • 也可以在自己的程序中使用這個模塊來實現對網絡數據包的發送、監聽和解析。
  • 這個模塊相比起Nmap來說,更爲底層。可以更爲直觀地瞭解到網絡中的各種掃描和攻擊行爲,例如,要檢測某一個端口是否開放,只需提供給Nmap一個端口號,而Nmap就會給出一個開放或者關閉的結果,但是並不知道Nmap是怎麼做的。
  • 如果想對網絡中的各種問題進行深入研究,Scapy無疑是一個更好的選擇,可以利用它來產生各種類型的數據包併發送出去,Scapy也只會把收到的數據包展示給你,而並不會告訴你這意味着什麼,一切都將由你來判斷。

基本用法

Scapy提供了和Python一樣的交互式命令行。Scapy可以作爲Python的一個模塊存在,但是Scapy本身就是一個可以運行的工具,它自己具備一個獨立的運行環境,因而可以不在Python環境下運行。
在這裏插入圖片描述

基本操作

  • 在Scapy中,每一個協議就是一個類。
  • 只需要實例化一個協議類,就可以創建一個該協議的數據包。例如,如果要創建一個IP類型的數據包,就可以使用如下命令。
ip = IP()

在這裏插入圖片描述

  • IP數據包最重要的屬性就是源地址和目的地址,這兩個屬性可以使用src和dst來設置。
  • 例如,要構造一個發往“192.168.1.101”的IP數據包,可以使用如下語句。
ip = IP(dst="192.168.1.101")

在這裏插入圖片描述

  • 這個目標dst的值可以是一個IP地址,也可以是一個IP範圍,
  • 例如192.168.1.0/24,這時產生的就不是1個數據包,而是256個數據包。
    在這裏插入圖片描述
  • 如果要查看其中每一個數據包,可以使用
p for p in ip

在這裏插入圖片描述

採用分層形式來構造數據包

  • 通常最下面的一個協議爲Ether,然後是IP,再之後是TCP或者是UDP。
  • IP()函數無法用來構造ARP請求和應答數據包,可以使用Ether(),
  • 這個函數可以設置發送方和接收方的MAC地址。
  • 產生一個廣播數據包,執行命令如下
Ether(dst="ff:ff:ff:ff:ff:ff")

在這裏插入圖片描述

  • Scapy中的分層通過符號“/”實現,一個數據包是由多層協議組合而成,這些協議之間就可以使用“/”分開,按照協議由底而上的順序從左向右排列
  • 例如,可以使用以下命令來完成一個TCP數據包,
Ether()/IP()/TCP()	

在這裏插入圖片描述

  • 如果構造一個HTTP數據包,可以使用以下方式
IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"

在這裏插入圖片描述

ls()函數查看一個類所擁有的屬性

  • 使用ls(Ether())來查看Ether類屬性
    在這裏插入圖片描述
  • 使用ls(IP())來查看IP類的屬性
    在這裏插入圖片描述
  • 可以對這裏面的屬性進行設置
  • 例如:將ttl的值設置爲32,可以使用如下方式
IP(src="192.168.1.1", dst="192.168.1.101", ttl=32)

在這裏插入圖片描述

發送函數

send() 工作在第三層,發送IP數據包
sendp() 工作在第二層,發送Ether數據包

  • 例如,構造一個目的地址爲"192.168.1.101"的ICMP數據包,並將其發送出去,可以使用一下語句
send(IP(dst="192.168.1.101")/ICMP())

在這裏插入圖片描述

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

在這裏插入圖片描述

  • 注:這兩個函數只發不收

fuzz()函數

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

在這裏插入圖片描述

sr(),sr1()和srp()

  • 在網絡的各種應用中,需要做的不僅是將創建好的數據包發送出去,也需要接收這些數據包的應答數據包,這一點在網絡掃描中尤爲重要。
  • 在Scapy中提供了三個用來 發送和接收數據包的函數,分別是sr()、sr1()和srp(),其中,sr()和sr1()主要用於第三層,例如IP和ARP等。而srp()用於第二層。
  • 仍然向192.168.1.101發送一個ICMP數據包來比較一下sr()和send()的區別。
sr(IP(dst="192.168.1.101")/ICMP())

在這裏插入圖片描述

  • 當產生的數據包發送出去之後,Scapy就會監聽接收到的數據包,並將其中對應的應答數據包篩選出來,顯示在下面。Reveived表示收到的數據包個數,answers表示對應的應答數據包。
  • sr()函數是Scapy的核心,它的返回值是兩個列表,第一個列表是收到了應答的包和對應的應答,第二個列表是未收到應答的包。所以可以使用兩個列表來保存sr()的返回值
  • sr()函數是Scapy的核心,它的返回值是兩個列表
  • 第一個列表是收到了應答的包和對應的應答,
  • 第二個列表是未收到應答的包。所以可以使用兩個列表來保存sr()的返回值
    在這裏插入圖片描述
  • 使用ans和unans來保存sr()的返回值,因爲發出去的是一個ICMP的請求數據包,而且也收到了一個應答包,所以這個發送的數據包和收到的應答包都被保存到了ans列表中
  • 使用ans.summary()可以查看兩個數據包的內容,而unans列表爲空。
  • sr1()函數跟sr()函數作用基本一樣,但是隻返回一個應答的包。只需要使用一個列表就可以保存這個函數的返回值。
  • 例如,使用p來保存sr1(IP(dst=“192.168.26.6”)/ICMP())的返回值,如圖所示。
    在這裏插入圖片描述
  • 可以利用sr1()函數來測試目標的某個端口是否開放,採用半開掃描(SYN)的辦法。
sr1(IP(dst="192.168.26.101")/TCP(dport=80,flags="S"))

在這裏插入圖片描述
在這裏插入圖片描述

  • 192.168.26.101迴應了發出的設置了SYN標誌位的TCP數據包,這表明這臺主機的80端口是開放的

sniff()

這個函數可以在自己的程序中捕獲經過本機網卡的數據包
在這裏插入圖片描述

  • 比如先在終端開一個sniff() scapy 就處於一個捕獲網卡數據包的狀態

  • 如果有流量經過網卡(比如在另一個終端上 ping一下別的主機)

  • 在 ctrl+c的時候獲取sniff()的結果

  • 這個函數最強大的地方在於可以使用參數filter對數據包進行過濾。

  • 例如,指定只捕獲與192.168.1.102有關的數據包,可以使用“host 192.168.1.102”:

sniff(filter=" host 192.168.1.102")
  • 同樣,也可以使用filter來過濾指定協議,例如,icmp類型的數據包:
sniff(filter="icmp")
  • 如果要同時滿足多個條件可以使用“and”“or”等關係運算符來表達:
sniff(filter=" host 192.168.1.102 and icmp")
  • iface參數
    指定所要進行監聽的網卡
    例如,指定eth1作爲監聽網卡sniff(iface="eth1")
  • count參數
    用來指定監聽到的數據包的數量,達到指定數量就會監聽停止
    例如,只希望監聽到三個數據包就停止sniff(count=3)
  • 設計一個綜合性的監聽器,它會在網卡eth0上監聽源地址或者目的地址爲192.168.1.102的icmp數據包,當收到了三個這樣的數據包之後,就會停止監聽。
  • 首先在Scapy中創建如下監聽器:
sniff(filter="icmp and host 192.168.26.100“,count=3,iface="eth0")
  • 正常情況下,是不會有去往或者來自192.168.1.102的icmp數據包的,所以這時候可以打開一個新的終端,然後在裏面執行命令“ping 192.168.1.102”
  • 然後在Scapy中使用組合鍵Ctrl+C結束捕獲,這時可以看到已經捕獲到三個數據包
    在這裏插入圖片描述
  • 如果需要查看這三個數據包內容,可以使用“_”,在Scapy中這個符號表示是上一條語句執行的結果,
  • 例如剛剛使用sniff捕獲到的數據包,就可以用“_”表示。
a =_
a.nsummary()

在這裏插入圖片描述

  • 剛剛使用過的函數pkt.summary()用來以摘要的形式顯示pkt的內容,這個摘要的長度爲一行
p = IP(dst="www.baidu.com")     
p.summary()     "192.168.169.130>Net('www.baidu.com') hopopt"

常用簡單實例

  • 使用Scapy來實現一次ACK類型的端口掃描
  • ACK掃描:掃描主機向目標主機發送ACK數據包。根據返回的RST數據包- 有兩種方法可以得到端口的信息。方法一是:
    若返回的RST數據包的TTL值小於或等於64,則端口開放,反之端口關閉
  • 例如,對192.168.1.102 的 21、23、135、443、445 這5個端口是否被屏蔽進行掃描,注意是屏蔽不是關閉,採用ACK掃描模式,可以構造如下的命令方式。
ans,unans = sr(IP(dst="192.168.1.102")/TCP(dport=[21,23,135,443,445],flags="A"))
  • 正常的時候,如果一個開放的端口會迴應ack數據包,而關閉的端口會迴應rst數據包。
  • 在網絡中,一些網絡安全設備會過濾掉一部分端口,這些端口不會響應來自外界的數據包,一切發往這些端口的數據包都如同石沉大海。注意這些端口的狀態並非是開放或者關閉,而是被屏蔽。
    在這裏插入圖片描述
  • 向目標發送了5個標誌位置爲“A”的TCP數據包。按照TCP三次握手的規則,如果目標端口沒有被過濾,發出的數據包就會得到迴應,否則沒有迴應。另外,根據Scapy的設計,ans列表中的數據包就是得到了迴應的數據包,而unans中的則是沒有得到迴應的數據包,只需要分兩次來讀取這兩個列表就可以得到端口的過濾結果
    在這裏插入圖片描述
  • 也可以用類似的方法來查看被過濾的端口:
    在這裏插入圖片描述
  • 下面在Python中編寫程序來實現一個查看端口是否被屏蔽的簡單程序。首先導入需要使用的scapy模塊中的函數:
from scapy.all import IP,TCP,sr
  • 這裏需要IP()和TCP()來產生所需要的數據包,sr()函數來發送,然後發送構造好的數據包,在Python交互式命令行中執行這個程序的結果如圖所示。
    在這裏插入圖片描述

  • 下面使用Scapy強大的包處理功能來設計一個端口是否開放的掃描器。

  • 如果一個端口處於屏蔽狀態,那麼它將不會產生任何響應報文。

  • 如果一個端口處於開放狀態,那麼它在收到syn數據包之後,就會迴應一個ack數據包。

  • 反之,如果一個端口處於關閉狀態,那麼它在收到syn數據包之後,就會迴應一個rst數據包。

  • 先導入需要使用的模塊文件,這次需要使用IP()、TCP()來創建數據包,使用fuzz()來填充數據包,使用sr()來發送數據包。

from scapy.all import fuzz,TCP,IP,sr
  • 接下來產生一個目標爲“192.168.26.100”的80端口的syn數據包,將標誌位設置爲“S”:
ans,unans = sr(IP(dst="192.168.26.100")/fuzz(TCP(dport=80,flags="S")))
  • 接下來使用循環來查看,
  • 如果r[TCP].flags==18,則表示返回數據包flags的值爲0x012 (SYN,ACK)目標端口爲開放狀態。
  • 如果r[TCP].flags==20,則表示返回數據包flags的值爲0x014 (RST, ACK) 目標端口爲關閉狀態。
    在這裏插入圖片描述
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章