0.前言
最近現場測試項目時,突如其來需要僞造IGMP封包,騙取交換機相關多點傳播流量,慌忙之下學習了Scapy的使用,以及相關快速學習的方法,在這裡分享下。
1.Scapy庫安裝
github位址:https://github.com/secdev/scapy
安裝過程:見官方文檔
筆者方案:
$ git clone https://github.com/secdev/scapy.git
$ cd scapy
$ sudo python setup.py install
2.模拟發送封包
理論上Scapy可以發送任意封包,但相對造輪子的工作較為辛苦,幸運的是,官方提供了現成的封包庫,我們可以利用這些輪子輕松造出符合期待的封包。在選擇想要發送的封包時,最好在scapy貢獻庫上看下相關字段及協定,否則會出現造好封包無法發送的情況下。
下面以發送IGMP Membership Report 封包為例,分享下使用的心得。
2.1 IGMPv3 Membership Report
官方貢獻庫:igmpv3.py
我們在官方庫裡發現了有好幾個類,比如:IGMPv3 、IGMPv3mq 、IGMPv3mr ,可是要怎麼用呢?雖然了解了相關協定的建構,但是看了這些使用起來還是略吃力,比如我們要發送IGMPv3 Membership Report可能要用到IGMPv3gr 這個類,于是筆者跟着自己的了解以及網上的教程試了起來,發現還是沒有成功發出去,一度懷疑人生。情急之下便将IGMPv3gr作為關鍵字在github進行搜尋,看下有沒有相關例子,結果老天還是可憐笨小孩,搜完後竟發現了新天地,下面貼個連結,大家可從連結發現大量的IGMPv3gr相關的例子,筆者對着github公開的代碼示例進行了嘗試,不過一會便成功了,這裡感謝github這個優異的社群,下面貼下筆者模仿寫的發送封包:
from scapy.all import *
from scapy.contrib.igmpv3 import IGMPv3,IGMPv3mq,IGMP,IGMPv3gr
from scapy.contrib.igmpv3 import IGMPv3mr
p_join = Ether(dst='01:00:5e:00:00:16', src='00:0c:29:c8:31:8a') / IP(src='192.168.204.139', dst='224.0.0.22', tos=0xc0) /IGMPv3() /IGMPv3mr(numgrp=1) /IGMPv3gr(rtype=4, maddr="239.1.1.1")
p_join.show()
sendp(p_join,iface='eth0')
編寫完畢,執行
sudo python xxx.py
,便可将封包發送出去,可通過wireshark或tcpdump驗證封包是否發送。
2.2 IGMPv2 Membershrp Report
官方貢獻庫:igmp.py
根據以上方法,同樣收到igmp的使用方法,下面貼下代碼:
from scapy.all import *
from scapy.contrib.igmpv3 import IGMPv3,IGMPv3mq,IGMP,IGMPv3gr
from scapy.contrib.igmpv3 import IGMPv3mr
from scapy.contrib.igmp import IGMP
import time
import IPy
testIpArr = ["238.1.3.21"]
while True:
for i in range(len(testIpArr)):
ip = testIpArr[i]
ipIpy = IPy.IP(ip);
ipYan = ipIpy.strBin()[-23:];
ipYan = '0000000100000000010111100' + ipYan
mac = hex(int(ipYan, 2))[2:]
if (len(hex(int(ipYan, 2))[2:]) < 12):
for j in range(12 - len(hex(int(ipYan, 2))[2:])):
mac = '0' + mac
mulMac = mac[0:2] + ':' + mac[2:4] + ':' + mac[4:6] + ':' + mac[6:8] + ':' + mac[8:10] + ':' + mac[10:12]
print ip
print mulMac
p_join = Ether(dst=mulMac, src='a0:8c:fd:9e:2d:f1') / IP(src='10.0.0.123', dst=ip, ttl=1) /IGMP(type=0x16,gaddr=ip,mrcode=0x00)
sendp(p_join,iface='eth0')
print '----------------'
time.sleep(5)
其中
IPy
是有關代碼IP位址的轉換的庫,大家可參照這篇博文:Python之實用的IP位址處理子產品IPy。IGMPv2需要注意目的IP及目的Mac的對應關系,否則會出現封包雖發送了,卻被交換器丢棄,進而無法騙取流量的情況,具體可以參考這篇博文:多點傳播IP位址與多點傳播MAC位址之間的換算方法 。
結語
筆者學習scapy的方法較為讨巧,對于初學者來說較為友好,不過相對考驗github上scapy的資源,當然用多了漸漸也就能學會scapy的使用套路了。