汽车安全入门:OBD-II 与 CAN 总线抓包分析完整指南(2026)

一句话概括:OBD-II 是每辆车都有的诊断插座,CAN 总线是车上各个 ECU 之间传递指令的内部网络。把一根线接到 OBD 口,你就能看到这辆车”说话”的内容。本文从硬件采购讲到 Linux 抓包,再到把一堆十六进制读成”车速 60km/h、转速 1726rpm”,最后落到安全防护与合规要求。

适合人群:有一定 Linux 基础、想进入车联网安全方向的学习者 · 难度:入门到中级 · 预计阅读 18 分钟 · 全部实操可在虚拟总线复现

⚠️ 请先读这一段,再往下看

汽车安全是授权制领域,不是”技术中立”。

  • 只对你本人名下的车辆、或取得书面授权的车辆/实验台架动手;
  • 不要在公共道路、他人车场、租赁车、二手待售车上做任何测试;
  • 抓包阶段只监听、不发送(listen-only),本文所有发送命令都在虚拟总线或台架上演示;
  • 绝不修改里程表、防盗系统、排放数据——这已经不是技术问题,是刑事问题;
  • 车辆在行驶中不要插拔 OBD 设备,误发帧可能导致动力/制动系统进入保护状态。

本文第 11 节给出的 ICSim 方案零风险,建议先在虚拟环境把流程走通,再碰真车。

一、为什么 2026 年值得学汽车安全

三件事同时发生了,把这个方向推到了台前。

第一,攻击面外扩。传统汽车的安全边界就是那个 OBD 口——想攻击得先物理接触。现在 T-Box、蓝牙钥匙、手机 App、OTA 升级、V2X 通信全都连上来了。2023 年以后的量产车,单车 ECU 数量普遍在 70 到 150 个之间,信号总量以万计,CAN/CAN-FD 依然是车身与动力域的主干。

第二,法规强制。联合国 UN R155(网络安全)与 UN R156(软件升级)2022 年 7 月起对新车型强制,2024 年 7 月起覆盖所有新下线车辆,配套的 ISO/SAE 21434 成了主机厂和 Tier1 的流程标准。国内对应的 GB 44495-2024《汽车整车信息安全技术要求》和 GB 44496-2024《汽车软件升级通用技术要求》于 2024 年 8 月 23 日发布,自 2026 年 1 月 1 日起正式实施——也就是现在。

第三,入门成本极低。一套能用的硬件两百块上下,软件全免费开源。对比移动端要脱壳、要过反调试,CAN 总线这个入口干净得像是二十年前的 Web——没有鉴权、没有加密、没有签名,谁在总线上谁就能发言。

💡 学习路径建议

物理层 → 抓包工具 → 帧语义 → 诊断协议(ISO-TP / UDS)→ 逆向方法论 → 攻击面与防护。前四步两三个晚上就能走完,真正花时间的是第五步:从”能看懂帧”到”能定位某个功能对应哪几条 ID”。

二、60 秒搞懂 CAN 总线

2.1 物理层:两根线的差分信号

高速 CAN(HS-CAN)用的是一对双绞线,叫 CAN-H 和 CAN-L。它不是靠对地电压判断 0 和 1,而是靠两条线的电压差。

状态 CAN-H CAN-L 差分电压 逻辑值
隐性(Idle / 空闲) ≈2.5V ≈2.5V ≈0V 1
显性(Dominant) ≈3.5V ≈1.5V ≈2V 0

差分传输的好处是共模干扰会被抵消——发动机点火、电机逆变器产生的噪声同时叠加在两根线上,做减法就消掉了。这也是 CAN 能在电磁环境极差的发动机舱里活到今天的原因。

总线两端各要接一个 120Ω 终端电阻,用于吸收信号反射。两端并联后,你断电用万用表量 OBD 口 6 脚与 14 脚之间,读数应该在 60Ω 左右。如果量到 120Ω,说明有一端断路;量到无穷大,说明这条 CAN 根本没接到 OBD 口(有些车型的诊断 CAN 和动力 CAN 是分开的)。

