汽车安全测试CAN指南
CAN相关介绍
CAN
在汽车领域,CAN(Controller Area Network)是一种通信协议,用于在车辆电子系统中传输数据和命令。CAN总线是车辆中各个电子控制单元(ECU)之间进行通信的基础设施。
控制器局域网(CAN总线)是一种车辆总线标准,旨在允许微控制器和设备在没有主机的情况下与彼此的应用程序通信。这是一个基于消息的协议,最初设计用于汽车内的多路电气布线,以节省铜,但它也可以在许多其他环境中使用。对于每个设备,帧中的数据是串行传输的,但如果多个设备同时传输,最高优先级的设备可以继续,而其他设备可以退出。帧由所有设备接收,包括传输设备。^1
在CAN问世之前,车载通信系统是通过点对点的布线系统实现的。随着车载电子元件越来越多,这种通信系统变得愈发笨重,而且维护费用非常昂贵。这时,CAN应运而生,并成为主流的车载通信系统。
简单地说,CAN允许汽车中的不同电子模块相互通信并分享数据。CAN提案的主要动机是它允许多个ECU(ECU=发动机控制单元=汽车控制单元)仅用一根电缆进行通信。一辆现代汽车最多可以有70个ECU。

相关介绍文档
为什么要使用can
安全性:CAN是低级协议,不支持任何内在的安全功能。在标准的CAN中也没有加密,使得网络数据能被截取。在大多数应用中,应用程序需要部署自己的安全机制,例如认证传入命令或网络上某些设备的存在。若不执行适当的安全措施,其他人可能设法在总线上插入消息。尽管一些安全关键功能(如修改固件,编程键或控制防抱死制动)存在密码,但这些系统并未普遍实施,并且密钥对的数量有限。
通信机制:多主机,即每个节点都有接入总线的能力
寻址机制:消息区别,不设节点的地址,通过消息的标志符来区别消息。
帧类型:数据帧、远程帧、错误帧、超载帧、帧间隔
由于CAN总线上的数据包没有进行过任何的加密处理,因此这些数据包是能够被截取窃听。由于车载网络使用CAN协议进行通信,所以我们可以联想到车联功能也是通过CAN网络进行数据发送和交换。^4
为什么要使用CAN系统,毕竟还有许多其他的方式可以轻松实现呀?在发明CAN总线之前,汽车制造商使用点对点的布线系统。因此,如果您在汽车中有三个部件,则所有三个部件都需要通过三角形布线系统以点对点方式相互连接。
假设这三个部件是方向盘、变速箱和ABS。现在,在一个标准的点对点布线系统中,我们需要用线缆将转向系统与变速箱和防抱死系统连在一起,同时,变速箱也需要通过线缆与ABS和转向系统相连。
这对于组件较少的汽车来说是完美的解决方案。但是,如果一辆汽车拥有多达100个不同ECU和其他组件的话,情况会怎样?除了连线是一件苦差事外,检测布线系统中的故障也不轻松(如果还能检测到的话),这时,故障诊断将是一场真正的噩梦,而且成本高昂。
面对这种困局,汽车制造商提出了CAN的想法。大量的点对点接线,可以用两条线代替,分别是CANH和CANL,它们是CAN HIGH和CAN LOW的简写。现在,这种通信方式不仅更快、更简单,并且非常容易诊断故障。
CAN协议的使用在汽车行业中具有重要意义,有以下几个原因:
- 实时性和可靠性:CAN总线是一种实时通信协议,可以实现高速数据传输和可靠性的消息传递。这对于车辆中需要实时交换数据的系统至关重要,如发动机管理、刹车系统、安全气囊等。
- 多节点通信:CAN总线支持多个节点之间的通信,每个节点可以是一个电子控制单元(ECU)。这样,不同的车辆系统和子系统可以通过CAN总线进行相互连接和通信,实现整车的集成和协调操作。
- 简化布线:使用CAN总线可以大大减少车辆中的布线复杂性。相比于传统的点对点电气连接,CAN总线使用共享的双绞线来连接各个节点,降低了线缆数量和重量,简化了系统设计和维护。
- 灵活性和可扩展性:CAN总线具有良好的可扩展性,可以轻松地添加和移除节点,以适应不同车型和配置的需求变化。这种灵活性使得车辆系统的开发和升级更加方便和高效。
网络拓扑
CANbus是一种汇流排网路,他的汇流排是由两条线路所实现,当两条线路电位差小的时候为1,电位差大的时候为0。 |
数据格式
一辆车通常有多个能够发送和/或接收消息的节点。通常来说,每个消息都包含一个ID(表示消息的优先级),以及一个CAN报文,其中可以包含八个字节或更少内容。
如果两个或多个节点同时开始发送报文,则ID数字较低的节点发送的报文将替换ID数字较高的节点所发送的报文。这被称为基于优先级的总线仲裁。具有较低数值标识符的报文具有较高的优先级,并且总是首先发送。这就是节点在信道上定位和放置最高优先级报文的方式。
例如,来自制动器的报文的优先级,将高于来自音频播放器的报文。
请注意,较低的ID = 较高的优先级。
如果两个或更多的节点同时开始发送报文,以显性ID发送的报文将覆盖那些隐性ID报文。
CAN总线由两条不同的线缆组成。由于它是一条总线,许多设备都连接到它上面。一个CAN帧有3个主要部分,它们是:
仲裁标识符 |
CAN报文
下图展示的是我们记录下来的CAN报文。第一列是接口,第二列是仲裁ID,第三列是CAN报文的大小,第四列是CAN数据本身。

