一辆 2014 年款雷诺 Latitude(纬度)的中控时钟和实际时间差了一小时,而车主翻遍菜单也调不回来。挡住他的不是机械故障,是几千公里外一台厂商关停的地图服务器。
这辆车的 Carminat LIVE 车机由 TomTom 代工。上一任车主当年问他要不要那张导航地图 SD 卡,理由是「这台车连改时间都得靠它」。他不信,也觉得卡上的地图早已过期,就没要,卡被扔掉了。他后来发现,前任车主说的每个字都是真的。
一辆车的时钟由一张地图卡决定。这套设计把车主的硬件控制权做成了依赖外部服务的租赁物。服务器关停之后,唯一能修好它的补丁,只能由车主自己写。
调时钟要先买回一张旧地图卡
在雷诺 Latitude 上,屏幕由一套代号 beaumont 的平台驱动,硬件是三星 S5P6440 芯片,跑的是 TomTom 定制系统,内核版本 Linux 2.6.28.10。
车机的交互入口是 PNDNavigator。雷诺与 TomTom 没有为整车单独写一套设置菜单,时钟、语言、亮度这些条目全部塞在 PNDNavigator 的界面定义里,而这份定义是从外置 SD 卡上读出来的。卡不在,车机连「设置」这个程序该怎么进都不知道。
图:车机中控屏幕上大面积显示的爱沙尼亚语「No maps found!」提示——地图卡决定的不只是地图。来源:blog.nns.ee
他花了一个小时翻遍各级菜单,始终没等到那个「Set time」选项。修车的第一条路是买回一张卡:市面上还找得到,但寄到爱沙尼亚要花大约 60 欧元。他不打算为一个时钟付这笔钱,决定自己把权限拿回来。
厂商把基础设置做成地图附件
十多年前汽车行业掀起第一轮网联化浪潮。主机厂想要智能中控的卖点,又缺少自研车载系统的积累,于是把整套座舱交给导航厂商 TomTom。外包团队为赶车型节点,直接把便携导航的固件搬进车机:开机先拉起导航,基础设置挂在下面。基础设置绑在导航业务之下,时钟功能随着地图服务一同失效。 车主面对的是一台机械完好、却连夏令时都调不回去的汽车。
芯片锁死与 noexec 筑起层层防线
最直观的自救办法是买一张普通 SD 卡,把脚本拷进去。车机准备了不止一道防线。
第一道是芯片级绑定。TomTom 的 DRM 会核验存储卡的 CID(Card Identification,卡片识别码)——出厂时烧录在卡内、无法改写的唯一编号,以及地图文件的签名。空白卡在第一步就被弹回。
第二道防线藏在挂载策略里:即便伪造出合法 CID,系统仍以 noexec 挂载外置存储,卡上的程序与脚本都不允许执行。这些机制本该拦下盗版地图,最后拦下的是想修车的车主。
触发一次崩溃,跨过执行限制
车主 Rasmus Moorats 把固件从设备里取出来,在电脑上用 QEMU 模拟 S5P6440,开始反汇编。他逐段逆向了负责解析 master.script 的 ttn,记录下内部命令协议 SHEX 的用法:SHEX 只接受一个以空格分隔的参数,把它交给 launchserver,后者用 execve 执行——而这条路又被 noexec 堵死。
突破口在内核的核心转储机制。Linux 允许通过 /proc/sys/kernel/core_pattern 指定进程崩溃时的转储管道;带命令行参数的写法从 2.6.24 起支持,而这台车的内核是 2.6.28,core_pattern 还能从用户态改写。他挑了一个必然崩溃的进程:/bin/dbus-monitor 连不上系统总线时会抛 SIGABRT。内核以特权身份执行 core_pattern 指定的命令,这条路径不受 noexec 约束。
图:车机提示执行 master.script,脚本随后绕过 noexec 在真机上跑了起来。来源:blog.nns.ee
结果是一台能以 root 身份运行自写脚本的车机,时钟和时区重新可调。
代码停止维护之后
拿到底层权限的消息传开后,社区车主开始复现。TomTom 论坛上有人确认,同一套流程在 Carminat TomTom 8.843 固件上同样可行;论坛帖子还报告了一个反直觉的细节——导航本身并不因为缺卡而失效,受影响的只有时钟显示。真正需要补的是卡上的星历文件 packedephemeris.ee、ee_meta.tlv、ee_meta.txt,把它们换成最新的离线数据,定位与时钟就能继续工作。
花钱买下整台车的人,得靠黑客手段给车机打补丁。车企把硬件功能抵押给云端服务,用户手里就只剩下租赁权。 服务器可以停,代码可以不再维护,打开系统控制权是这类设备活过厂商寿命的唯一办法。
参考链接:
- blog.nns.ee:Jailbreaking my car’s navigation system just so I can change the time
- TomTom 官方社区讨论帖(Carminat TomTom 8.843)
- Lobsters 技术社区讨论