查看原文
其他

汽车动力系统 ECU 固件逆向工程初探

gjden 看雪学院 2017-04-02


偶尔看到国外一些论坛讨论汽车改装(都是基于ECU的)的技术问题,于是产生了兴趣,想想如果ECU能够被改装,那么它肯定也会面临一些安全问题。所以参阅了一些讨论文章,发现他们讨论的问题基本上都是如何修改MAP表(ECU中的数据表),而并没有人基于ECU二进制代码的逆向工程,因此有了本文。本文只是做一些关于汽车动力系统(发动机)ECU逆向工程的初步探索,在这方面资料稀缺,因此把自己一些粗浅的认知和分析结果放出来,文章必定有错误之处,人外有人天外有天,还望资深人士纠正,另外发出来的目的更希望能够起到抛砖引玉的作用。


一、明确一下 ECU 概念


不必多说, ECU 指的就是汽车电控制单元,也就是 ECU 的本意( Electronic Control Unit)。像防抱死制动系统、 自动变速箱、 SAM 模块、多媒体系统、刹车辅助系统、巡航定速系统、自动空调系统、 驱动系统、电控自动变速器、主动悬架系统、安全气囊等等都是包含有各自的ECU,他们分别由这些 ECU 控制管理并且这些 ECU 都通过 CAN 总线连接起来,形成我们通常所说的汽车网络(车载网络)。


但是汽车行业内大部分人说的 ECU 都特指为发动机 ECU, 也称车载电脑。 这种延续了传统老式的叫法,因为早期的汽车只有一个用于管理发动机控制系统的 ECU,因而大家习惯说的 ECU 实际上指的是发动机 ECU,比如 ECU 更新、ECU 调校、 ECU 改装等等概念都是特指发动机ECU。 包括汽车百科里也都特指 ECU 为行车电脑/车载电脑。但国外很多分析文章、论文中涉及 ECU 基本上都是广泛意义的 ECU,而不特指发动机 ECU。


下面我截了几张发动机 ECU 的 PCB 图,可以看出 ECU 的 PCB 似乎和普通电子设备的 PCB差不多。



至于 ECU 控制发动机的原理,几乎所有将汽车的教材中都有,我就不多说了,否则得引出一堆东西,那就是给自己挖了一个大坑, 所以还是那一句话: 网上资料多,还得靠自摸^^!


下图是我从 PPT 上截来的,应该是最直观易懂的图。


二、 ECU 固件获取


先做一点科普, 对于大部分汽车玩得比较深的人, 对汽车改装都不会陌生,现代意义的汽车改装实际上是对发动机 ECU 固件提取、调校、回写等。 一般通过 ECU 调校可以让发动机输出更高的动力。 ECU 调校通常比较复杂, 比如需要对点火时间、喷油量、喷油时间、燃油压力、 增压压力等等参数的调整并且还需要结合负荷、档位、转速、温度等做出最优的调整方案, 另外还得考虑安全性等等问题。 因而需要对汽车系统非常熟悉并且具有丰富的调校经验的工程师才能够完成,所以 ECU 调校的费用也会很高。


ECU 固件的读取和普通设备的固件读取类似,但是也有差别。相似之处就是都需要硬件设备支持,不同在于接口方式的不同(实际上是废话^^)。 当然有的 ECU 需要将 ECU 拆解下来进行固件读取,而有的可以直接通过 OBD 口进行固件读取,通过 OBD 读取更加简单,至少不用拆机和焊线。 以下是我列举的一些可以进行 ECU 读写的工具,当然并不全,有需要的可以自行搜索购买。



当然如果你的汽车支持 OBD2 进行固件读写并且你已经熟悉读写 ECU 固件的诊断命令,那么你也可以连接 OBD2 接口并且向其发送诊断命令来操作,只是相对来说麻烦一些。


下图展示的以上列举的刷 ECU 固件的硬件工具的截图:


如果拆机的话,会涉及接线问题, 你可以通过 chip datasheet 来搜索与你车型 ECU 相匹配的芯片手册。 下面这张图是奥迪 ECU 的接口图, 你可以根据自己 ECU 的类型找到其针脚定义。


目前,大部分的汽车都支持 OBDII 来进行 ECU 的操作,因此来一张 OBDII 关键接口的图:


如果你购买有硬件 FLASH 工具,那么产品相关的说明文档应该可以解决大部分问题,网上也有相当多的资料, 实际上 ECU 固件的读写比一般的设备的固件读写简单很多,因而在这里也不细说了。


三、 ECU 固件分析初探