在这个例子中,我们将看到一个8字节的数据帧。该报文以ID 0x111发送。一旦仪表盘看到这个消息,它会首先判断它是否是为仪表盘准备的。如果是,那么它读取的信息将是0x0BB8,转化为十进制值为3000。现在,仪表盘将转速表上的指针移到3000的位置。
攻击方式
为什么要关注can
因为几乎每辆车都使用CAN,这是法律规定的,导致CAN不会很快停止使用。同时在设计CAN总线的开发中并没有考虑到现代安全问题。
要访问汽车的CAN总线,必须能够访问驾驶室诊断端口,也就是OBD。虽然当前的诊断标准和端口有数百种之多,但如今OBD-II已经成为常用端口,几乎所有汽车都使用这种诊断端口。在汽车修理工诊断汽车故障时,使用的就是它。
通过OBD可以直接访问CAN,并且是最直接的方式。另外,OBD-II也很容易找到:通常位于前排乘客或驾驶员座位附近的某个地方,而且不需要螺丝刀就能连接使用。
OBD 的样子如下所示:
OBD引脚的布局情况如下
第6和第14引脚为CANH和CANL
- 恶意消息注入:攻击者通过物理接入或软件漏洞向CAN总线注入恶意消息,干扰车辆系统的正常功能或引发安全问题。
- 报文重放攻击:攻击者拦截和重放CAN总线上的消息,以欺骗车辆系统执行未经授权的操作。
- 欺骗和伪装:攻击者伪造或伪装CAN总线上的消息,误导车辆系统做出错误判断或执行不安全的操作。
- 拒绝服务(DoS)攻击:攻击者发送大量无效或恶意的消息,导致CAN总线过载,影响车辆系统的正常功能。
- 未经授权的访问:攻击者未经授权地访问CAN总线,通过物理接触或其他方式获取对车辆网络的控制权。
- ECU固件攻击:攻击者利用ECU(电子控制单元)中的软件漏洞或弱点,获取对CAN总线的控制权。
- CAN总线窃听:攻击者通过拦截CAN总线上的消息来获取车辆的敏感信息,如速度、位置等。
- CAN总线分析和逆向工程:攻击者分析CAN总线的通信协议和消息格式,以理解车辆系统的工作原理,并可能发现漏洞。
- 车辆网络中间人攻击:攻击者通过插入中间设备或攻击节点,截取、篡改或注入CAN总线上的消息。
- 软件更新攻击:攻击者利用不安全的软件更新机制,通过CAN总线向车辆系统中注入恶意软件或固件。
通过OBD访问CAN
连接到OBD-II所需的硬件设备可以很容易在市场上找到,比较贵的包括Kvaser和EMS,它们不是一般的贵,而是太贵了。不过,我们可以选用USB2CAN,这是一个用于Linux系统的接口,大概60欧元左右。
基于ELM327和蓝牙的设备。测试比较不方便,因为数据速率较慢,会丢失大量的数据包。但相对比较便宜,约为10欧元
Macchina M2(价值85欧元)
Macchina M2是一个开源的汽车接口,可以用于通过OBD-II与CAN总线通信。Macchina M2的最大特点在于:它是模块化的,这意味着你可以在M2上添加WiFi、GSM、LTE、BLE。M2有2个CAN信道。此外,M2还支持LIN
CSS电子公司的CLX000,成本较低,它可以用来记录和传输CAN数据。这些数据可以通过免费的Wireshark开源软件进行显示,而且还有一个插件,可以帮助我们实现逆向分析。
CLX000是可视化和远程信息处理的理想选择。
环境相关
Macos 12.3 |
安装
SDL
SDL是一个用于计算机图形和音频的多平台开发库。ISCim使用了虚拟控制面板,并以动画的形式展示数据。
sudo apt-get install libsdl2-dev libsdl2-image-dev -y |
Can-utils
sudo apt-get install can-utils -y |
为了发送、接收和分析CAN数据包,我们需要用到CAN工具。Can-utils是一套Linux工具,它允许Linux与车内CAN网络进行通信。Can-utils主要由5个工具组成:
- cansniffer:用于嗅探数据包
- cansend:用于编写数据包
- candump:转储所有下载的数据包
- canplayer:用于重放CAN数据包
- cangen:用于创建随机的CAN数据包
ICSim
git clone https://github.com/zombieCraig/ICSim.git |
SavvyCan
SavvyCAN为我们提供了更多的功能。对于初学者来说,它提供了一个很好的GUI,可以帮助你轻松地浏览、过滤数据包、ID等
“SavvyCAN是一个基于多个QT平台的C++程序,主要用于CAN数据的逆向分析和捕获。它最初是为了介绍EVTVDue和CANDUE等EVTV硬件的用法而编写的。此后,它被扩展到适用于任何socketCAN兼容设备,以及Macchina M2和Teensy 3.x板。它可以同时捕获并发送至多个总线和CAN摄像机。”^7
wget https://github.com/collin80/SavvyCAN/releases/download/continuous/SavvyCAN-0f32533-x86_64.AppImage |
Wireshark
sudo add-apt-repository universe |
创建虚拟网络
ol4three@ubuntu:~/Desktop/ICSim-master$ cat setup_vcan.sh |
这里的modprobe命令是用来加载内核单元的,比如can和vcan。最后两行将创建一个vcan0接口,以模拟汽车网络。
ol4three@ubuntu:~/Desktop/ICSim-master$ ./setup_vcan.sh |
运行模拟器
./icsim vcan0 |
Vcan0是虚拟的CAN接口,ICSim将通过它发送和接收CAN帧。一旦启动控制面板,速度表会出现一些波动。这是由于控制面板所模拟的噪音而造成的。
启动控制面板后,我们就可以使用键盘上的按键来模拟各种运动。
使用以下组合键,可以对ICSim控制面板进行相应的修改:
功能 | 控制按钮 |
---|---|
转向 | 键盘左右 |
速度 | 键盘上下 |
开/关左前车门 | 右shift/左shit+A |
开/关右前车门 | 右shift/左shit+B |
开/关左后车门 | 右shift/左shit+X |
开/关右后车门 | 右shift/左shit+Y |
开启全部车门 | 左shift+右shift |
关闭全部车门 | 右shift+左shift |
可以看到我们启动车辆并打开了右侧的所有车门
数据传输
cangen
cangen可以为教育用途而创建各种CAN帧
CANGEN(1) User Commands CANGEN(1) |
cangen vcan0 |
打开wireshark查看can数据包,
candump
抓取记录can数据帧
CANDUMP(1) User Commands CANDUMP(1) |
使用candump来处理帧,可以使用如下命令
candump vcan0 |

