THE CAR HACKER’S HANDBOOK 第六章解读
ECU 破解ECU 攻击途径可分为三类前门攻击 劫持原始设备制造商 (OEM) 的访问机制后门攻击 应用更传统的硬件黑客攻击方法利用发现非预期访问机制前门攻击OBD-II 标准规定必须能通过 OBD-II 接口对车辆进行重新变成而原始编程方法进行逆向工程是必然攻击途径。J2534:标准化车辆通信 API目的是统一车辆诊断和刷写接口标准解决以前每个诊断工具公司都用自己专有的硬件和驱动。可以理解为一个统一的插头加接口协议让 Windows 系统能标准化地和汽车 ECU 通信。主要功能ECU 诊断固件升级(刷写程序)参数读取和修改维修诊断它本质上是合法的前门通道让维修厂访问车辆电脑。在安全测试中可以通过观察 J2534,可以学到原厂是如何与 ECU 通信的。1、使用 J2534 工具正常操作车辆(刷写参数)2、观察并记录整个通信过程(API 调用或总线流量)3、分析记录的数据4、模仿原厂行为实现不用原厂软件也能读写、刷写 ECU两种主要的观察方法方法1J2534 Shim DLL中间人记录像抓包一样记录 J2534 应用程序与车辆之前的所有 API 调用方法2配合 Sniffer抓总线流量用 J2534 操作一边用另一台设备抓取 CAN 总线上的真实数据。核心思路通过观察合法工具J2534如何与 ECU 通信 → 逆向分析 → 模仿实现直接访问。KWP2000 Seed-Key 算法KWP2000(ISO 14230)本质是一个应用层协议可以跑在 CAN 总线上主要用途就是诊断ECU 刷写但属于老协议新车越来越少。Seed-Key 算法基本原理ECU 在允许我们进行操作时刷写、读取敏感数据之前会先进行身份认证。认证方式几乎都是 Seed-Key种子-密钥机制过程如下1、ECU 给我们一个随机种子 Seed例如01 C3 45 22 842、我们必须根据这个种子计算出一个正确的密钥 Key例如02 3C 54 22 483、把密钥发回给 ECUECU 验证通过后才允许我们继续操作特点没有统一的 Seed-Key 算法每个厂商 ECU 算法不同。大多是简单的数字运算加减乘除、位运算、查表等组合。种子和密钥长度常见16、32位。破解/绕过 Seed-Key1、固件逆向拿到 ECU 固件反汇编后找到计算 Seed-Key 代码2、分析合法工具逆向原厂诊断软件J2534 刷写工具找到如何计算密钥3、观察合法交互抓取原厂工具和 ECU 真实 Seed-Key 交互过程分析规律4、主动欺骗自己构造设备反复向 ECU 请求 Seed,然后记录对应的 Key后门攻击核心思想是软件层面很难出成果就从硬件下手因为 ECU 本质就是嵌入式系统。攻击步骤1、分析电路板从最大的芯片看起处理器、内存芯片记录所有芯片型号去查 datasheet特别注意各种存储芯片SRAM、EEPROM、FlashROM.Serial EEPROM、Serial FlashNVSRAM 等。2、EXP 利用核心思想是不拆硬件不需要完全逆向前门锁。利用方式触发系统 Bug崩溃、重启、异常行为发展缓冲区溢出等漏洞最终打成 RCE汽车固件逆向工程逆向第一步获取与反汇编获取二进制流大小通常在 4KB 到 4MB 之间。确定芯片架构必须先知道芯片型号。寻找突破口三条关键线索1、自诊系统每个 ECU 都有监控自身健康的程序。利用方法定位错误码逻辑比如已知 DTC 代码 10 代表进气温度传感器故障。逆向追踪在反汇编代码中搜索设置”错误状态“10 的地方接下来就找内存中存储传感器数据的变量地址。2、库函数与查找表ECU 运行涉及大量数学转换这些数据在查找表中。特征就是高频调用以及插值算法查找表逻辑通常带有大量的插值计算。去寻找特殊的访问指令微控制器通常有专门读取程序存储器Flash的指令。这些函数通常在内存中挤在一起找到一个就能找到全部。所以这里再深入理解一下书中的意思是逆向分三步一、盯住图书馆函数这里库函数个人理解为我们向 ECU 输入某个值会调用一个函数得到的结果是这个函数的计算结果。在 IDA 里看哪个函数被几百个地方调用它大概率是库函数。二、识别插值算法特征传感器数据通常是不连续的表中只有几个点1v、2v、3v如果电压是 1.5v就会做插值运算算 1v 和 2v 之间。就是说当我们看到汇编里一段逻辑访问 Flash且有密集的数学运算就能找到参数入口。三、反推核心参数每次调用这个”小助手“时程序必须告诉他两个信息表的起始地址与表的结构几行几列8 位或者 16 位。这样我们就能通过这些地址把固件中的”限速表“、”喷油表“等导出来。3、已知物理特性的数据某些传感器的输出符合物理定律。图 6-1 和 6-2 显示了形状相似的福特和日产传感器曲线它们所说明的相似性也延伸到多个制造商图 6-2 至 6-6 显示了同一数据的五个不同视图。图 6-3 显示了图 6-2 中所示的 VQ 曲线在十六进制编辑器中的样子。能看到明显的曲线变化。通常情况下可以找到多个能在同一个物理 ECU 上运行的固件文件bin。越多越好在十六进制编辑器中进行简单的比较就能看出文件之间哪些字节不同。代码保持不变而参数发生变化的情况很常见但并非总是如此。如果文件差异小于 5%通常可以认为差异在于参数。如果您知道两个固件文件之间的功能变化以及哪些字节发生了变化就能获得更多线索帮助您将 ROM 的变化与参数的变化关联起来。比较字节以识别参数图 6-9 和 6-10 对比了 1996 款 V8 Mustang 和 1997 款 V6 Thunderbird显示在 114,688 字节中存在 6,667 处差异。这是一个参数不同的相同代码的极端例子但与整体文件大小相比差异仍然只有大约 5.8%。大多数处理器使用由处理器自身定义的中断向量表。参考处理器的数据手册可以了解中断例程的结构从而快速识别中断处理程序。通过追踪处理器上的中断引脚、ECU 内部的电路以及车辆线路图中对应的引脚可以帮助您识别用于处理诸如燃油和点火控制、曲轴和凸轮轴信号处理以及怠速功能等硬件功能的代码块。使用 WinOLS 识别 ROM 数据这里工具和技术有点被淘汰了不多介绍。A Plain Disassembler at Work这段是 1990 年日产 300ZX 双涡轮增压版的 ECU 反汇编。1、确定硬件架构与内存布局目标芯片是 HD6303 MCU 寻址能力 64kb已知 EPROM 芯片大小为 32KB0x7FFF。已知处理器的复位向量固定在内存末尾的 0xFFFE/0xFFFF。计算偏移量为了让着 32KB 的固件刚好填满内存末尾他的起始加载地址必须为 0x8000(0XFFFF - 0X7FFF 0X8000)。这里我们拿Vxworks作为举例像这个 300ZX 的 ECU 一样他必须挂载到内存的 0x8000 基址上。类似于Vxworks的基址。这里是因为 CPU 硬件写死了要在 0xFFFF 去寻找启动指令。这里是 AI 给出的基址计算其实整个流程就跟 Vxworks 的符号表修复差不多。2、寻找中断向量表普通的文本反汇编(DASMx)会输出极其详尽且枯燥的代码。要判断反汇编是否成功首先要看向量表。如果反汇编地址都在指定的起始地址0x8000之上说明正确。复位入口在 300ZX 的例子中复位向量指向了 0xBE6D。这是处理器通电后执行的第一行代码。观察 0xBE6D 代码发现他执行擦除 RAM 的操作。这符合固件启动常理初始化内存为 0证明反汇编逻辑是正确的。