2.2 帧结构:一帧最多 8 个字节

经典 CAN 一帧的结构如下,标准帧(11 位 ID)全长 108~111 位左右(含位填充):

SOF ID RTR IDE r0 DLC Data CRC ACK EOF IFS
1 bit 11 bit 1 bit 1 bit 1 bit 4 bit 0~8 字节 16 bit 2 bit 7 bit 3 bit

三个关键点:

  • ID 决定优先级,不是决定目的地。CAN 是广播总线,每一帧所有节点都能收到。ID 越小(二进制里显性位越多)优先级越高。两个节点同时发,低 ID 的赢,输的那个自动重发——这叫非破坏性仲裁,不会丢数据。
  • 没有源地址,也没有目标地址。接收方靠 ID 过滤,靠 DLC 和负载内容的约定解释含义。这个约定就是后面要讲的 DBC 文件。
  • CAN-FD 是升级版。数据段最多 64 字节,速率可到 5Mbps(仲裁段仍用低速保证兼容)。新势力车型上已经大量使用,但本文先讲经典 CAN,原理一致。

2.3 速率

动力/底盘域通常是 500 kbps,车身舒适域常见 250 kbps 或 125 kbps,少数老车用 33.333 kbps。速率必须精确匹配,差一点就一个字节都收不到——这是新手最常踩的坑。

三、硬件怎么买

核心原则:要能收发任意帧,不要买 ELM327。

设备 芯片/方案 能否监听任意帧 参考价 评价
ELM327(各种克隆版) STN1110 / PIC 克隆 ❌ 只做标准 PID 轮询 ¥30~60 只能读故障码和少量 PID,玩不动抓包。别买。
CANable 2.0 / M8 gs_usb(candleLight 固件) ✅ ¥150~300 入门首选,Linux 免驱,插上就是 can0
USB2CAN(国产) 各家自研 ✅ ¥100~200 便宜好用,注意要装厂商驱动
CANalyst-II / ZLG USBCAN 国产专业方案 ✅ ¥300~800 稳定性好,Windows 工具链成熟
PCAN-USB / Kvaser PEAK / Kvaser ✅ ¥1500+ 工业级,时序精度高,做研究/写报告用
树莓派 + MCP2515 HAT SPI 转 CAN ✅ ¥200~400 适合做车载常驻记录仪

另外还要准备:

  • OBD 转接线/转接板:把 16 针 OBD 口引出成 6/14 两根线 + 电源,几块钱一根但极大提升体验;
  • 万用表:量终端电阻和电平,判断接线对不对;
  • 杜邦线/鳄鱼夹:部分车型 OBD 口被盖板挡住,需要从线束侧取信号;
  • 一台跑 Linux 的笔记本:Kali、Ubuntu 都行,虚拟机也行(USB 直通给虚拟机)。

关于供电:OBD 口 16 脚是常电 12V,4 脚和 5 脚是地。如果要给树莓派供电,务必加保险丝并用降压模块(12V→5V),直接从 16 脚取电烧过车的人不在少数。

四、找到 OBD 口,先量一量

OBD-II 是 16 针梯形接口,位置一般在方向盘下方靠左,部分车型在中央扶手箱里或副驾脚部。针脚定义(ISO 15765-4):

针脚 定义 说明
4 底盘地 Chassis Ground 车身金属
5 信号地 Signal Ground ECU 参考地
6 CAN-H 高速 CAN 高
7 K-Line 老车用,ISO 9141
14 CAN-L 高速 CAN 低
16 常电 +12V 直接连蓄电池

三步验证:

  1. 断电测电阻:钥匙拔掉,万用表电阻档量 6-14 脚,读数 55~65Ω 说明总线和终端电阻正常。
  2. 上电测电平:钥匙拧到 ON,直流电压档量 6 脚对 4 脚,应接近 2.5V;14 脚也接近 2.5V。
  3. 看有没有数据:接到适配器上抓 10 秒,如果全是零流量,先怀疑速率错了,再怀疑这条 CAN 没引到 OBD 口(很多车 OBD 只接了诊断 CAN,动力 CAN 走另一条支路)。