每个数据帧的具体含义在上文已经介绍过了
candump还可以用来记录帧。在进行重放攻击时,需要先记录相应的帧,然后,用canplayer这样的小工具来重放这些帧。为了记录CAN帧,可以添加命令选项 -l
candump -l vcan0 |
效果如下
ol4three@ubuntu:~/Desktop/ICSim-master$ candump -l vcan0 |
canplayer
canplayer可以用来播放CAN帧;需要进行重放攻击时,使用canplayer重放这些CAN帧。
CANPLAYER(1) User Commands CANPLAYER(1) |
使用方法
canplayer -I canfile.log |
cansniffer
使用CAN嗅探器来查看CAN数据的变化。来查看特定字节的变化。Cansniffer有一个-c选项,能够通过颜色来展示字节的变化。这个工具的工作方式为:比较字节当前值和之前的值,如果存在差异,就用字节的颜色变化来加以表示。当你想知道当对汽车进行的操作是否导致CAN数据发生变化时,这个功能会非常有用。
CANSNIFFER(1) User Commands CANSNIFFER(1) |
还可以进行ID过滤。因此,如果只想查看来自某个特定ID的帧,比如说0x011,你可以根据ID进行过滤。
cansniffer -c vcan0 |

CAN帧的变化非常快,因为有大量数据高速传输。在一辆真正的汽车中,这是非常常见的。为此,我们可以使用ID进行过滤。如果你想只考察ID为40C的帧,你可以先按-,然后按000000,再按回车键,以从cansniffer中删除所有的ID对应的数据;然后,按+,然后按要过滤的ID,再按回车键即可。
cansend
Cansend用于将CAN帧发送到一个特定的CAN接口。
CANSEND(1) User Commands CANSEND(1) |
ICSim实战
candump命令来记录和保存帧
candump命令来记录和保存帧,与此同时,我们将通过按左、右方向键来加油门。
ol4three@ubuntu:~/Desktop/ICSim-master$ candump -l vcan0 |
canplayer重放数据帧
canplayer -I candump-2023-07-11_010451.log |
仪表板闪光灯以及速度表和我们刚刚的操作一样
在真实的汽车中,CAN总线可能会复杂得多,而且CAN帧的出现速度也会快得多,所以定位ID可能相当困难。因此,为了方便识别ID,可以使用二分法进行判断操作:
二分法分析车门数据帧
查看数据帧大小,并将其分割为2份,使用二分法就行对应的定位
ol4three@ubuntu:~/Desktop/ICSim-master$ wc candump-2023-07-11_010659.log |
可以看到多出了poc1aa和poc1ac两个数据帧可以对两个数据帧进行筛选排查,通过二分法我们找到了左前侧开门的数据包
vcan0 19B#00000E000000 |
我们重新抓取CAN数据帧,依次进行开门相关操作在日志中寻找所有的ID值为19B的数据
(1689072859.589432) vcan0 19B#00000F000000 |
最终分析确定部分can数据帧,其他数据帧保存为车门当时状态可自行分析
操作 | can数据帧 |
---|---|
开左前门 | 19b#00000e000000 |
开右前们 | 19b#00000c000000 |
开左后门 | 19b#000008000000 |
开右后门 | 19b#000000000000 |
开启全部车门/关闭全部车门 | 19b#000000000000/19B#00000F000000 |
SavvyCan分析车门数据帧
更为简单方法为抓取两次数据包时间稍微长一些,并查找新增数据包即可

