1. 描述
使用scapy進行以太網幀的注入,相對於RAW_SOCKET還是比較簡單的。在講述packet注入之前,先了解一下scapy偽造以太網幀的相關知識。下圖為以太網幀格式和scapy對應的封裝包格式。
2. 示例
2.1 使用scapy構造IP數據包
進入scapy環境,輸入以下代碼:
>>>
>>> pkt = IP()/ICMP()/”hello”
>>>
>>>
>>> pkt.show()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= icmp
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
###[ Raw ]###
load= ‘hello’
上面代碼的意思是,構造一個pkt的包,在IP層中封裝了ICMP包,負載的數據位“hello”。通過pkt.show()
函數顯示包的詳細信息。
2.2 發送packet
- sendp——在第二層次上發送數據包。需要給定正確的網卡接口。
- send——在第三層次上發送數據包。根據本地的路由表來進行路由發送。
- 循環發送相同的包。
- 間隔幾秒發送一次包。
2.2.1 第三層次上發送包(layer 3)
首先,我們在第三層次上發送packet來做測試。在這之前先另起一個終端,輸入以下命令,對流量做一下監聽。
tcpdump -i eth0 -XX -vvv icmp
然后運行send(pkt)
命令發送數據包,觀察結果:
監聽結果:
從結果上看,我們發送了一個ICMP請求包,收到了百度的一個ICMP答復包,還可以看到我們發送的數據。
####2.2.2 第三層次發送包(layer 3)
使用重構數據包,然后用sendp()函數發送。
sendp(Ether()/IP(dst= "www.baidu.com")/ICMP()/"XXX",iface="eth0")
Ether()構造以太網幀,和第三層次不同的是,在第二層次上發送要指定網卡接口, 這里我使用eth0。執行代碼,成功發送一個數據包。如果想要循環發送,可以使用loop選項。
sendp(Ether()/IP(dst= "www.baidu.com")/ICMP()/"XXX",iface="eth0",loop=1)
代碼執行后,會快速的循環發送這個數據包,使用ctrl+C結束。
如果想在兩次發送數據包之間有一定的時間間隔,使用inter選項。
sendp(Ether()/IP(dst= "www.baidu.com")/ICMP()/"XXX",iface="eth0",loop=1,inter=1)
表示每隔1秒發送一個數據包。
2.3 在層次2和層次3上發送和接收包
- 層次3
- ——sr()。返回答復和沒有答復的包。
- ——sr1()。返回僅僅答復或者發送的包。
- 層次2
- ——srp()
- ——srp1()
執行sr(IP(dst="www.baidu.com")/ICMP()/"XXX")
,觀察執行結果:
成功發送了一個數據包,接收到了2個數據包,其中一個為答復包。這是我要集中注意的地方。將收到的數據賦值給自定義的變量,並查看。
使用sr1()函數,效果: