Python3+Scapy安裝使用教程


一、說明

之前寫DoS程序的時候(見"拒絕服務(DoS)理解、防御與實現"),數據包完全是自己構造的,這其中的難處一是要清楚各層協議的字段、字段長度、字段是數值還是字符、大頭還是小頭,二是計算校驗和。整個過程比較痛苦。

其實構造DoS數據包,我們經常只是想偽造一下源IP等少數字段,而事實上大量時間花在其他大多數不想關心的字段的構造上。

在查找資料過程中發現很多DoS程序直接使用一個“Scapy”的包(開始還以為是Scrapy心想Scrapy什么時候可以用來構造數據包了,后來才注意到少了個“r”)。當時沒太在意,現在回頭看Scapy確實堪稱“神器”,值得記錄一番。

本文主要參考官方文檔,更多用法也請見:https://scapy.readthedocs.io/en/latest/usage.html

 

二、安裝

直接使用pip安裝:

pip install scapy

一些擴展功能安裝,可選:

pip install matplotlib pyx cryptography

 

三、生成數據包

3.1 啟動scapy交互shell

切換到Python的Scripts文件夾下,直接使用scapy命令啟動(本質是scapy.bat):

scapy

啟動界面如下圖(由於我沒裝PyX所以提示不能使用psdump()和pdfdump(),另外還有一些告警,都無關緊要就不處理了):

 

3.2 生成數據包

在scapy中,應用層之下的數據包,基本使用協議大寫對應的方法就可以直接生成。如:

# 使用Ether()方法生成一個以太網層數據包
eth_packet = Ether()
# 使用IP()方法生成一個網絡層數據包
ip_packet = IP()
# 使用TCP()方法生成一個tcp數據包
tcp_packet = TCP()
# 使用UDP()方法生成一個udp數據包
udp_packet = UDP()
# 使用ICMP()方法生成一個udp數據包
icmp_packet = ICMP()

 

3.3 查看數據包內容

上一小節中生成數據包,如果就長這樣的話完全就是一個黑盒,我們需要一些方法來知道數據包(各字段)是什么內容。

哪個協議的數據包查看都是類似的,我們這里以一個tcp數據包為例,查看其他協議的數據包類似操作即可。

# 使用IP()方法生成一個tcp數據包
ip_packet = IP()

# 方法一、使用raw()方法查看
raw(ip_packet)

# 方法二、使用hexdump()查看。類似Wireshark
hexdump(ip_packet)

# 方法三、raw()配合協議類查看。最佳
# 查看該數據包以太網層內容(下層內容不層示,上層內容不解析只以load形式展示)
Ether(raw(ip_packet))
# 查看該數據包網絡層內容(下層內容不層示,上層內容不解析只以load形式展示)
IP(raw(ip_packet))

 

3.4 自定義字段值

上一小節中我們使用raw配合協議方法的方式清楚地看到了數據包中各字段的值,這些值是根據本機信息自動生成的,我們來看如何自定義各字段的值。

定義字段的值有兩個種方法,一種是在構造時直接傳遞參數,另一種是在生成后重新賦值;至於參數名即是上一小節中打出的那些項。

以修改源IP地址和TTL為例,在上一小節中可以看到默認生成的源IP地址叫“src”值為“10.10.6.91”(這是我本機當前的IP地址),TTL叫ttl默認值64。

# 方法一,在構造時直接傳遞參數
# 給src傳值10.10.6.92,ttl傳值128;字段為字符的以字符串形式傳,字段為數值的以數值形式傳
ip_packet = IP(src="10.10.6.92",ttl=128)
# 查看數據包各項值,確認src項是否為10.10.6.92,ttl項是否為128
IP(raw(ip_packet))

# 方法二,在生成后重新賦值
# 給src賦值10.10.6.92,ttl賦值128;字段為字符的以字符串形式賦,字段為數值的以數值形式賦
ip_packet.src = "10.10.6.93"
ip_packet.ttl = 200
# 查看數據包各項值,確認src項是否為10.10.6.93,ttl項是否為200
IP(raw(ip_packet))

 

3.5 同時自定義多層協議的字段

在上一小節中我們自定義了源IP地址,但有一個問題:如果此時我想自定義源MAC地址該如何操作呢。想在構造時直接傳遞參數使用的是IP()又不是Ether();想在生成后重新賦值,上一小節已試驗過了src改的是源ip,源mac沒法通過src項改。

構造多層協議,構造函數可使用“/”隔開,低層函數在前高層函數在后;最后使用構造函數中的最低層函數即可查看數據包內容。

# 構造一個IP數據包,源mac設置為"00:00:00:00:00:11",源ip設置為"10.10.6.92"
ip_packet = Ether(src="00:00:00:00:00:11")/IP(src="10.10.6.92")
# 當前構造函中最低層為Ether
Ether(raw(ip_packet))

# 定義一個TCP數據包,源mac設置為"00:00:00:00:00:11",源ip設置為"10.10.6.92",源端口設置為1234
tcp_packet = Ether(src="00:00:00:00:00:11")/IP(src="10.10.6.92")/TCP(sport=1234)
# 當前構造函中最低層為Ether
Ether(raw(tcp_packet))

# 定義一個應用層數據包,應用層內容為"GET / HTTP/1.0\r\n\r\n"
app_packet = IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
# 當前構造函中最低層為IP
IP(raw(app_packet))

 

四、發送和接收數據包

4.1 只發送數據包不接收數據包

send()函數允許自定義網絡層,sendp()函數允許自定義以太網層。

不管TCP還是UDP都一樣直接使用send()等函數即可,scapy會自己選擇socket類型,不我們關心。

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

sendp(Ether()/IP(dst="10.10.6.92")/ICMP())

 

4.2 發送並接收響應數據包

sr1()函數參許自定義網絡層,srp()函數允許自定層數據鏈路層

rec_packet = sr1(IP(dst="10.10.6.92")/ICMP()/"abcdefg")
rec_packet
# 直接讀取某項值
rec_packet.src
# 使用show()方法格式化輸出
rec_packet.show()

 

4.3 syn掃描

所謂syn掃描就是把Flags字段明確指定為SYN

rec_packet = sr1(IP(dst="10.10.6.92")/TCP(dport=80,flags="S"))
rec_packet.show()

 

五、在代碼中使用

前面我們都是基於交互shell進行了,如果是在文件中該如何使用scapy呢。

交互shell和文件在代碼書寫上沒有區別,唯一的區別就是交互shell導入好了scapy的所有類,而到文件上導入scapy所有類最簡單的方式就是:

from scapy.all import *

(實踐發現,這種寫法在Pycharm中還是會提示“Unresloved reference”但運行是不報錯的;實在不行使用“Alt+Enter”鍵把使用到的類逐個導入即可。)

 

參考:

https://scapy.readthedocs.io/en/latest/usage.html

https://github.com/secdev/scapy/


免責聲明!

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



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