通过SavvyCan来分析车门开启状态
SavvyCan转向数据帧分析
使用分析车门的方法进行分析数据帧发现由于控制面板所模拟的噪音导致无法进行区分

首先使用二分法对数据包进行切割,然后使用SavvyCan分析缩小范围
逐帧分析即可发现对应指令
ol4three@ubuntu:~/Desktop/ICSim-master$ cat car1ab.log | grep 188# |
SavvyCan分析加速数据帧
打开SavvyCan并添加对应的配置
创建好之后即可在Savvy中看到can数据包
可以从右窗格中剔除不需要的ID,这样,就可以快速识别相关的ID。
另一个非常好的功能是“替换模式”。如果启用此选项,将以相同的顺序替换帧。
重放攻击
可以使用Send Frames-> Playback 使用抓取到的数据帧或者数据帧文件进行重放
嗅探数据包
我们通过Sniffer对id进行筛选,查看当速度增加时其如何变化
最终发现0x244就是我们要找的了,随着速度的增加,可以看到转速表显示第3和第4字节的变化(从第0个字节开始计数)
数据发送
同时也可以通过SavvyCan进行数据帧的发送。发送到总线0,ID 0x244(转速计),数据为0x00 0x00 0x00 0x00 0x00,并且每次将第三个字节增加1,所以在修改中,写入d3 = d3+1结果如下,可以看到我们已经找到了控制转速的数据帧
通过cansend进行验证
ol4three@ubuntu:~/Desktop/ICSim-master$ cat speed-car.py |
效果如下