注意:部分车型的 OBD 口只暴露诊断 CAN(网关后面的那一段),你抓到的是网关转发的报文,不是动力 CAN 的原始流量。想要原始流量,得拆中控从网关侧或 CAN 分配器取信号——这一步就涉及拆车了,务必在授权和保险前提下进行。

五、十分钟搭好 Linux 抓包环境

以 Kali/Ubuntu 为例,can-utils 是全部工作的基础。

sudo apt update
sudo apt install -y can-utils

# 插入 CANable(gs_usb)后,内核会自动创建 can0
ip link show type can

# 启动接口,波特率按实际填(500k 最常见)
sudo ip link set can0 up type can bitrate 500000

# 看看状态
ip -details -statistics link show can0

如果设备不叫 can0,用 dmesg | tail 看它被识别成什么名字。gs_usb 方案通常开箱即用;国产 USB2CAN 需要装厂商的 .ko 驱动并手动 modprobe。

速率不对怎么办?CAN 对时序极其敏感,500k 的接口收到 250k 的流量就是一片错误帧。可以先扫一遍常见速率:

for br in 125000 250000 500000 1000000; do
  echo "== try $br =="
  sudo ip link set can0 down 2>/dev/null
  sudo ip link set can0 up type can bitrate $br
  timeout 2 candump -n 5 can0 || true
done

哪一档能抓到帧,就是哪一档。少数非标速率(比如 33333)需要额外给 sample-point 参数,或者换支持自定义时钟的方案。

六、第一帧:把数据抓下来

最基础的命令是 candump,它把总线上每一帧打印成一行:

# 实时打印
candump can0

# 只看某几个 ID(7DF 是诊断请求,7E8 是发动机 ECU 响应)
candump can0,7DF:7FF

# 存成日志,后面分析
candump -l can0        # 生成 candump-2026-10-21_120000.log

# 回放日志(虚拟总线上演示用)
canplayer -I candump-2026-10-21_120000.log

输出长这样,从左到右依次是:接口名、ID、DLC、8 个字节的数据。

can0  7DF   [8]  02 01 00 00 00 00 00 00
can0  7E8   [8]  06 41 00 BE 3F A8 13 00
can0  201   [8]  00 00 00 00 00 00 00 00
can0  0C9   [8]  1A 00 3C 00 00 00 00 00
can0  3D1   [8]  00 0F 8C 00 00 00 00 00

另一个非常有用的工具是 cansniffer:它按 ID 分组,实时刷新每个 ID 最新一帧的内容,并给变化的字节高亮反色。定位”哪个字节在动”比一行行翻日志快得多。

cansniffer -c can0

再配一个带宽监控,判断总线负载:

canbusload can0@500000

七、读懂数据:周期、ID、负载

先把日志做一次统计,摸清这辆车的”说话节奏”。用 candump -l 存下来的日志是文本格式,可以直接用 awk 处理:

# 统计每个 ID 出现的次数,按次数排序
awk '{print $3}' candump-*.log | sort | uniq -c | sort -rn | head -30

你会发现一个规律:绝大多数车身信号是周期性广播的,周期常见 10ms、20ms、100ms、500ms、1s。周期越短,通常越关键(比如轮速、扭矩、转向角)。

判断周期的土办法是数一个 ID 在 1 秒内出现几次:

timeout 1 candump -n 10000 can0,0C9:0C9 | wc -l
# 输出 100 左右 → 10ms 周期;输出 10 左右 → 100ms 周期

再看哪些字节在变。车辆静止怠速时,绝大多数字节不变,只有转速、水温、电压这几个在动。把车挂挡起步,再抓一段对比——变化的字节就暴露出”油门/车速”这类信号的载体。