在汽车界玩得最深的估计就是做 ECU 调校了,但是 ECU 调校只是对 ECU MAP 表( ECU固件中的数据表,后面会有更详细的说明) 进行微调并且读修改的数据做校验。但如果对ECU 固件代码进行逆向工程,我们不仅可以对修改MAP 表,还可以破解其校验功能(很多买得很贵的 MAP 校验工具就是靠逆向校验函数而编写的,这实际上并不难,因为 MAP 的校验算法本身就不是很复杂),并且修改固件代码流程,甚至可以给其添加功能或者是加一些恶意代码进去,就像我们玩儿 PE 文件一样,在保证其能够正常和安全运行的前提下,你可以自由的改造。


1. 固件信息提取


首先通过二进制数据中的字符串来看看该 ECU 固件的有哪些信息。



上图中我标记的第二行信息是该 ECU 的电子发行包, 我们可以看出该 ECU 是采用的博世的 ECU ME7.1。此后,我又发现了与发动机相关的信息,如图:



其中 06A906032JB 为发动机零件号,通过零件号可以得知该车型的发动机为宝来发动机, 但是 ECU 采用的是博世 ECU, 发动机排量1600ml,变速器为 AG4 自动 4 档位等等。


最后,我通过 ME7Info 提取出了更多的信息。比如可能的通信协议硬件号、软件号、软件版本、引擎 ID 等等信息。



2. 指令集识别


如果要对固件进行逆向工程的话,必须知道该固件的 MCU 类型,以便知道该 ECU 采用指令集类型。因此,我首先想到了 binwalk,因而我尝试了一下, binwalk 识别指令花了很长时间:



Binwalk 识别出来竟然是 ARM, 着实让人兴奋了一把, 因为个人对 ARM 指令还是比较熟悉的,更何况 IDA 还可以 F5。但是看到后面的说明感觉就有点不对, 怎么可能只有 540条有效指令。随后,我用 IDA 来验证了一下,反汇编指令选择 ARM big endian。并且从 0x12943的位置开始进行反汇编,如图:



可以明显的看出,这是不正常的代码,并且根据经验,固件开始部分应该会有一大堆中断跳转, 但通过 ARM Big Endian 得到的代码却是如下这样:



另外我也尝试了使用 little endian 方式来反汇编,同样是不正确的。


此时,第一步提取的固件信息就很有用了,至少为我们提供了搜索的线索, 结合固件涉及的电子属性和发动机相关信息, 我发现该 ECU 属于英飞凌的 (Infineon,前身为西门子集团的半导体部门),而该 ECU 采用的是 C16X 系列的内核,也就是说该 ECU 封装的实际上 C16X的 MCU,这款 MCU 原先属于西门子,因此指令集极有可能也是西门子的。强大的 IDA 果然没有让我失望,其完全支持 C16X 家族系列。 在 IDA 中我选择 Siemens C166 进行反汇编, 确认后需要填写 RAM 和 ROM 地址。RAM 和 ROM 地址目前还不清楚,因而先空着直接反汇编。



从图中我们可以看出部分跳转指令是正常的, 但是有的又不正常(红色阴影的地址)。不正常的地址有一个共同点就是都是基于 0x820000 的地址。 因而,部分于 MCU 相关的中断服务以及硬件管理代码可能的基地址为 0x000000, 这就是这部分代码可能映射在 0x0000000处,而部与 ECU 相关的中断服务和硬件管理代码可能的基地址为 0x820000。如果你关心 MCU 的代码可以将固件分割后进行分段加载,我这里只是简单将整个固件映射到 0x800000,因为我只关心 ECU 的代码,所以将该 ROM 的起始地址设置为 0x800000,而我们的固件大小为 1M,因此 ROM 大小设置为 0x100000,加载地址和大小和 ROM 设置成为一样。 RAM 采用默认的方式不管它。



反汇编后,我们可以看到 MCU 相关的中断跳转表。



OK,现在我们可以正常的分析该 ECU 固件了。当然如果你想逆向分析该 ECU 固件,你得熟悉 C166 汇编语言,还得要十足的耐性。下表我列举了 C166 汇编指令及其功能(也基本上来自于网络),如果想要更新详细的信息,那就去看 Infineon 的手册吧。


算数指令

逻辑指令

比较指令

布尔位操作指令

移位和循环移位指令

系统控制指令

控制流程指令


这里不一一列举了,其他指令请查询 C166 手册,此外本文不打算介绍 C166 的那些寄存器以及 ECU 自身寄存器(这些寄存器是处在 MCU 外部,和 MCU 一起被封装在 ECU 中,通常都是映射在 RAM 中,寄存器太多了,就不做介绍了)。


