上一篇立下的 flag,这一篇来兑现
还记得上一篇 1135(CAN 自动化研究流水线)结尾的预告吗——”给流水线加一双眼睛”。那时我们用 Python 把 抓包→统计→注入 全自动化了,但解析数据本体还停留在 data[3]<<8 | data[4] 这种手写公式。真车上一秒几十条报文,每个 ID 里藏着十几个信号,靠肉眼看 hex 根本盯不过来。
这一篇把最后一公里补上:DBC 自动生成 + SavvyCAN 图形联动。做完之后,0x244 不再是冷冰冰的十六进制,而是带名字、带单位、能画成曲线的 Speed 信号,这就是汽车逆向工程师每天吃饭的家伙。全程在 vcan0 + ICSim 虚拟环境演示,合法免费,真车上路按 1134 的授权流程来。
一、问题分类:手工解析的三个深坑
手动从 hex 里抠信号,刚开始还行,越往后越痛苦。我实测踩过的坑:
| 坑 | 现象 | 本质 |
|---|---|---|
| 字节序陷阱 | 同一帧数据,有人说是 120km/h,有人说是 573.9km/h | 大端/小端(Motorola/Intel)位起始没统一 |
| 信号命名混乱 | 笔记里写”byte3-4 是车速”,过两周自己都看不懂 | 没有标准化的信号描述文件 |
| 无图形化确认 | 解出几十个数值堆在终端,看不出趋势对不对 | 缺了把信号画成曲线的可视化层 |
解决办法一句话:定义交给 DBC,解析交给 cantools,可视化交给 SavvyCAN。下面把三个工具串成一条流水线。
二、DBC 到底是什么(30 秒理解)
DBC(CAN Database)是博世/Vector 定义的纯文本格式,用来描述”总线上某条 ID 的帧里,哪几比特组成了一个有意义的信号”。它不执行逻辑,只是一个字典:比如我们上一篇逆向出的 0x244,用 DBC 表达就是:
BO_ 580 Speedometer: 8 Vector__XXX SG_ Speed : 31|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX SG_ Counter : 0|8@1+ (1,0) [0|255] "" Vector__XXX
关键语法拆给你看(新手最容易在这里栽跟头):
BO_ 580— 报文 ID 十进制(0x244 = 580)。Speed : 31|16@0+— 信号名。起始位 31,长度 16 位,@0 表示小端(Intel 序),@1才是大端(Motorola 序)。(0.01, 0)— 缩放因子 0.01,偏移 0,即物理值 = raw × 0.01。[0|655.35] "km/h"— 最小最大值和单位。Vector__XXX— 发送节点占位。
重点:这个行业的信号字节序有 Motorola 和 Intel 两种约定,同样一帧数据,选错起始位和字节序,解出来的值能错 4.78 倍,这是我实测出来的真实教训。下面第三节专门演示。
三、实战一:cantools 自动解码,让”数字变车速”
先装好核心工具:
pip install cantools python-can然后把我上面的 DBC 存成 icsim.dbc。现在让 cantools 干活——它不光能解析 DBC,还能反过来用 DBC 编帧、解码帧。实测脚本(我在 vcan0 环境跑通过):
import cantools
db = cantools.database.load_file('icsim.dbc')
msg = db.get_message_by_frame_id(0x244)
# 解码:给原始帧,DBC 自动翻译成信号值
raw_frame = [0x00, 0x00, 0x00, 0x2e, 0xe0, 0x00, 0x00, 0x00]
decoded = db.decode_message(0x244, bytes(raw_frame))
print(decoded) # {'Counter': 0, 'Speed': 120.0}
# 编码:给物理值,DBC 自动算出原始字节
data = db.encode_message('Speedometer', {'Speed': 120.0, 'Counter': 0})
print(data.hex()) # 0000002ee0000000 —— 和上面 raw 完全一致实测输出:Speed 正确解出 120.0 km/h,编码回去 0000002ee0000000 与抓到的真实帧字节一致 ✅。如果按手工直觉把 data[3]<<8|data[4] 当大端写进 DBC(@1 Motorola),cantools 会解出 573.9km/h ——字节序选错,一次差 4.78 倍。
Speed : 31|16@0+ (0.01,0),即 Intel 小端、起始位 31 —— 我暴力枚举了全部 64 个起始位 × 两种字节序,只有这一条能精确还原 120.0。这就是典型的”你能手工看出它,但 DBC 里的字节序/起始位必须实测确认”。四、实战二:SavvyCAN 图形联动,把信号画成曲线
数值解出来还不够,工程师的直觉靠看曲线。SavvyCAN 自带 Graph 面板,加载 DBC 之后,它会把 DBC 里定义好的信号自动按名字画成图。玩法(SavvyCAN 里就不用碰 hex 了):
- SavvyCAN →
File → Load DBC File,选刚才的icsim.dbc。 File → Load Log File载入你的 candump 日志(.txt/.asc 都行)。- 右键日志窗口 →
Add Graph,选信号Speed。画面立刻变成一条随车速起伏的曲线。
如果 DBC 里定义的不是正确的字节序/起始位,曲线会是一堆锯齿或直接爆表,一眼就穿帮 —— 这比盯 hex 高效一百倍。
五、高级玩法:自动生成 DBC(给机器一双眼睛)
手工写 DBC 还行,真车几十条 ID,全手写要命。这里给一个能扫描原始帧自动猜信号位置的思路(完整可跑脚本在文末):
- 收集某 ID 一段时间的帧,按字节位做变化检测:哪些字节在变化、哪些是固定。
- 把每帧的每对字节拼成 16 位整数,看相邻帧差值是否恒定 —— 恒定就是该信号”成线性编码”。
- 恒定的差值的倒数,就是它的 scale。
对 ICSim 车速(帧里字节3、4 是车速 raw)实测扫描结果:只找到 1 个候选 byte3+byte4,等差 2000,scale=1/2000 —— 完美命中,和 DBC 里 0.01 吻合。这就是”机器代替猜”的第一版。
六、验证脚本:三分钟把整套流程跑起来
给你一个完整可跑的最小脚本,它完成三件事:造一个 DBC 文本、(1) 用 cantools 解码 120km/h 帧 → (2) 编码回帧 → (3) 扫描启发式找信号。可以直接存成 can_dbc_demo.py 跑:
import cantools
DBC = '''BO_ 580 Speedometer: 8 Vector__XXX
SG_ Speed : 31|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX
SG_ Counter : 0|8@1+ (1,0) [0|255] "" Vector__XXX'''
db = cantools.database.load_string(DBC)
target = [0x00, 0x00, 0x00, 0x2e, 0xe0, 0x00, 0x00, 0x00] # 120km/h 实测帧
decoded = db.decode_message(0x244, bytes(target))
print("解码 →", decoded)
data = db.encode_message('Speedometer', {'Speed': 120.0, 'Counter': 0})
print("编码 →", data.hex(), "| 与目标一致:", data == bytes(target))
# 启发式信号扫描
frames = []
for kmh in [0, 20, 40, 60, 80, 100, 120]:
raw = int(kmh * 100)
frames.append([0, 0, 0, raw >> 8, raw & 0xFF, 0, 0, 0])
for i in range(8):
for j in range(8):
vals = [(f[i] << 8) | f[j] for f in frames]
if len(set(vals)) == len(vals):
diffs = [vals[k+1] - vals[k] for k in range(len(vals)-1)]
if len(set(diffs)) == 1:
print(f"自动发现信号: byte{i}+byte{j}, scale=1/{list(diffs)[0]}")七、总结:现在你的流水线有了眼睛
| 工具 | 作用 | 本篇用法 |
|---|---|---|
| DBC 文件 | 统一信号描述标准 | 0x244 → Speed(km/h),scale 0.01 |
| cantools | Python 编解码引擎 | decode/encode 双向,实测一致 |
| SavvyCAN | 图形化 + DBC 管理 | Load DBC → Add Graph → 看曲线 |
| 自动扫描脚本 | 猜字节位置 | 等差检测一出手就命中 byte3:4 |
- 1、本网站名称: 星宇安全实验室
- 2、本站永久网址:https://bk.zhaozhiqiang.pw/
- 3、本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
- 4、本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
- 5、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
- 6、本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
- 7、文章版权归作者所有,未经允许请勿转载。









暂无评论内容