scapy的基本用法


不知道為何,網上有些把scapy跟scrapy搞混的。scapy是一個操作網絡數據包的工具(Packet crafting),scrapy是一個屏幕抓取和web抓取框架(A Fast and Powerful Scraping and Web Crawling)...

scapy的基本用法還是參照scapy官網上的來做吧。翻譯對我來說是一件困難的事,幸虧有人已經做過類似的工作,如這篇博客Scapy使用文檔中文版。那對於一些我不確定的翻譯,我就直接使用這篇博客的。我的文章也可以看作是對於Scapy使用文檔中文版的轉載;不過我會根據自己的理解,以及結合不同網絡協議的學習,加一些注解。測試平台是linux centos7。

安裝

python3 -m pip install scapy

或者嘗試

python3

pip3 install scapy

開始使用scapy

scapy的交互式shell在終端會話中,發送數據包需要root權限,所以普通用戶需要使用sudo命令

sudo ./scapy

我這root用戶,直接使用scapy命令就好

配置終端顯示顏色

將conf.color_theme設置為下列樣式中的一種:

DefaultTheme, BrightTheme, RastaTheme, ColorOnBlackTheme, BlackAndWhite, HTMLTheme, LatexTheme

如:

conf.color_theme = BrightTheme()

交互式教程

新建一個包(packet),測一測以下代碼

 此處IP創建了一個默認的數據包,使用ls(IP())可以查看IP數據包的參數

 

 

 疊層(Stacking layers)

“/”操作符在兩個層之間起到一個組合的作用。當使用該操作符時,下層可以根據其上層,使它的一個或多個默認字段被重載。(您仍可以賦予您想要的值)一個字符串也可以被用作原始層。

 

 

 

每一個數據包都可以被建立或分解(注意:在Python中“_”(下划線)是上一條語句執行的結果):

 

被拆分的包保留了所有字段,如果這樣顯得太啰嗦,可以通過hide_defaults()方法刪除重復的字段

 

 

 讀取PCAP文件

a=rdpcap("/spare/captures/isakmp.cap")

 圖形轉儲(PDF,PS)

如果你安裝了PyX,你可以將一個包或者一系列包圖形轉儲為PostScript/PDF文件(下面是比較丑的PNG圖片,如果是PostScript/PDF格式的話質量要更好)
未安裝pyx提示:ImportError: PyX and its dependencies must be installed

a[423].pdfdump(layer_shift=1)

a[423].psdump("/tmp/isakmp_pkt.eps",layer_shift=1)

 

命令

作用

raw(pkt)

組裝數據包

hexdumo(pkt)

轉換成16進制

ls(pkt)

列出字段值

pkt.summary()

查看數據包的一行摘要

pkt.show()

包的開發視圖

pkt.show2()

show一樣,但是用於組裝包上(例如,計算校驗和(checksum))

pkt.sprintf()

用包字段值填充格式化字符串

pkt.decode_payload_as()

改變有效載荷的解碼方式

pkt.psdump()

繪制一個解釋說明的PostScript圖表

pkt.pdfdump()

繪制一個解釋說明的pdf

ptk.command

返回一個可以生成包的scapy命令

 

生成數據包的集合/生成一組包

目前我們只是生成一個數據包。讓我們看看如何輕易地定制一組數據包。整個數據包的每一個字段(甚至是網絡層次)都可以是一組。在這里隱含地定義了一組數據包的概念,意思是在所有字段中使用笛卡爾積來生成一組數據包。

 

 

 某些操作(如修改一個數據包中的字符串)無法對一組數據包使用。在這些情況下,如果您忘記展開您的數據包集合,只有您忘記生成的列表中的第一個元素會被用於組裝數據包。

(這里其實就是利用python的list生成一組數據包sets of packets)

命令

集合

summary()

顯示每個包的摘要列表

nsummary()

跟前面的一樣,並且帶有包數量

conversations()

顯示會話的圖標

show()