3. 汇编代码的二次处理


通过 IDA 反汇编得到毕竟只是原始的汇编代码,代码量巨大并且难以识别, 分析起来也会非常吃力。 如果有现成的插件或者脚本自动识别一些函数或者数据,那么可以大大减少我们逆向工程的工作量。幸运的是目前还真有这样的插件—Bosch Me7x 插件,该插件针对ME7.1 和 7.5 来进行函数和 MAP 表的识别以及做出相应的注释。这是一款比较老的插件,对于部分的函数和 MAP 表的识别有些错误。但是有总比没有好, 通过该插件我们成功找到了一些关键函数和 MAP 表。


如下图是识别出来的操作系统自身的函数, 主要是一些基本操作函数, 当然这些函数我们可以不用关心。


以下是一些识别出来的 lookup 表(这些表构成了 MAP)和以及部分操作 MAP 的函数。 此外很多 MAP 查询函数都没有做明确的注释,只是被命名为 LookupA-Z,因而具体的那个函数操作那个 MAP 需要花费大量的时间来分析。


查表函数对参数都做了注释,很人性化


另外, 插件采用的是固定的函数特征和 MAP 表特征, 因而很多 MAP 表也都没有识别出来。 所以我们还需要结合其他工具来分析。在代码级别的逆向工程对固件的操作级别更高,你可以绕过某些逻辑和校验,甚至可以给 ECU 添加功能,或者添加一个后门(在某个传感器的值达到一个异常值时触发后门,对于目前很多将发动机 ECU 接入 CAN 网络后,你会有更多的攻击入口,此处不多说,自己体会吧),而不仅仅限制于修改 MAP(大部分都是做 ECU 改装)。


4. MAP 表的进一步分析


MAP 表,又称脉谱表,设计者将提前将计算好的数据采用二维、三维或多维的数据结构方式存储到 ROM 里面去。典型的三维 MAP 就是喷油 MAP,一般横坐标是转速,纵坐标是节气门开度,纵横坐标交叉点就是喷油量数据。采用这种三维数据结构,能够精确的表示出每一个不同转速和不同节气门开度情况下的喷油量。 ECU 通过读取传感器的工作参数得知引擎各机构当前状态(如空气流量、曲轴位置等) 并且将读取的数据作为 MAP 表的坐标参数查出需要控制引擎的信息等(如喷油时机、喷油量)。


通过更加细致的分析,我找到了一些 MAP 表,比如油量表、 直接转矩控制表(DTC 表)、DTS 表、油量表、 RPM 表、 进气温度表等, 以及操作表的函数,比如有做 MAP 校验的函数,查表的函数等等。 但这是远远不够的,现在汽车的 MAP 表通常都有几十上百个 MAP 表。


因此,为了识别出更多 MAP表,我需要一个更加专业的工具,那就是鼎鼎大名的 winols,该款工具可以很好的识别出 ECU 固件中 MAP 并且能够实现这些数据的 2D、 3D 展示,最强大的是可以实现 MAP 数据的编辑和校验,即便是加密处理过的数据也可以自行解密。


如图,可以看出 winols 可以识别出 71 个 MAP 表,每个 MAP 表都是以 Map “Bosch II”类似的默认名称命名,这些需要自行进行识别以后进行更改,不同的 ECU 有不同的 MAP 表,也没有固定特征,需要一些经验来进行识别。



针对于每一个 MAP 表都可以以纯数据、 2D、 3D 方式来进行显示。



以 3D 形式显示有助于工程师根据 3D 形状来判定该 MAP 的类型,也可以非常直观的看到 MAP 修改之后的改变。当然 winols 还支持修改完自动完成校验的功能。如果连接上汽车,它还可以实时进行修并且实时校验,大大方便了 ECU 的调试。



此外还有很多其他做 MAP 数据修改的工具比如 3D MAP 之类的,也都是非常好的工具,此处也不做介绍了。


四、 总结


本文仅仅对 ECU 固件分析做了一个初步探索和简单的分析, 后续还有很多工作要做,比如 ECU MAP 数据校验绕过,添加和修改 ECU 功能和某些逻辑, 二进制代码级别的 ECU CAN协议解析逆向,传感器数据解析逻辑以及指令发送逻辑等等。


        


看雪安全 · 看雪众测

持续关注安全16年,专业为您服务!

快,关注这个公众号,一起涨姿势~

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存