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的使用套路了。