displays the preferred representation (通常用nsummary()

filter()

返回一個由lambda函數過濾的包列表

hexdump()

返回所有包的一個hexdump數據

haxraw()

返回所有包的Raw layer 的一個hexdump數據

padding()

返回一個帶有填充的包的hexdump

nzpadding()

返回一個非0填充的包的hexdump

plot()

繪制應用於數據包列表的lambda函數

make table()

根據lambda函數顯示一個表格

 
發送包
我們已經知道如何去修改包,現在讓我們看看怎么發送它們。send()函數在第3層(網絡層?)上發送包。這就是說,它將為你處理第2層數據和路由。sendp()函數工作在第2層(數據鏈路層?)。選擇正確的接口和鏈接層協議(link layer protocol)完全取決於你。如果return_packets=True,則send()和sendp()將返回已發送的包列表。

 ttl,即Time To Live的縮寫,該字段指定IP包被路由器丟棄之前允許通過的最大網段數量,TTL是IPv4報頭的一個8bit字段。雖然TTL從字面上翻譯,是可以存活的時間,但實際上TTL是IP數據包在計算機網絡中可以轉發的最大跳數。TTL字段由IP數據包的發送者設置,在IP數據包從源到目的的整個轉發路徑上,每經過一個路由器,路由器都會修改這個TTL字段值,具體的做法是把該TTL的值減1,然后再將IP包轉發出去。如果在IP包到達目的IP之前,TTL減少為0,路由器將會丟棄收到的TTL=0的IP包並向IP包的發送者發送 ICMP time exceeded消息。(百度百科)

錯誤提示:WARNING: Mac address to reach destination not found. Using broadcast.這個錯誤是因為應該用sendp發送而用了send

 關於返回值的測試

 

Fuzzing

fuzz()函數可以通過一個具有隨機值、數據類型合適的對象,來改變任何默認值,但該值是不能被計算的(像校驗和那樣)。這使得可以快速建立循環模糊化測試模板。在下面的例子中,IP層是正常的,UDP層和NTP層被fuzz。UDP的校驗和是正確的,UDP的目的端口被NTP重載為123,而且NTP的版本被更變為4.其他所有的端口將被隨機分組:

 

 備注:Fuzzing是模糊測試,通過函數隨機生成大量測試用例來測試程序。

 發送並且接收包

 現在,我們來做一些有趣的事,src()函數用來發送包並且接收響應。這個函數返回包及其響應,以及沒有響應的包。函數sr1()是一個變體,它只返回一個響應包(不管是發送一個包還是一組包)。這些包必須是第三層的包(IP包,ARP包等)。函數srp()做類似的事,不過它是發送第二層包(如以太包,802.3等),如果沒有應答,或者超時,會返回一個空值(比如,構建包字段填寫錯誤,返回空值)。

 

 一個DNS查詢(rd=recursion desired)。主機192.168.5.1是我的DNS服務器。注意從我Linksys來的非空填充具有Etherleak缺陷:

>>> sr1(IP(dst="192.168.5.1")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.slashdot.org"))) Begin emission: Finished to send 1 packets. ..* Received 3 packets, got 1 answers, remaining 0 packets <IP version=4L ihl=5L tos=0x0 len=78 id=0 flags=DF frag=0L ttl=64 proto=UDP chksum=0xaf38  src=192.168.5.1 dst=192.168.5.21 options='' |<UDP sport=53 dport=53 len=58 chksum=0xd55d  |<DNS id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L rcode=ok qdcount=1 ancount=1  nscount=0 arcount=0 qd=<DNSQR qname='www.slashdot.org.' qtype=A qclass=IN |>  an=<DNSRR rrname='www.slashdot.org.' type=A rclass=IN ttl=3560L rdata='66.35.250.151' |>  ns=0 ar=0 |<Padding load='\xc6\x94\xc7\xeb' |>>>> 

發送和接受函數族(function family)是scapy的核心。它們返回兩個列表。第一個就是發送的數據包及其應答組成的列表,第二個是無應答數據包組成的列表。為了更好地呈現它們,它們被封裝成一個對象,並且提供了一些便於操作的方法:

>>> sr(IP(dst="192.168.8.1")/TCP(dport=[21,22,23])) Received 6 packets, got 3 answers, remaining 0 packets (<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>) >>> ans, unans = _ >>> ans.summary() IP / TCP 192.168.8.14:20 > 192.168.8.1:21 S ==> Ether / IP / TCP 192.168.8.1:21 > 192.168.8.14:20 RA / Padding IP / TCP 192.168.8.14:20 > 192.168.8.1:22 S ==> Ether / IP / TCP 192.168.8.1:22 > 192.168.8.14:20 RA / Padding IP / TCP 192.168.8.14:20 > 192.168.8.1:23 S ==> Ether / IP / TCP 192.168.8.1:23 > 192.168.8.14:20 RA / Padding

如果對於應答數據包有速度限制,你可以通過“inter”參數來設置兩個數據包之間等待的時間間隔。如果有些數據包丟失了,或者設置時間間隔不足以滿足要求,你可以重新發送所有無應答數據包。你可以簡單地對無應答數據包列表再調用一遍函數,或者去設置“retry”參數。如果retry設置為3,scapy會對無應答的數據包重復發送三次。如果retry設為-3,scapy則會一直發送無應答的數據包,直到“timeout”參數等待最后一個數據包已發送的時間。

 

 

 SYN Scans

經典的SYN掃描可以通過執行下面的提示符命令初始化

 

 

上面向Google的80端口(我這里改成能ping通的其他主機地址了)發送單個SYN包,在接受單個響應時退出。

從上面的輸出可以看出,目標主機返回一個“SA”或者SYN-ACK標志標明端口是開放的。

使用其他標志位掃描一下系統的440到443端口:

>>> sr(IP(dst="192.168.1.1")/TCP(sport=666,dport=(440,443),flags="S"))

或者:

 

>>> sr(IP(dst="192.168.1.1")/TCP(sport=RandShort(),dport=[440,441,442,443],flags="S"))

可以對收集的數據包進行摘要(summary),來快速地瀏覽響應:

 

>>> ans, unans = _ >>> ans.summary() IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:440 S ======> IP / TCP 192.168.1.1:440 > 192.168.1.100:ftp-data RA / Padding IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:441 S ======> IP / TCP 192.168.1.1:441 > 192.168.1.100:ftp-data RA / Padding IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:442 S ======> IP / TCP 192.168.1.1:442 > 192.168.1.100:ftp-data RA / Padding IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp-data SA / Padding

 

進度......20%

參考

Scapy使用文檔中文版

推薦

 Fuzzing技術總結(Brief Surveys on Fuzz Testing)

 


免責聲明!

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



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