汽車動力系統ECU固件逆向工程初探

作者:gjden

完成時間:20161119

原文最初發佈於個人博客、看雪論壇、GDA公眾號,知乎排版不好,可以看如下幾個連接看起來舒服點。

汽車動力系統ECU固件逆向工程初探-博客

汽車動力系統ECU固件逆向工程初探-看雪安全論壇

汽車動力系統ECU固件逆向工程初探-GDA

偶爾看到國外一些論壇討論汽車改裝(都是基於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讀寫的工具,當然並不全,有需要的可以自行搜索購買。

工具名稱

簡介

CMD Flash

支持OBD2、BDM 和BOOT模式對ECU進行讀寫

AZN Tuning

AZN改裝店專用,似乎不向外出售

Galletto 1260

實際就是一根診斷線(內含OBD 轉USB晶元)

OpenPort

支持OBD2進行數據讀寫

MPPS V13.02

和Galletto 1260類似

當然如果你的汽車支持OBD2進行固件讀寫並且你已經熟悉讀寫ECU固件的診斷命令,那麼你也可以連接OBD2介面並且向其發送診斷命令來操作,只是相對來說麻煩一些。

下圖展示的以上列舉的刷ECU固件的硬體工具的截圖:

Galletto 1260

OpenPort

CMD Flash工具

AZN Tuning

MPPS v12

如果拆機的話,會涉及接線問題,你可以通過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的手冊吧。

算數指令

指令1

指令2

功能描述

ADD

ADDB

兩字或位元組加法

ADDC

ADDCB

帶進位的兩字或位元組加法

SUB

SUBB

兩字或位元組減法

SUBC

SUBCB

帶進位的兩字或位元組減法

MUL

MULU

16位乘16位帶符號或無符號乘法

DIV

DIVU

16位除16位帶符號或無符號除法

DIVL

DIVLU

32位除16位帶符號或無符號除法

CPL

CPLB

一個字或位元組的1的補數

NEG

NEGB

一個字或位元組的2的補數

邏輯指令

AND

ANDB

兩字或位元組位與

OR

ORB

兩字或位元組位或

XOR

XORB

兩字或位元組位與或

比較指令

CMP

CMPB

兩字或位元組比較

CMPI1

CMPI2

帶增長1或2的兩字比較

CMPD1

CMPD2

帶增長1或2的兩字比較

布爾位操作指令

BFLDH/BFLDL

字的高位位元組或低位位元組的可屏蔽位的操作

BSET

對某位置1

BCLR

對某位清零

BMOV

移動某一位

BMOVN

反相移動某位

BAND

兩位相與

BOR

兩位相或

BXOR

兩位相與或

BCMP

兩位比較

移位和循環移位指令

SHR

字右移

SHL

字左移

ROR

字循環右移

ROL

字循環左移

ASHR

帶符號位右移

系統控制指令

SRST

通過軟體複位

IDLE

進入休閑狀態

PWRDN

進入掉電狀態

SRVWDT

服務看門狗定時器

DISWDT

關閉看門狗定時器

控制流程指令

JMPA/JMPI/JMPR

當前程序段有條件跳轉到絕對、間接或相對目標地址

JMPS

在任何程序段無條件跳轉到絕對目標地址

JB/JNB

根據選擇位的狀態,在當前程短有條件跳轉到相對目標地址

JBC/JNBS

根據選擇位的狀態,用取反測試位,在當前程序段有條件跳轉到相對目標地址

CALLA/CALLI

在當前程序段中有條件調用絕對或間接地址的子程序

CALLR

在當前程序段中無條件調用相對地址的子程序

CALLS

在當前程序中無條件調用絕對地址的子程序

PCALL

在當前程序段中將選擇寄存器壓入堆棧無條件調用絕對地址的子程序

TRAP

在程序段中無條件跳轉到中斷或陷阱矢量跳轉表

RET

在當前程序段從子程序返回

RETS

在任何程序段從子程序返回

RETP

在當前程序段從子程序返回,外加從系統堆棧中彈出一個選擇寄存器

RETI

從中斷服務程序中返回

JMPA/JMPI/JMPR

當前程序段有條件跳轉到絕對、間接或相對目標地址

JMPS

在任何程序段無條件跳轉到絕對目標地址

JB/JNB

根據選擇位的狀態,在當前程短有條件跳轉到相對目標地址

JBC/JNBS

根據選擇位的狀態,用取反測試位,在當前程序段有條件跳轉到相對目標地址

CALLA/CALLI

在當前程序段中有條件調用絕對或間接地址的子程序

CALLR

在當前程序段中無條件調用相對地址的子程序

CALLS

在當前程序中無條件調用絕對地址的子程序

這裡不一一列舉了,其他指令請查詢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固件分析做了一個初步探索和簡單的分析,後續還有很多工作要做,比如ECUnMAP數據校驗繞過,添加和修改ECU功能和某些邏輯,二進位代碼級別的ECU CAN協議解析逆向,感測器數據解析邏輯以及指令發送邏輯等等。


推薦閱讀:

GDA關於android脫殼的問題說明
R2逆向練習(4-7)
新手到大神反編譯unity3d遊戲系列教程【一】
有Android逆向基礎如何學習Android漏洞挖掘?

TAG:ECU | 汽车安全 | 逆向工程 |