💡 速记:字节序

CAN 里的多字节信号大多是大端(Motorola)排列,也就是高位字节在前。你看到的 1A F8 应该读成 0x1AF8,不是 0xF81A。极少数厂商用 Intel 小端,遇到对不上的值先怀疑字节序。

八、诊断层:0x7DF 与 ISO-TP

到这里你抓的是”广播流量”。而 OBD 诊断走的是请求-响应模式,这才是能直接读懂车辆状态的部分。

8.1 请求 ID 与响应 ID 的对应关系

功能寻址 物理寻址范围 响应范围 说明
0x7DF 0x7E0~0x7E7 0x7E8~0x7EF 0x7DF 是广播请求,所有 ECU 都会应答;0x7E0 起是点对点

经验公式:响应 ID = 请求 ID + 8。你发到 7E0,发动机 ECU 从 7E8 回你;发到 7E1,变速箱从 7E9 回。

8.2 ISO-TP:把长数据切成多帧

CAN 一帧只有 8 字节,但 UDS 诊断消息经常几十上百字节,所以有 ISO 15765-2(ISO-TP)做分片与重组。首字节的高 4 位就是帧类型:

高 4 位 类型 含义
0x0 Single Frame 单帧,低 4 位是数据长度
0x1 First Frame 多帧的第一帧,低 4 位 + 下一字节共 12 位表示总长度
0x2 Consecutive Frame 后续帧,低 4 位是序号(从 1 递增)
0x3 Flow Control 接收方告诉发送方”继续发 / 等一下”

抓包时你会看到一长串 21 / 22 / 23 ... 开头的帧,就是连续帧;中间夹着的 30 00 00 是流控。

8.3 实战:读转速和车速

服务 0x01 是”读当前数据”,PID 0x0C 是转速,PID 0x0D 是车速。请求报文 02 01 0C 表示:长度 2、服务 01、PID 0C。

# 在台架/虚拟总线上发送请求
cansend can0 7DF#02010C0000000000

# 抓响应
candump can0,7E8:7EF

收到这样一帧:

can0  7E8   [8]  04 41 0C 1A F8 00 00 00

拆解:04 是 ISO-TP 单帧长度(后面 4 个有效字节),41 = 服务 0x01 + 0x40(正响应标志),0C 是 PID,1A F8 是两个数据字节。

转速公式:((A × 256) + B) / 4

A = 0x1A = 26
B = 0xF8 = 248
((26 × 256) + 248) / 4 = (6656 + 248) / 4 = 1726 rpm

车速 PID 0x0D 更简单,一个字节直接就是 km/h:03 41 0D 3C → 0x3C = 60,即 60km/h。

常用 PID 记住这几个就够日常用:

PID 含义 换算
0x05 冷却液温度 A − 40(℃)
0x0C 发动机转速 ((A×256)+B)/4(rpm)
0x0D 车速 A(km/h)
0x11 节气门开度 A×100/255(%)
0x2F 燃油液位 A×100/255(%)
0x42 控制模块电压 ((A×256)+B)/1000(V)

九、逆向方法论:差分采集定位功能帧

广播帧没有文档,只能靠”实验 + 对比”。核心方法是单变量差分:保持其他一切不变,只改变一个动作,看哪几个字节跟着变。

  1. 采基线:车辆静止、点火、所有电器关闭,抓 30 秒存为 base.log。
  2. 改一个变量:只开左转向灯,抓 30 秒存为 left.log。
  3. 做差分:对比两个日志里同一 ID 的负载,字段从 00 变 01 的那一位就是转向灯状态。
  4. 验证:关掉转向灯再抓一次,确认字段回到 00;再开右转向灯,确认是另一个 bit。

用 Python 做自动差分,比肉眼翻日志靠谱得多:

import collections

def load(path):
    db = collections.defaultdict(list)
    for line in open(path):
        p = line.split()
        if len(p) < 5 or not p[1]: continue
        db[p[1]].append(p[4:])
    return db

