cdt规约报文用程序解析_用Python运维网络(5):scapy
本文參考了文章:
弈心:網絡工程師的Python之路---Scapy基礎篇?zhuanlan.zhihu.com弈心:網絡工程師的Python之路---Scapy應用篇?zhuanlan.zhihu.com什么是Scapy?
根據scapy官方的定義:
Scapy is a Python program that enables the user to send, sniff and dissect and forge network packets. This capability allows construction of tools that can probe, scan or attack networks.In other words, Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. Scapy can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery. It can replace hping, arpspoof, arp-sk, arping, p0f and even some parts of Nmap, tcpdump, and tshark).
大意就是:Scapy是一個強大的,用Python編寫的交互式數據包處理程序,它能讓用戶發送、嗅探、解析,以及偽造網絡報文,從而用來偵測、掃描和向網絡發動攻擊。Scapy可以輕松地處理掃描(scanning)、路由跟蹤(tracerouting)、探測(probing)、單元測試(unit tests)、攻擊(attacks)和發現網絡(network discorvery)之類的傳統任務。它可以代替hping,arpspoof,arp-sk,arping,p0f 甚至是部分的Nmap,tcpdump和tshark 的功能。
Scapy實驗運行環境和拓撲:
網絡環境同前幾篇:
幾臺交換機的管理ip地址為:
- L3-1 192.168.56.10/24
- L2-1 192.168.11.253/24
- L2-2 192.168.12.253/24
- L2-3 192.168.13.253/24
- L2-4 192.168.14.253/24
- L2-5 192.168.15.253/24
密 碼: 123
scapy運行在win7或ubuntu上,安裝很簡單,網上有很多教程。
https://www.cnblogs.com/qingkongwuyun/p/8508733.html
測試環境:
ubuntu下:
win7下:
用ls()函數來查看scapy支持的網絡協議, (由于輸出內容太長,只截取部分以供參考)。
可以看到網工們耳熟能詳的ARP, BOOTP, Dot1Q, DHCP, DNS, GRE, HSRP, ICMP, IP, NTP, RIP, SNMP, STP, PPPoE, TCP, TFTP, UDP等等統統都支持。
除了ls()外,還可以用lsc()函數來查看scapy的指令集(函數)。比較常用的函數包括arpcachepoison(用于arp毒化攻擊,也叫arp欺騙攻擊),arping(用于構造一個ARP的who-has包) ,send(用于發3層報文),sendp(用于發2層報文), sniff(用于網絡嗅探,類似Wireshark和tcpdump), sr(發送+接收3層報文),srp(發送+接收2層報文)等等
這里還可以用使用ls()的攜帶參數模式,比如ls(IP)來查看IP包的各種默認參數。
實驗1
實驗目的:使用IP()函數構造一個目的地址為192.168.12.101(即拓撲中的PC2)的IP報文,然后用send()函數將該IP報文發送給PC2,在PC2上開啟抓包軟件以驗證是否收到該報文。
a. 首先用IP()函數構造一個目的地址為192.168.12.101的IP報文,將它實例化給ip這個變量。
ip = IP(dst='192.168.192.168.12.101')b. 用ls(ip)查看該IP報文的內容,可以發現src已經變為192.168.56.1(本機的IP),dst變為了192.168.12.101。 一個最基本的IP報文就構造好了。
ls(ip)c. 構造好了IP報文(src=192.168.56.1, dst=192.168.12.101)后,我們就可以用send()這個函數來把它發送給PC2了。
為了驗證PC2確實接收到了我們發送的報文,在PC2上開啟抓包功能。
在scapy上輸入 send(ip,iface='VirtualBox Host-Only Network')將該報文發出去,注意后面的iface參數用來指定端口,該參數可選。
抓包結果:
這時可以看到我們已經抓到了從192.168.56.1發來的IP報文,注意Protocol: IPv6 Hop-by-Hop Option (0),這是因為該包的proto位為0, 不代表任何協議。
實驗2
實驗目的:除了send()外,scapy還有個sendp()函數,兩者的區別是前者是發送三層報文,后者則是發送二層報文,實驗2將演示如何用sendp()來構造二層報文。
a. 用sendp()配合Ether()和arp()函數來構造一個ARP報文,命令如下
這里我們構造了一個源MAC地址為01:23:45:67:89:01, 源IP地址為192.168.56.1, 目標MAC地址為ff:ff:ff:ff:ff:ff,目標IP地址為192.168.12.101,payload為abc的ARP報文。
b. 可以另開一個控制臺,啟用sniff()來抓包,并將抓包的內容實例化到data這個變量上。
>>> data = sniff()使用show()命令監控本地的收發包情報
>>> data.show()注意是arp包,所以不能跨網段,需要在56段監聽才行:
可以看到該報文ARP部分的內容和ARP報文的結構完全一致
hardware type(HTPYE)為0x0001的時候,表示Ethernet
protocol type(PTPYE)為0x0800的時候,表示IPv4
hardware length (HLEN)為0x06的時候,表示MAC地址長度為6byte
protocol length(PLEN)為0x04的時候,表示IP地址長度為4byte
ARP包有request和response之分,request包的OPER(Opcode)位為0x0001 (也就是這里的who has), response包的OPER位為0x0002。
最后的payload位(padding)即為我們自己定制的內容'abc'。
實驗3
實驗目的:從實驗1和實驗2的例子可以看出:send()和sendp()函數只能發送報文,不能接收返回的報文。如果要想查看返回的3層報文,需要用到sr()函數,實驗3將演示如何使用sr()函數。
a. 用sr()向PC2發一個ICMP包,可以看到返回的結果是一個tuple(元組),該元組里的元素是兩個列表,其中一個列表叫Results(響應),另一個叫Unanswered(未響應)。
>>> sr(IP(dst = '192.168.43.1') / ICMP())這里可以看到192.168.43.1響應了這個ICMP包,所以在Results后面的ICMP:顯示1。
b. 如果向一個不存在的IP,比如192.168.43.2發ICMP包,那么這時會看到scapy在找不到該IP的MAC地址(因為目標IP 192.168.43.2和我們的主機192.168.43.1在同一個網段下,這里要觸發ARP尋找目標IP對應的MAC地址)的時候,轉用廣播。當然廣播也找不到目標IP,這里可以Ctrl+C強行終止。
sr(IP(dst = '192.168.43.2') / ICMP())c. 我們可以將sr()函數返回的元組里的兩個元素分別賦值給兩個變量,第一個變量叫ans,對應Results(響應)這個元素,第二個變量叫unans,對應Unanswered(未響應)這個元素。
ans, unans = sr(IP(dst = '192.168.43.2') / ICMP())d. 這里還可以進一步用show(), summary(), nsummary()等方法來查看ans的內容,這里可以看到192.168.43.114向192.168.43.1發送了echo-request的ICMP包,192.168.43.1向192.168.43.114回了一個echo-reply的ICMP包。
e. 如果想要查看該ICMP包更多的信息,還可以用ans[0](ans本身是個列表)來查看,因為這里我們只向192.168.2.11發送了一個echo-request包,所以用[0]來查看列表里的第一個元素。
ans[0]可以看到ans[0]本身又是一個包含了兩個元素的元組,我們可以繼續用ans[0][0]和ans[0][1]查看這兩個元素。
ans[0][0] ans[0][1]實驗4
實驗目的:實驗3講到了sr(),它是用來接收返回的3層報文。實驗4將使用srp()來接收返回的2層報文。
a. 用srp()配合Ether()和ARP()構造一個arp報文,二層目的地址為ff:ff:ff:ff:ff:ff,三層目的地址為192.168.56.0/24, 因為我們是向整個/24網絡發送arp, 耗時會很長,所以這里用timeout = 5,表示將整個過程限制在5秒鐘之內完成,最后的iface參數前面講過就不解釋了。
ans, unans = srp(Ether(dst = "ff:ff:ff:ff:ff:ff") / ARP(pdst = "192.168.56.0/24"), timeout = 5, iface = "VirtualBox Host-Only Network")b. 實驗環境56段有5臺設備,從上圖可以看到我們收到了5個answers,符合我們的實驗環境,下面用ans.summary()來具體看看到底是哪5個IP響應了我們的'who has'類型的arp報文。
ans.summary()這里可以看到192.168.56.1, 192.168.56.100, 192.168.56.101, 192.168.56.10, 192.168.56.253響應了我們的'who has'類型的arp報文,并且能看到它們各自對應的MAC地址。
c. 用unans.summary()來查看那些沒有回復'who has'類型arp報文的IP地址
unans.summary()實驗5
實驗目的:使用tcp()函數構造四層報文,理解和應用RandShort(),RandNum()和Fuzz()函數。
a. 實驗開始前,首先對外網絡接口進行抓包。
b. 在scapy上使用ip()和tcp()函數來構造一個目的地IP為http://www.baidu.com,源端口為30,目的端口為80的TCP SYN報文。
>>> ans, unans = sr(IP(dst = "www.baidu.com") / TCP(sport = 30, dport = 80, flags = "S"))c. TCP SYN報文發送后,監聽網卡的抓包軟件上發現了發出的報文
d. 在scapy上輸入ans[0]繼續驗證從主機發出的包,以及遠端收到的包。
ans[0]e. TCP端口號除了手動指定外,還可以使用RandShort(), RandNum()和Fuzz()這幾個函數來讓scapy幫你自動生成一個隨機的端口號,通常可以用作sport(源端口號)。
首先來看RandShort(),RandShort()會在1-65535的范圍內隨機生成一個TCP端口號,將上面的sport = 30 替換成 sport = RandShort()即可使用。
>>> ans, unans = sr(IP(dst = "www.baidu.com") / TCP(sport = RandShort(), dport = 80, flags = "S"))這里可以看到RandShort()替我們隨機生成了13116這個TCP源端口號
f. 如果你想指定scapy生成端口號的范圍,可以使用RandNum(),比如你只想在1000-1500這個范圍內生成端口號,可以使用RandNum(1000,1500)來指定,舉例如下:
ans, unans = sr(IP(dst = "www.bing.com") / TCP(sport = RandNum(1000,1500), dport = 80, flags = "S"))這里RandNum()幫我們生成了1246這個源端口號
由于我們指定的范圍是1000-1500,很有可能和一些知名的端口號重復,這個時候會出現sport顯示的不是端口號,而是具體的網絡協議名字的情況。
g. 最后來講下fuzz()函數,前面的RandShort()和RandNum()都是寫在sport后面的(當然也可以寫在dport后面用來隨機生成目的端口號),用fuzz()的話則可以省略sport這部分,fuzz()會幫你檢測到你漏寫了sport,然后幫你隨機生成一個sport也就是源端口號。
使用fuzz()的命令如下:
ans, unans = sr(IP(dst = "www.163.com") / fuzz(TCP(dport = 80, flags = "S")))這里看到fuzz()函數已經替我們隨機生成了7673這個源端口號
此后的內容為Scapy的實際應用,包括怎么使用Scapy進行TCP的SYN掃描、ACK掃描、FIN掃描、Xmas掃描, Null掃描,怎么使用Scapy執行TCP SYN flooding攻擊,ARP欺騙攻擊,DHCP饑餓攻擊,怎么用Scapy探測rogue DHCP服務器等等。
實驗6 -- TCP SYN掃描
實驗目的:使用TCP SYN掃描交換機L2-1(192.168.11.101)的53(DNS), 80 (HTTP), 23 (FTP)端口,知道如何判斷端口是被關閉了(closed)還是被過濾了(filtered),兩者各自有什么特征。
實驗原理:TCP三次握手的原理和過程相信大家都知道。根據RFC 793,當發送端的TCP SYN包發出后,大致會有下面四種情況發生:
知道實驗原理后來看代碼:
#!/usr/bin/env python # _*_ coding: utf-8 _*_ """@author: antenna@license: (C) Copyright 2019, Antenna.@contact: lilyef2000@gmail.com@software: @file: synscan.py@time: 2019/3/30 3:11@desc: """ from scapy.all import *target = 'www.cnblog.com'ans, unans = sr(IP(dst = target) / TCP(sport = RandShort(), dport = [21, 80, 53], flags = "S"), timeout = 5)for sent, received in ans:if received.haslayer(TCP) and str(received[TCP].flags) == "SA":print("Port " + str(sent[TCP].dport) + " of " + target + " is OPEN!")elif received.haslayer(TCP) and str(received[TCP].flags) == "RA":print("Port " + str(sent[TCP].dport) + " of " + target + " is closed!")elif received.haslayer(ICMP) and str(received[ICMP].type) == "3":print("Port " + str(sent[TCP].dport) + " of " + target + " is filtered!")for sent in unans:print(str(sent[TCP].dport) + " is filtered!")- 這里我們使用sr()函數對'www.cnblog.com'做端口21,80,53的TCP SYN掃描(注意flags = "S"), timeout設為5秒。sr()函數返回的是一個元組,該元組下面有兩個元素,一個是Results,一個是Unanswered,我們用ans來表示Results,也就是被響應的包,用unans來表示Unanswered,表示沒有被響應的包。
- ans和unans各自又含兩個包,一個是發出去的包,一個是接收到的包,以ans[0][0]和ans[0][1]為例,第一個[0]表示抓到的第一個包,第二個[0]和[1]分別表示第一個包里發出的包和接收到的包。舉例如下:
- 正因如此,所以下面for loop里的sent, received分別代表的是ans[0][0]、ans[0][1](抓到的第一個端口為22的包),ans[1][0]、ans[1][1](抓到的第二個端口為80的包)以及ans[2][0]、ans[2][1](抓到的第三個端口為53的包)里的內容
- haslayer()函數返回的是布爾值,用來判斷從接收端返回的包(received)里所含協議的類型,這里用來判斷該received包是否包含TCP協議,并且該包里TCP的flag位是否為SA, SA代表SYN/ACK,如果這兩個條件都滿足,則說明該端口在接收端是打開的(Open),然后將該信息打印出來。
- 同理,如果返回的包是TCP包,并且該TCP包的flag位為RA(RA表示Reset+),則說明該端口在接收端已經被關閉(closed),將該信息打印出來。
- 如果返回的包是ICMP包,并且該ICMP包的類型為3,則說明該端口被路由器或者防火墻過濾了(filtered),將該信息打印出來。
- 最后,如果發送端沒有收到任何回復(no response),我們同樣可以判斷該端口被路由器或者防火墻過濾了(filtered),將該信息打印出來。
執行代碼看效果:
- 目標網站如何,我也不清楚,查查看:
- 執行代碼后,會發現所有端口都是打開的
可以嘗試搭建環境,添加acl或防火墻來驗證更多的效果。
實驗7 -- 使用scapy分析路由
不說廢話,直接上代碼:
import os,sys,time,subprocess import warnings,loggingwarnings.filterwarnings("ignore", category=DeprecationWarning) logging.getLogger("scapy.runtime").setLevel(logging.ERROR) from scapy.all import traceroute domains = "113.108.238.121 180.96.12.11" # raw_input('Please input one or more IP/domain: ') target = domains.split(' ') dport = [80] if len(target) >= 1 and target[0]!='':res,unans = traceroute(target,dport=dport,retry=-2)res.graph(target="> test.svg", type="svg")time.sleep(1)subprocess.Popen(r"C:ImageMagickconvert test.svg test.png", shell=True) else:print("IP/domain number of errors,exit")代碼說明:
需要下載ImageMagick轉換生成的svg格式的路由圖到png格式。
代碼執行結果:
Begin emission: *********.*******.........*********Finished sending 60 packets. *******.Begin emission: Finished sending 28 packets. Begin emission: Finished sending 28 packets.Received 43 packets, got 32 answers, remaining 26 packets113.108.238.121:tcp80 180.96.12.11:tcp80 1 192.168.43.1 11 192.168.43.1 11 4 114.247.23.185 11 114.247.23.185 11 5 - 221.219.202.213 11 6 202.96.12.21 11 202.96.12.5 11 7 - 219.158.4.158 11 8 219.158.9.38 11 - 9 202.97.17.153 11 202.97.88.253 11 10 202.97.63.213 11 - 11 - 202.102.69.14 11 12 - 180.96.35.46 11 13 - 180.96.65.162 11 14 - 180.96.65.157 11 15 - 180.96.65.10 11 16 - 180.96.65.9 11 17 - 180.96.65.10 11 18 - 180.96.65.9 11 19 - 180.96.65.10 11 20 - 180.96.65.161 11 21 - 180.96.65.10 11 22 - 180.96.65.157 11 23 - 180.96.65.162 11 24 - 180.96.65.141 11 25 - 180.96.65.162 11 26 - 180.96.65.9 11 27 - 180.96.65.10 11 28 - 180.96.65.157 11 29 - 180.96.65.10 11 30 - 180.96.65.161 11 Process finished with exit code 0怎么早沒發現scapy還有這功能,太牛了。
總結
以上是生活随笔為你收集整理的cdt规约报文用程序解析_用Python运维网络(5):scapy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: talcid是什么药
- 下一篇: 耳朵电流声怎么消除