3、CAN总线基础:CAN协议帧结构、CAN ID与数据域、CAN总线仲裁机制
各位同学,今天我们聊CAN总线。说实话,搞ADAS安全测试,CAN总线是绕不过去的坎。你想想看,车上几十个ECU,全靠这条总线在通信。我刚开始接触车载安全时,第一件事就是把CAN协议啃透。嗯,今天我们就从帧结构、ID和数据域,再到仲裁机制,一层层剥开来看。
3.1 CAN协议帧结构——报文长什么样?
CAN总线上的数据,是以“帧”为单位传输的。我个人习惯把帧想象成一个信封,里面装着你要发的消息。CAN协议定义了四种帧类型:数据帧、远程帧、错误帧和过载帧。我们做渗透测试,最常打交道的是数据帧和远程帧。
数据帧的结构,我拆开给你看:
- 帧起始(SOF):1个显性位,告诉总线“我要开始发消息了”。
- 仲裁场:包含CAN ID和RTR位。这里决定了谁能抢到总线。
- 控制场:包含IDE位、保留位和DLC(数据长度码)。DLC告诉你后面数据域有几个字节。
- 数据场:0~8字节,这就是实际传输的数据。我们做攻击模拟时,改的就是这里。
- CRC场:15位CRC校验,加上1位CRC界定符。用来检测传输错误。
- ACK场:接收节点如果正确收到,会在ACK槽位发送显性位确认。
- 帧结束(EOF):7个隐性位,表示帧结束。
重点记忆:数据场最多8字节。很多新手问我为什么这么短?因为CAN总线设计初衷是实时控制,不是传大文件。8字节足够传递转速、车速、刹车状态这些关键信号了。
我在项目中遇到过一件事:某次测试时,我们往总线上灌了一个DLC=0的数据帧,结果接收节点直接忽略。后来查手册才发现,DLC=0表示数据域为空,但帧本身是合法的。这个细节,做模糊测试时特别有用。
3.2 CAN ID与数据域——你改的就是这里
CAN ID,说白了就是报文的“身份证”。它决定了两个事情:一是报文的优先级,二是报文的内容标识。标准帧的ID是11位,扩展帧是29位。做ADAS安全测试,我建议你重点关注标准帧,因为大部分ADAS相关报文用的都是11位ID。
数据域呢?就是那0~8个字节。每个字节、每个bit都可能代表一个物理信号。比如:
| 字节位置 | 信号含义 | 常见值 |
|---|---|---|
| Byte 0 | 车速(高字节) | 0x00~0xFF |
| Byte 1 | 车速(低字节) | 0x00~0xFF |
| Byte 2 | 方向盘转角 | 0x00~0xFF |
| Byte 3~7 | 保留/其他信号 | 视协议而定 |
举个例子。假设你抓到一条CAN报文:ID=0x158,数据=0x41 0x00 0x32 0x00 0x00 0x00 0x00 0x00。根据DBC文件解析,Byte0=0x41表示车速65km/h,Byte2=0x32表示方向盘转角50度。你看,就这么简单。
我的经验:做渗透测试时,我经常先抓一段正常报文,然后逐字节修改数据域,观察车辆行为变化。比如把车速报文中的Byte0改成0xFF,看看仪表盘会不会显示255km/h。这种“数据篡改”攻击,是ADAS安全测试的经典手法。
3.3 CAN总线仲裁机制——谁先说话?
这个问题很有意思。CAN总线是多主总线,意味着多个节点可以同时发送。那冲突了怎么办?靠仲裁。
仲裁机制的核心是:ID越小,优先级越高。具体怎么实现的?我简单说下:
- 所有节点同时发送帧起始位(显性位),总线状态为显性。
- 接着发送ID位。如果某个节点发送隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发,这个节点就自动退出发送,转为接收。
- 这个过程是逐位比较的,直到剩下一个节点胜出。
你想想看,这就像一群人同时喊话,谁嗓门大(ID小)谁就能继续说下去。我曾经在测试中遇到过一个问题:两个ECU同时发送相同ID的报文,结果总线一直冲突,导致通信瘫痪。后来发现是软件bug,没有做发送去重。
避坑指南:我曾经在测试ADAS系统时,往总线上发送了一个ID=0x000的报文。结果所有节点都退出了发送,因为0x000是最高优先级。整个总线被我的测试设备占用了,其他ECU发不出任何消息。嗯,这个教训告诉我:测试时千万别乱发0x000,否则车辆可能直接“失联”。
仲裁机制还有一个关键点:数据帧优先级高于远程帧。因为数据帧的RTR位是显性位(0),远程帧是隐性位(1)。所以,如果数据帧和远程帧同时发送,数据帧胜出。这个细节,做攻击模拟时可以利用——比如发送大量高优先级数据帧,把低优先级的远程帧饿死。
3.4 实战视角:这些知识怎么用?
好了,理论讲完了。我们聊聊实战。做ADAS系统安全测试,CAN总线知识至少用在三个地方:
- 报文嗅探:你得能看懂抓到的CAN报文,知道ID代表什么,数据域怎么解析。
- 攻击注入:伪造报文时,你得选对ID(优先级要够高),填对数据(要能骗过接收节点)。
- 拒绝服务:利用仲裁机制,发送高优先级报文抢占总线,让其他ECU无法通信。
我记得有一次做渗透测试,目标车辆的ADAS系统会在收到特定ID的报文后执行紧急制动。我通过逆向DBC文件,找到了那个ID和数据格式。然后我伪造了一条报文,在测试场地上让车辆在30km/h时突然刹停。嗯,效果很震撼,但也提醒我们:这种攻击一旦被恶意利用,后果不堪设想。
总结一句话:CAN总线是ADAS系统的神经,帧结构是神经的骨架,ID是神经的标签,仲裁是神经的规则。搞懂这些,你才能做后续的攻击模拟和防御设计。
下一章,我们会深入CAN总线的物理层和链路层特性,聊聊如何用硬件工具抓取和注入报文。到时候,我会带大家实操一把,用实际工具演示如何“劫持”一条CAN报文。敬请期待。