a, b = load('base.log'), load('left.log')
for cid in sorted(set(a) & set(b)):
    fa, fb = a[cid][-1], b[cid][-1]
    if fa != fb:
        print(cid, ''.join(fa), '->', ''.join(fb))

输出里同时变化、且只在开灯时变化的 ID,就是候选。通常一个功能由 1~3 个字节承载,可能有冗余(网关会同时转发到舒适 CAN 和诊断 CAN)。

💡 更高效的做法

把 candump -l 的日志导入 SavvyCAN 或 cabana,它们能把每个 ID 的字节画成曲线。开灯那一瞬间曲线上出现方波,一眼就能定位到具体 bit,比写脚本快。

十、零风险练习:ICSim 虚拟台架

真车成本高、风险大,先用 ICSim 把整套流程走通。它是 OpenGarages 出的仪表盘模拟器,用 socketCAN 的虚拟总线。

# 1. 建一条虚拟 CAN 总线
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

# 2. 编译并运行
git clone https://github.com/zombieCraig/ICSim.git
cd ICSim && make
./icsim vcan0          # 仪表盘窗口
./controls vcan0       # 控制窗口

控制窗口里用方向键加速、刹车、打转向灯,同时另开一个终端 candump vcan0,你会看到仪表盘动作对应的帧实时出现。这就是”动作 → 帧”的因果链,在真车上你要花一整天才能建立,这里五分钟。

还可以直接把文献里公开的 ID 打进去验证理解:

cansend vcan0 244#0000000000   # 转向灯
cansend vcan0 191#0000000000
cansend vcan0 3E9#0000000000

做完这一步,你就具备了在授权车辆上复现的完整肌肉记忆:接线、设速率、抓包、过滤、差分、验证。

十一、用 DBC 把十六进制变成人能读的信号

DBC 是 Vector 定义的报文描述文件,用文本描述”ID 0x0C9,偏移 0 位,长度 16 位,大端,系数 0.1,单位 km/h,叫 VehicleSpeed”。有了它,工具能直接把负载解析成物理量。

BO_ 201 VehicleStatus: 8 ECU_Engine
 SG_ VehicleSpeed : 0|16@0+ (0.01,0) [0|250] "km/h" Gateway
 SG_ EngineOn : 23|1@0+ (1,0) [0|1] "" Gateway

没有厂商 DBC 的时候就自己写:抓到帧、定位字段、量出系数和偏移、写成 DBC,然后导入 cabana(Linux 原生,配合 CANable 直接实时看图)或 SavvyCAN(跨平台)。

pip install canmatrix
canconvert my.dbc my.json

这一步的意义是:你从”看十六进制”进阶到”看物理量”。写报告、做异常检测、做 IDS 都需要这个抽象层。

十二、安全视角:CAN 到底危险在哪

回到”安全”这个主题。CAN 的设计目标是可靠和便宜,安全性从来不在设计目标里。

缺陷 后果 典型利用
无身份认证 任何节点都能冒充任何 ECU 伪造轮速/车门状态
无加密 总线可被任意监听 窃取位置、驾驶行为
无完整性校验 帧可被篡改、重放 重放解锁指令
广播 + 低优先级仲裁 高优先级 ID 可占满带宽 ID 0x000 泛洪造成 DoS
UDS 诊断权限弱 部分 ECU 的 SecurityAccess 可被暴力破解 进入编程会话后写入任意数据

2015 年 Miller 和 Valasek 那篇著名的 Jeep 远程利用,就是从娱乐系统一路打进 CAN,最后在高速上切断了刹车。十年过去,物理层的这些特性没有变,变的是边界被网关和 T-Box 围起来了。

主机厂现在的做法

  • SecOC(AUTOSAR Secure Onboard Communication):给关键帧加 MAC 和新鲜度值,接收方校验,防伪造和重放,代价是带宽和延迟;
  • 网关分区:动力、车身、诊断、娱乐分成不同网段,跨域必须过网关白名单;
  • IDS 入侵检测:基于周期偏差、ID 白名单、负载熵值做异常检测,检测到异常就降级或断连;
  • 诊断加固:UDS 的 0x27 服务用非对称挑战响应、速度限制、会话超时,诊断口加物理锁或需要在 4S 店内网才开放。

自己做研究时的建议:先只读监听,建立基线;发帧前先在台架验证;任何写操作(0x2E WriteDataByIdentifier、0x31 RoutineControl)只在报废件或虚拟总线上做。

十三、合规地图:想把这事做成职业,得知道这些

标准/法规 范围 要点
UN R155 整车网络安全 建立 CSMS 体系,做 TARA 威胁分析;2022-07 起新车型强制,2024-07 起全部新车
UN R156 软件升级 SUMS 体系,OTA 过程的安全性与失败回滚
ISO/SAE 21434 工程流程 从概念、开发、生产到运维的全生命周期网络安全
GB 44495-2024 中国整车信息安全 2024-08-23 发布,2026-01-01 起实施
GB 44496-2024 中国软件升级 同上,对应 UN R156

对个人学习者的意义很直接:招聘方要的是”能出 TARA 报告 + 能复现漏洞”的人。只会抓包不够,能说清”这个信号被篡改后影响哪个安全目标、风险等级多少、缓解措施是什么”才是岗位要求。

十四、新手最常见的 8 个坑

  1. 抓不到任何帧:90% 是波特率不对,其次是 OBD 口没接这条 CAN,再次是设备没 up。
  2. 帧全是错误帧:终端电阻缺失(少了 120Ω)或线太长、分支太长。总线拓扑应该是主干 + 极短分支。
  3. ELM327 抓不到广播帧:正常,它只做 PC 端发起的 PID 轮询,硬件层面不给你任意帧。
  4. 同一 ID 抓到的内容对不上手册:字节序搞反了,或者这是网关转发后的重组报文。
  5. 日志太大打不开:500k 满载每秒约 4 万帧,抓 10 分钟就是几十 MB。用 candump can0,ID:ID 先过滤。
  6. 虚拟机里看不到 can0:USB 直通没配对,或者宿主机抢先加载了驱动。
  7. 发了帧车没反应:可能被网关丢弃(跨域白名单),也可能需要先发诊断会话进入指令。
  8. 误以为抓到 ID 就等于控制了车:绝大多数广播帧是状态不是指令,改它只会让仪表显示异常,不会改变执行器。

十五、下一步怎么走

把本文流程走完,你已经能:接线、设速率、抓包、读 PID、做差分、写 DBC。接下来三条分支,按兴趣选:

  • 深入诊断:啃 ISO 14229(UDS)的服务清单,特别是 0x10 会话控制、0x27 安全访问、0x22 读数据、0x2E 写数据、0x31 例程控制,这是”从观察到操作”的门槛。
  • 深入逆向:拿报废件或拆车件搭台架,做完整的”信号 → 功能 → 协议”还原,练习写 TARA 报告。
  • 深入防护:研究 SecOC 的报文格式、CAN IDS 的检测算法(时序、熵、信息论),这块人才缺口最大。

最后再说一次边界:本文所有内容仅用于本人车辆或取得书面授权的车辆、台架、虚拟总线。未经授权对他人的车辆、车队、租赁车辆进行测试,在国内可能触犯《刑法》第 285 条(非法侵入计算机信息系统)与第 286 条(破坏计算机信息系统),并需承担民事赔偿。技术能力越强,越要清楚这条线在哪。

本文所述方法与工具均可公开获取,仅作安全研究与防御体系建设参考。文中数值与协议细节基于经典 CAN 与 ISO 15765-4,不同车型的实际实现可能存在差异,请以实车抓包结果为准。

© 版权声明
THE END
喜欢就支持一下吧
点赞7赞赏 分享
相关推荐
评论 共1条

请登录后发表评论