當前位置:
首頁 > 新聞 > 大眾車機天寶187A Hack筆記

大眾車機天寶187A Hack筆記

*本文原創作者:mengxp,屬Freebuf原創獎勵計劃,未經許可禁止轉載,

由於篇幅限制,

本文中代碼部分請移步至閱讀原文查看~


0×00前言

自從去年買了車,對汽車電子系統的興趣就上來了。這不,前一陣子逛汽車論壇,發現了有網友將老版本的天寶車機被刷上了2017新帕薩特車機的系統,支持超級藍牙和蘋果CarPlay,百度CarLife等功能。

沒錯,這台車機就是最近很火的天寶187A,據說被刷上去的新系統是屬於天寶187B,而天寶187B是為在當時並未上市的2017款新帕薩特配備的。

我瞧了一眼我車上的車機型號,和天寶187A零件型號一樣,都是6RD035187A,但是我這台卻是德賽的。一樣的型號,卻有兩個製造商,這很有意思,就好比有一汽大眾和上汽大眾一樣…

在網上查了一些相關資料,得知德賽187A運行WINCE系統,沒有CarPlay功能和百度Life。天寶187A運行Linux系統,也沒有CarPlay功能和百度Life。

但是天寶187A可以刷187B的系統,天寶187A和187B的區別僅僅是DRAM內存大小和面板按鍵不一樣。187A是256MB 內存,而187B是512MB內存。

這就產生了一個問題,有些網友刷了系統後啟動時死機,但是換了512MB內存後就正常了。

由於本人對硬體也有研究,因此決定買一台天寶187A來研究一下,至於德賽……先好好地在車上服役,暫時不去虐他了…

關於天寶這個公司,也許是我才接觸汽車不久,之前沒有聽說過。德賽倒是聽說過,專門做汽車導航機器的,也給大眾代工車機。

江蘇天寶汽車電子有限公司(http://www.toppower.com),公司很低調,網站很簡陋…看一下職位招聘,都招什麼工程師,嗯,CAE工程師、項目工程師、電子工程師、製造工程師,就是沒有軟體系統工程師,那這機器軟體哪來的?大眾給的?外包的?此處留下疑問……


0×01硬體

接下來我準備詳細分析天寶187A的硬體系統。我從鹹魚平台上買了一台沒有刷過系統的天寶187A。拆機後看到了主板。

主板正面有很多晶元,首先看電源部分。電源由汽車蓄電池直接供電,汽車啟動後就是發電機供電,因此輸入電壓應是12-14V大概這個範圍。

首先電源經過了一個STPS41H100CGY,這是一個肖特基二極體,整流作用,不關心。然後有一些大電容,大電感,背面有一個SOT23-5封裝的IC,難道是DCDC?

由於這部分電路靠近功放IC,不想繼續追究他,無非就是一些給功放IC供電的濾波電路或者開關電路。畢竟車機接的是蓄電池,功放IC是不可能一直工作的。

接下來會看到很多電源IC,小電感,還有很多1206封裝的電容,這肯定是給CPU或其他晶元供電的部分。首先負責12V轉5V供電的有兩個晶元。

TI德州儀器SSOP-10封裝的TPS54260-Q1,IC絲印是5426Q。MAXIM美信QFN-28封裝的MAX16984,IC絲印是16984RA。

TPS54260是一顆寬電壓輸入(3.5V-60V),2.5A電流的DCDC降壓IC,在這裡設計12V輸入,5V輸出,由於電感體積很大,大過其他幾個電感,應該是主要供電。

美信的MAX16984是設計給USB供電的,電流是2.5A,很高啊,看來是可以滿足iPad2.1A充電的,設計的比較有良心……

往上看還有3顆電源IC,分別是兩顆德州儀器QFN-16封裝的TPS54388Q1,絲印5438Q,一顆安森美DFN-10封裝的NCV896530,絲印是完整型號。

TPS54388-Q1,2.95V-6V輸入,3A輸出。NCV896530,2.7V-5.5V輸入,兩路1A輸出。其中一顆TPS54388-Q1負責5V轉1.5V給DDR3內存供電,另一顆TPS54388-Q1負責5V轉1.375V給CPU核心供電。

NCV896530負責5V轉1.8V和3.3V,應該是IO供電和外設供電。

靠近大插座附近有一個CAN PHY晶元,附近還有一顆電源晶元,絲印是BLW N EO,查不到具體型號,但是他附近沒有電感,應該是一顆LDO降壓晶元,測量結果是12V轉3.3V,是給旁邊這顆MCU供電的,這樣大的壓差使用LDO供電非常不明智…

唯一的解釋就是這個MCU功耗非常低,使用LDO設計上合理,成本上也合理…

分析了這麼多硬體電源部分,感覺好無聊。其實在我看來分析一個系統是否成功,首先就要看他的供電設計,這部分是核心,供電設計的好不好,關乎整個系統工作是否穩定。

另外,我沒有看到高級電源管理IC,此處也是一個疑問,不過後面的分析可以解答這個問題。

接下來登場的是系統主要晶元。CPU是飛思卡爾(已被NXP恩智浦收購)公司的i.MX6DL,型號是MCIMX6S6AVM08AC。雙核Cortex-A9,最高1G工作頻率,內置2D/3D圖形處理單元,具有1080p圖像處理能力,支持豐富外設。看起來很強大的樣子…

DRAM是南亞的NT5CB128M16FP-D1H,16位,256MB,DDR3,1.5V。

快閃記憶體使用的是Spansion的ML02G100BHA00,256Mx8 NANDFLASH,3.3V。

還有一顆QFP-100封裝的晶元R7F7010253,直接搜索這個型號其實只能得知他是一顆瑞薩設計的晶元,其實他有個代號是RH850,搜這個代號能找到更多的資料,還有開發工具,但是就是找不到datasheet。

瑞薩這家公司主要設計生產MCU微控制器,汽車領域是其主要業務。

經過後面結合軟體部分的一番分析得知,這個MCU的作用其實是CAN通信、硬體身份信息(零件號,序列號)、電源管理。

沒錯,電源管理,因為汽車通信網是CAN匯流排,因此這款機器的電源其實也是受CAN匯流排管理的。

由於缺乏這顆MCU更詳細的datasheet資料,不能找到具體哪些引腳對應哪些功能,不過後來我還是找到了控制每個電源IC使能引腳(EN),以及CPU複位引腳(POR_B)所對應的引腳,這些後面結合軟體部分再說。

主板背面還有2個晶元,一個是ANALOG亞德諾的ADV7182,負責倒車影像攝像頭信號轉換(AV轉數字信號)。還有一個絲印是2313,查不到具體型號,看旁邊的測試點,和I2C匯流排相關,作用不明…

硬體就先講到這,大家是不是以為我是一個硬體工程師?

其實我只是個業餘的…硬體不是我的本職工作,不過我給公司客串過硬體設計,做過一個小產品,從硬體電路設計,到PCB Layout,從MCU固件,到產測軟體,都被我包了,公司小,又是做軟體的,請個硬體工程師沒必要,就讓我上了…還好這個項目比較小,不然我真要累死…

了解了天寶187A的硬體組成,就方便了接下來開展Hack行動!


0×02調試串口

Hack一台硬體和軟體公開資料並不多的主板,最好的入口點就是尋找他的調試介面。

很多產品的主板在設計時都會將TTL串口,JTAG這種關鍵的介面在主板上以插針或測試點(TestPad)的方式引出來,這種方式很普遍,比如說常用的路由器,大部分路由器都引出了TTL串口,少部分還引出了JTAG調試介面;3.5寸/2.5寸硬碟主板背面是不是有2排測試點?沒錯,這也是串口和JTAG。

其實不局限於常見的這些產品,絕大多數產品,都會引出TTL或JTAG,這主要是為了方便生產和測試,一顆CPU或MCU晶元、或者FLASH晶元,在工廠SMT貼在主板上後,裡面是沒有程序的,程序怎麼燒進去?

這就需要TTL或JTAG介面來實現了,有些帶USB介面的還可以從USB引導燒入。

串口和JTAG是生產測試所必須的介面,我想應該很少有人會把燒程序這個階段放在SMT工藝前面,再說還有測試環節怎麼辦,盲測?

不可能嘛……比如下面這張是從網上找到的硬碟主板和很常見的路由主板,上面都有TTL介面或JTAG介面。

有些人沒做過硬體開發,我在這裡簡單解釋下什麼是TTL和JTAG。

TTL串口他就是一個串口,TTL電平,基本都是3線,TX,RX,GND,相比RS232來說,控制引腳、狀態引腳基本都是不使用的。

這其實簡化了串口的使用難度,方便了開發,一般開發人員僅使用一個USB轉串口的小板就能完成與目標板的通訊。

串口主要用途就是列印日誌,方便開發人員確定程序狀態,或對目標板進行控制。例如可以查看引導程序日誌,打斷引導,執行燒寫固件指令,上傳臨時程序到RAM等等。另外使用串口還可以登錄Linux系統的終端shell進行操作等等。

JTAG介面是CPU調試介面,通常由TDITDO TCK TMS這4個主要信號組成,一些系統還有TRST信號,用於複位JTAG狀態機,還有nSRST用於複位CPU等等。

使用這個介面需要與CPU搭配使用的硬體調試工具,每個CPU廠商所使用的工具是有一些區別的。

JTAG介面用途廣泛,他可以在CPU上電後就打斷CPU的運行,並直接操作CPU寄存器。如果開發Bootloader,或者相關底層的工作,也需要用到JTAG。

在生產測試環節,JTAG還可以測試CPU是否正常工作,讀寫DRAM,判斷DRAM是否正常工作,還可以將程序燒寫入Flash。

由於JTAG調試介面過於強大,大部分情況下為了避免自己的產品被山寨,製造商都會在產測結束後禁用掉這個JTAG介面,方法是燒掉CPU裡面的熔絲,這個介面就不起作用了。

接下來開始在主板上找TTL和JTAG,JTAG很好找,就在主板背面,有幾個較大的測試點,標明了TDI TDO TCK TMS等字樣,這些應該就是CPU的JTAG介面了。

但是JTAG熔絲很可能被燒掉了,JTAG介面估計是廢的。主要還是要找到調試串口。

雖然有找到一些標註了TXD RXD絲印的測試點,但是很遺憾,經過連接測試後,這些並不是CPU的TTL調試串口,系統上電後根本沒有任何字元串輸出。

難道這個主板在設計時沒有引出TTL串口嗎?這怎麼可能,太愚蠢了吧…

由於這個主板測試點非常多,密密麻麻很多小測試點,根本沒有絲印標註,難道TTL串口就隱藏在這些沒有絲印標註的小測試點嗎?

在這麼多測試點裡找到串口TX和RX信號,這看起來像是不可能完成的任務!

主板正面有兩個沒有焊接排線插座的焊盤,這兩個排線插座都是18pin的,其中一個走線靠近瑞薩MCU,有可能是瑞薩MCU的產測介面。

另一個排線插座頂層走線既不靠近CPU也不靠近MCU,但這並不意味著他沒有在內層電路與CPU相連,這很有可能主CPU的產測介面。

但是很遺憾當時我並沒有意識到這一點,我已經被密密麻麻的小測試點逼得抓狂了。接下來我甚至做了一系列現在想想覺得很愚蠢的事情,在此分享出來吧。

我在鹹魚上聯繫一位網友花廢品價買了他一個報廢的主板,為的就是拆CPU,尋找TXD,RXD的走線。我把主板上了熱風槍拆焊台,把CPU吹了下來。

尋找NXP的SDK開發資料,找到了一個參考板的電路圖,得知調試串口極有可能是UART4,TXD是Pin_W5,RXD是Pin_V6。

我根據Datasheet上的引腳圖去找W5和V6,然後通過BGA過孔找到背面的過孔焊盤,把焊盤的阻焊漆颳了,飛線,連接USB串口,上電發現並沒有任何信息。

難道廠商的UBOOT沒有啟用串口?或者配置了額外的引腳作為調試串口?因為找不到正確的調試串口Pin,我的研究一度陷入了停滯。

接下來,我從網上找來網友分享的187A升級包,裡面有Uboot鏡像文件,我上了IDA,對比SDK中的Uboot源代碼,找到了配置調試串口的數據。


ROM:178013AC dword_178013AC DCD 0x62C244 ; DATA XREF: sub_17801278+C8ROM:178013B0 dword_178013B0 DCD 0x10000100 ; DATA XREF: sub_17801278+D4ROM:178013BC dword_178013BC DCD 0x14640258 ; DATA XREF: sub_17801278+ECrROM:178013C0 dword_178013C0 DCD 0x3716348 ; DATA XREF: sub_17801278+F4r

通過分析uboot頭文件mx6dl_pins.h中的宏定義,得出這就是頭文件中定義的


MX6_PAD_DECL(KEY_COL0__KEY_COL0, 0x062C, 0x0244, 3, 0x0000, 0, 0)
MX6_PAD_DECL(KEY_ROW0__UART4_RX_DATA, 0x0640, 0x0258, 4, 0x0914, 3, 0)

對比datasheet,確定了串口4使用的確實是W5和V6。這就奇怪了,難道調試串口不是串口4?後來我又定位到了puts函數,然後進入putchar函數,發現寫入的確實是串口4的寄存器……

現在已經可以從代碼上確定,串口4就是調試串口,使用的引腳也確實是CPU的W5和V6,那為什麼我在串口上看不到任何信息?

此刻我已經被密密麻麻的測試點、BGA過孔、沒有任何符號的UbootIDA反彙編,折磨的想要放棄了。

過了幾天,我覺得不服,錢不能白花,決定再戰。我檢查了Datasheet是否是這個型號CPU的Datasheet,仔細研究了BGA焊盤,過孔,走線,引腳圖……

等下,我看到datasheet引腳圖上面寫的是Bottom View!HOLYCRAP!我把這個圖當作Top View來看了!

怪不得,我之前找的引腳是錯!的!我把圖垂直翻轉,然後右轉,右轉,對齊了PinA1,找到W5V6的過孔,刮背面過孔焊盤,飛線,上電……串口終於找到了!此刻成功激動的心情簡直無以言表……

後來我意識到那個18pin的排線插座極有可能引出了UART4,用表測了下,發現果然如此,那我之前的一系列行為豈不是很愚蠢……不過我又研究了這個18pin,發現他還引出了JTAG,USB Host。

接下來的研究,其實並不是按我文章的章節順序展開的,我的研究流程比較混亂,因為涉及的內容繁雜,相互糾纏。因此本文接下來的內容並不是嚴格按時間順序展開的……


0×03 UBoot Hack

他的這個UBoot並不是SDK裡面的Uboot,畢竟硬體設計上與參考板設計不同,Uboot代碼有所改動是理所應當的。

但這個Uboot不能被打斷引導,令我很頭疼。萬一我折騰折騰著,把Kernel搞死了,這塊主板就變成了一塊磚。由於我沒有NAND編程器,沒辦法對Flash燒寫恢復,一旦成磚我還怎麼研究下去?

我需要準備一個PlanB……

首先我要想辦法打斷Uboot的引導,進入uboot提示符,然後使用uboot指令,用命令傳輸數據,就有可能對磚機進行修復。

我首先查看了他的Flash布局:cat/proc/mtd


I have no name!@(none) /$ cat /proc/mtddev: size erasesize namemtd0: 00400000 00020000 "bootloader"mtd1: 00c00000 00020000 "nand.kernel"mtd2: 0d000000 00020000 "nand.rootfs"mtd3: 00a00000 00020000 "pss1"mtd4: 00a00000 00020000 "pss2"mtd5: 00c00000 00020000 "logo"

可以發現並沒有uboot環境變數分區,那麼環境變數可能是固定寫死在uboot固件裡面的,WinHex確實找到了這部分區域。

有一個變數叫bootdelay,值為0。

怪不得不能被打斷引導,我把這個值改為3,想著把他刷進去試一下看看。接下來怎麼把uboot刷進去又成了一個問題。

最簡單暴力的辦法是用dd命令直接從/dev/mtd0或者/dev/mtdblock0寫進去,那萬一寫成磚怎麼辦?

這個方法太危險,NAND Flash的操作與SPIFlash可能不同,因為NAND是有OOB區域的,裡面有ECC校驗,我不能冒險。

接下來我分析了這個系統的更新程序,/opt/sysupdate。

這個程序雖然去掉了一些符號表,私有函數在IDA裡面看來都是sub_XXXX,但是由於他使用了一套日誌介面,log_optional,裡面列印了源文件名,函數名,行號等信息,一些函數可能被編譯器整合優化成一個函數,但還是可以猜出絕大多數函數的功能。

經過一番分析,確定了他更新uboot使用了外部命令kobs-nginit -v ./uboot.bin。這個命令可能來源於NXP i.MX6 SDK,不管了,先把uboot複製到優盤,插入車機,輸命令更新uboot。

完成重啟,發現bootdelay沒生效,並沒有出現等待用戶3秒輸入打斷引導的環節……

我X,廠商竟然把bootdelay這部分代碼注釋掉了嗎?這不科學啊!

不過我又想到了一個辦法,把bootcmd這個變數擦掉,這樣uboot沒有了啟動命令,自然就無法引導了吧。於是上WinHex,找到bootcmd=,修改成aootcmd=。刷機,重啟,發現確實中斷了引導。

但是這種辦法帶來的後果就是,每次啟動,都需要手動輸入命令才能引導系統,不是什麼大問題,準備記事本每次複製粘貼啟動命令就可以了…


nand read0x10007FC0 0x400000 0x300000; bootm0x10007FC0

現在可以在uboot提示符下操作了,help查看幫助,看看支持哪些命令,沒有網路相關的,因為這主板上沒有導出乙太網IC……那用什麼命令恢復變磚的主板呢。【詳情點擊閱讀原文】

有一個sdma命令,好像是從sd卡傳輸數據?

找了下NXP官方uboot,並沒有這個命令,網上也找不到這個命令的詳細用法,但是我隨便敲了下,想要測試下這個命令看看出現什麼結果,卻發現這個命令是無效的。因為給出的提示是這樣的【點擊閱讀原文查看】

可以看到這個命令應該是3個參數的命令,但是這一行SDMA initialization failed表示命令失敗了。看來沒戲,按照之前對開發者的理解,他一定是在uboot發行版本中,把這個功能閹割掉了,或者是根本沒實現。

那還有哪些命令可以從外部傳輸數據呢?


loadb - load binary file over serial line (kermit mode)
loady - load binary file over serial line (ymodem mode)

從串口傳輸數據,協議是kermit和ymodem,這倆我很熟悉,以前救路由磚的時候用過,WinXP的超級終端就支持這種文件傳輸協議。

其中一個比另一個傳輸速率稍快一些。但是快能快到哪?理想狀態下115200/8 = 14.4KB/s,實際上達到10KB/s就燒高香了。

雖然速度奇慢,這畢竟是一個救磚的PlanB,在缺少NAND編程器的情況下,也許這兩條命令就是最後的救命稻草了。

或許我可以從固件升級包提取文件,製作一個最簡的rootfs,加上內核,估計也就5MB左右……先通過這個內核引導,然後有了USB支持,就可以用USB傳輸了。

接下來我還思考了下,通常情況下,製造商如何燒入鏡像。

我查詢了NXP的開發資料,可以配置CPU的BOOTMODE,讓CPU從USB引導,然後使用一個叫mfgtools的工具,傳輸bootstrap鏡像到RAM,然後再通過USB或乙太網傳輸文件,寫入Flash。

這個bootstrap鏡像其實就是我剛才所想到的,kernel和精簡的rootfs。

這種方法的關鍵在於如何將CPU配置從USB引導,這其實也是一個問題,因為這個配置是可以被製造商通過燒eFuse區域寫死的(或者說OTP區域,One Time Programmable),也就是說,這個USB引導,在工廠生產階段能用,用完之後把這個配置區域寫死,就沒人能改變CPU的引導方式了。

在uboot提示符使用md命令查看看了eFuse區域寄存器,確實已經被寫死了。除非買一片新的CPU換上去,但是新CPU沒有eFuse配置,需要從外部引腳配置BOOTMODE,電路改動難度非常大,幾乎不可能完成。

所以通過改變BOOTMODE,從USB引導,利用mfgtools燒固件救磚這個思路,沒戲了。

我想,我已經有了一個PlanB,就是有提示符的uboot,就算搞成磚,也有辦法修復,但是事情事實上遠沒有這麼簡單……我發現UBOOT中斷引導後,系統每隔60秒就重啟。

那如果我用串口貓協議傳輸文件,60秒能傳輸多少數據!況且還有後面的kernel引導!60秒什麼都做不了!

這種情況一定是有看門狗。

看門狗是什麼?看門狗是一種預防機制,可以防止CPU或程序異常,導致產品失去正常功能。原理其實很簡單,做一個定時器,定時器溢出了,就給CPU發送複位信號。

為了防止定時器溢出,就必須有一個程序負責清空定時器,這個環節就叫做「喂狗」。如果因為CPU或程序異常因素,導致這段喂狗程序無法正常運行,那麼CPU就會被看門狗無情的複位!

一開始,我覺得可能就是CPU內部集成的看門狗吧,反彙編uboot,把放狗的代碼屏蔽掉就好了……用IDA確實找到了一處寫看門狗寄存器的代碼。

寄存器0x20BC000在datasheet上就是 WatchdogControl Register (WDOG1_WCR)(這CPU有兩個狗),uboot寫了狗1的寄存器,寫入的4恰好是WDE(Watchdog Enable),沒錯,跑不了,這個函數絕對叫EnableWatchdog!

可惜當我HACK掉這個函數,把第一句改為BX LR,讓其直接返回。實驗結果是狗並沒有被關閉!

後來研究代碼發現這段代碼根本就沒有在啟動流程被調用……這段代碼的作用其實是ResetCPU(uboot reset命令)。


0×04看門狗

沒想到費勁研究出的uboot救磚方案,竟被一隻瘋狗給破壞了!既然不是CPU內部的狗,那就一定是外部的狗!

這回沒錯,跑不了,肯定是瑞薩那個MCU乾的!

首先我想弄清楚他是怎麼複位CPU的。這個CPU沒有RST引腳,只有一個POR_B引腳,其實就是個低電平的PowerOn Reset,POR引腳通常不是設計用來複位CPU的。

系統在剛開始上電時,供電電路電壓還不穩定,CPU不能正常啟動。這一般就需要由供電晶元的PG(Power Good)引腳輸出,來通知CPU的POR引腳。

大致可以理解為是電源IC給CPU說:「大哥,我的電壓穩定了,你可以正常工作了!」不過,一旦電壓失穩,PG電平改變,CPU一樣是會複位的!

我自信滿滿的認為是瑞薩的MCU通過拉低POR_B引腳來複位CPU的,於是用表開始找,找了小半天,竟然沒找到,這個POR_B沒有與MCU直接相連。

在這裡分享個尋線小竅門,數字表調整到歐姆檔,SELECT啟用短路告警,這樣一旦探測到短路的位置,表的蜂鳴器就會嗶~~,於是尋找的方法就變成了,一個表筆按在POR_B的測試點上,一個表筆在MCU引腳上划來划去。

可惜沒找到!難道不是通過拉低POR_B來實現複位的?

後來我發現,在複位的時候,機器的按鈕背光燈,短暫的熄滅了零點幾秒,難道複位的方法是關掉整機電源然後再打開!沒錯,這個MCU一定兼職了電源管理晶元的功能!

於是我開始找那幾個電源IC的Datasheet,找到他們的EN使能引腳,然後找這些引腳與MCU的哪些引腳直接相連。

可惜又沒找到!這不科學!難道不是直接相連,難道中間串了MOS管或三極體什麼的?這沒必要啊!難道中間串了電阻,電阻拉高,MCU開漏輸出?

查了下,使能引腳是高電平有效,那電阻是拉低,MCU輸出高電平唄!在MCU附近尋找,果然發現了一些布局類似的電阻,然後你猜怎麼著,我真的找到了與所有電源IC的EN引腳相連的MCU引腳!

現在事情清晰了,整套系統的供電都受MCU控制,MCU內部還實現了一隻看門狗,來複位整套系統,並且複位的方式是控制所有供電IC的EN引腳。

我想,可以直接把這些供電IC的EN引腳全都改一下,全都拉高,不過這很麻煩。CPU的上電其實是有時序要求的,哪個電壓先來哪個電壓後來,都是有講究的。除非是在CPU上電之後再去HACK EN引腳。

不過這麼一堆EN引腳,貿然去改動硬體來bypass看門狗,

說不定還有其他什麼我沒發現的坑,

有一定失敗風險,直接在硬體上做改動,難度較高。

除非搞到喂狗指令,不然這個狗是很難繞過去了,我決定先放棄尋找關狗的方案。


0×05軟體系統

接下來我主要研究的內容就是分析整套軟體。分析其軟體構成,軟體包,庫,驅動,內核模塊。

Ubi0:rootfs是根文件系統,他的文件系統是ubifs,這是一套專門為NAND Flash設計的文件系統,具有壞塊管理功能。

pss1和pss2裡面文件不多,結構一樣,估計2是1的備份。

看文件名猜測應該是與軟體配置相關的一些東西。

再看看/dev目錄,都有什麼設備。fb(framebuffer)是顯存。event0和event1可能是鍵盤和觸摸板。

3個i2c介面,用途不明,可能是配置功放晶元,攝像頭晶元或者觸摸板,收音機等用途。

一個spi介面,通過分析/opt/libHAL.so發現是與MCU通信用的。

tuner_knob,可能與前面板兩個旋鈕相關。

v850srq,這個看名稱就知道肯定也和MCU相關,因為那個瑞薩的MCU代號是RH850,而這個MCU的指令集就是NECV850,IDA恰好支持這個指令集。

video設備可能就是倒車攝像頭晶元ADV7182的介面。

再看看etc/rc.d目錄,有一些系統引導腳本,文件不多,很好分析。

我可以修改其中的rcS腳本,在裡面插入一個read-t 指令,這樣我就可以打斷Linux系統的引導,來製造一個failsafe模式。

這個模式有什麼用呢?其實就是為了防止後面的修改出錯,導致系統直接崩潰掉了。有這個failsafe模式,我就可以回退修改。例如還沒進入終端系統就崩潰了,我只能在uboot模式恢復系統了,會很麻煩的。

但是暫時這個修改沒有用,因為需要喂狗程序,這個程序在哪,是哪個程序,我都不能確定……先算是一個思路吧。點擊閱讀原文查看/opt目錄。

這裡面都是車機的應用程序,有庫,配置,圖片字體資源文件,各種腳本……

先看看正在跑的都有哪些程序吧。ps -ef

發現有很多進程,由於名字都是縮寫,很難直接猜出這些程序的用途。例如vmf、mfid、vgw、hmi、exlap、diag等等這些都是鬼?他們大多沒有-h –help 之類能顯示信息的參數可用,想知道他們的用途,估計是要上IDA逆向一下……

經過了幾天的研究,我終於知道了部分核心程序的用途。

他這套軟體,大部分都是在後台工作的,只有少部分是QT編寫的,有界面的。例如hmi和sysupdate。其中hmi體積最大,他就是界面主程序,他包含了所有的圖形資源,多國語言字元串。

其他程序基本都沒有界面,界面其實都是在hmi中。UI進程和邏輯進程之間使用類似IPC的消息機制,這個機制在這套系統中稱為vmf。

那個vmf程序,起到一個消息中轉站的作用,vmf可能是Virtual Message Function的縮寫?他有Usage信息,顯示的是vmffor linux version DOMAIN-SOCKET。

/opt/lib/libvmf_client.so這個就是vmf客戶端支持庫,很多程序通過調用libvmf_client.so的nw_vmf_send/receive函數來實現跨進程的IPC消息傳遞,這套消息機制是基於socket。

在/tmp/目錄有很多127.X.X.X文件,可能與此相關。在文章後面,我將詳細分析這套API的原型和消息數據結構。pwr_agent,從名字看,顯然是電源管理相關,我一直認為就是這個進程,在不斷地與MCU通信,喂狗。

我用IDA把他逆了個遍,他確實有這個動作,但是他只是構造了個消息包,包發給了誰並不知道……他其實不光是電源管理,在/opt/launch.sh腳本中可以發現,腳本執行了vmf hal_init pwr_agent sysupdate mfid,就沒有了。

其實大多數進程,都是由pwr_agent帶起來的,這在IDA逆向中能發現。點擊閱讀原文查看詳情。

hal_init,這個進程很簡單,只是調用了libHAL.so庫中的一些初始化函數就結束了。

vgw,這是關鍵進程,我發現把他殺了,系統過一會就重啟,所以他是喂狗嫌疑對象。

通過逆向,發現他調用了libHAL.so裡面的spi_ipcl_read、spi_ipcl_write等函數,通過Search And Replace搜索整個opt目錄也證實,只有vgw程序調用了上面的spi_ipcl_read/write介面。

這個vgw是什麼縮寫,我沒找到,可能是Vehicle Gateway或者VIP Gateway?感覺這種解釋不太靠譜……

/opt/lib目錄就是這套程序的庫文件了。重點關注其中的2個,libOSAL.so和libHAL.so,前者是操作系統支持庫,可能是為了方便跨平台開發,將一些系統級API重新封裝了一下,例如線程,定時器,互斥鎖等。

後者是硬體層面的介面,包括uart,spi,gpio,i2c等介面的讀寫函數封裝。其他都是carplay carlifemirrorlink等程序的支持庫。

/opt裡面很多程序都被strip掉了符號表。在IDA分析時沒有符號幫助,很難搞懂一些函數的作用,還好這些程序都調用了日誌介面log_optional來列印日誌,因此能獲知一些函數的真實名字,以及他們的用途。比如下面這個例子:

顯然,得知這個函數名字叫pwr_agent_vmf_rcv_handle_round_comm,日誌類別是radio_updown。

log_optional的消息列印是受配置文件控制的,這些配置文件以進程名作為區分,位於/opt/config或/pss1/config。

例如原文中這個pwr_agent的config,可見有很多開關,控制了哪些debug消息需要列印,哪些不列印。把一些需要的開關打開,可以方便逆向分析工作。主要開關就是ENABLE=1,OUTPUT是類別控制,控制對應的類別的日誌要列印出來。

/opt/ftpdup2.sh這個腳本很有意思,他insmod了asix.ko,然後用ifconfig配置了ip地址,還啟動了ftp服務。

看來是開發人員為了方便網路傳輸文件留下來的。這個asix.ko是ASIX的usb轉乙太網晶元的驅動,很多常見的USB轉網口的產品都是用ASIX晶元方案,例如綠聯的USB百兆網卡。

我試著運行了一下,確實把網卡帶起來了……

/opt還有一些usbgadget驅動程序,例如g_ether.ko和g_file_storage.ko,由於這台機器前面板的USB介面實際上是CPU的USB_OTG介面,因此我懷疑開發人員用這個驅動,直接把USBOTG虛擬成MassStorage或者網卡,與開發機用USB線連起來就能傳文件了,是不是很有意思……

另外我還在/opt/tools發現了兩個小程序。Search AndReplace搜索後發現,這兩個程序並沒有被任何程序或腳本使用,應該是開發人員在開發或調試時留下的,有意思……這個vmf_send很有用,後面會用到。


0×06升級包分析

不知道網友有什麼渠道,拿到了還沒有發布的187B的升級包,上傳到了網上,可以在百度網盤、或QQ群,找到這些升級包。用升級包給187A升級後,可以比原系統多出許多高級功能。

比如蘋果CarPlay,百度CarLife,還有什麼超級藍牙,我也沒用過,不知道具體是怎麼個超級法…

網友放出來的這些升級包,事實上可能都是開發階段的測試包,有很多bug。有一個固件要求運行內存是512M,在256M的機器上刷了會變磚。另一個固件包支持256M內存,但也是Bug最多的版本。

所以很多網友把天寶187A的機器換了內存,還有一些商家提供此類換內存服務,或者售賣已經換好內存的車機。

另外有少數商家有5314版本的升級包,這個版本與上市後的187B系統版本相同,估計算是正式版。

但是這個升級包在網上找不到,貌似只掌握在少數以刷機為盈利目的的商家手上,且不外賣,在鹹魚上賣的5314據說都是假包。

接下來研究一下升級包的構造,升級包其實就是一個tar包,沒有簽名。

例如這個版本的包用7z打開是這樣

用戶名組名是wangshi,王石?看來製作升級包的系統,有是一個叫wangshi的用戶,也許這個也是那位工程師的真實姓名……

看一下根目錄的config.txt文件


kernel_update:1
bootloader_update:1
vip_update:1
bt_update:1
middleware_update:1
[file]:[opt] [file]:[etc] [file]:[usr][file]:[mirrorlink][file]:[lib/firmware]

好簡單的設計,一目了然啊……

其中的vip_update其實指向的是vipImage.bin,大小1MB,文件末尾有哈希。這正好是瑞薩MCU的Flash大小,那麼這個MCU在軟體內部就是被叫做VIP咯,VIP是什麼呢?Very Important Processor?Vehicle InformationProcessor?

其實如果知道了這個MCU的地址空間布局,完全可以拖進IDA逆向一下,看看裡面的具體實現……

不過經過後來一番分析,已經知道了VIP的大致作用:CAN匯流排通訊,身份信息,電源管理等等。身份信息包括零件號,平台(PQ/MQB),序列號,車型(VW/SKODA)等。

現在知道這個MCU的代號其實就是VIP了,而且在分析軟體程序的過程中,有很多字元串提到了VIP,那麼我在後面文章就以VIP來稱呼吧。

bt_update就是藍牙了,這個機器的藍牙模塊是ALPS的一款模塊,網上找不到任何資料。與CPU的通訊是通過UART串口。升級包bt_ac_firm目錄裡面的文件就是藍牙控制晶元的固件了。

middleware就是中間件了,也就是opt那些目錄,想覆蓋哪個目錄,寫進config.txt就可以了。

升級包還有一個配置文件/opt/stdplus.ini。


[Version]AP_VER=5.4.1.1CUSTM_PQ=Y307CUSTM_MQB=Y307UBOOT_VER=uboot_1.3.2UIMAGE_VER=uImage_5.0.11KERNL_VER=3.0.35BT_VER = C150VIPAP_VER=5.4.1.1VIPBL_VER=2.0.2[Upgrade]PACK_TYPE=VW_PQ_PSS[CODING]BT=0CODINGS=0

裡面有兩個欄位是必須的,Version小節的AP_VER欄位,不能與主機/opt/stdplus.ini一致,否則sysupdate升級時會提示變數衝突。有Upgrade小節的PACK_TYPE,必須與主機/opt/stdplus.ini保持一致,否則不能升級。

其他欄位都是可選的,根據升級需要設定即可。

另外升級包裡面有一個script目錄,裡面有兩個腳本。

看名字很容易猜得出,一個腳本是更新前執行,一個是更新後執行。

另外還有一個有意思的地方,用7z解壓縮那個kernelImage,記事本打開,搜Linuxversion,可以看到編譯人員的機器名和用戶名,如圖。

看,機器名是HP-640,用戶名是changchun,難道內核編譯人員來自長春?

升級包的結構清楚了,再通過逆向/opt/sysupdate,就對更新過程有了進一步了解。


0×07更新流程分析

通過逆向/opt/sysupdate可以對更新流程有個大致了解,具體的逆向分析流程我不多說了,他這個程序是qt寫的,在log_optional這個日誌列印函數的幫助下,很容易逆向/跟蹤出具體流程。

流程大致就是:驗證包合法性,設置/sysupdate/flag.ini更新標誌,保存包文件名,重啟系統,重啟後rcS腳本檢查flag.ini文件,得知需要更新系統,然後走更新系統流程,啟動sysupdate。

sysupdate執行run_before_app_update_sh,刷內核(訪問/dev/mtd,不是通過dd),替換中間件(hostapp),刷bootloader(調用kobs-ng命令),執行run_after_app_update_sh,刷藍牙(uart傳輸),刷VIP(spi傳輸)。

這個更新流程中的重啟,很有意思,不是調用的reboot命令,而是硬重啟!

我打開了sysupdate的log日誌功能,通過日誌輸出,可以大致確定他是通過調用SendUpdateStatus(this, 1)來實現重啟的,因為列印了這個日誌就就沒有日誌了。

SendUpdateStatus這個函數發出了一個vmf消息,可能被vgw接收了,然後被vgw轉手發給了VIP,由VIP觸發了重啟動作。

這個函數的名字是SendUpdateStatus,發送更新狀態。估計VIP還關注了更新的狀態,能夠根據更新狀態來產生不同的動作,而這個狀態1,就對應著複位CPU。

另外我還發現,一旦這個命令發出去重啟了CPU,狗就被關起來了!電源不會每隔60秒被重置一次,這是一個很有意思的發現!


0×08破解通訊協議

現在知道的情況就是,pwr_agent肯定有一個定時器,每隔一段時間喂狗,sysupdate能通知VIP更新狀態,當狀態為1時,VIP就關掉了狗。

現在就有了兩種辦法關狗,一個是利用喂狗協議,一個利用升級狀態協議。都是通過協議,現在沒有協議,怎麼辦呢,想辦法抓到通訊協議就好辦了。

與VIP通訊的是vgw進程,IDA看看他裡面的函數,有幾個spi_ipcl_xxx的函數引起了我的注意,看來是通過調用libHAL.so的spi_ipcl_xxx讀寫函數實現通訊。前後找了下,沒有可以利用的log列印。

再看看libHAL.so的spi_ipcl_write,竟然有日誌列印,這太好了……

spi_ipcl_read也調用了這個IPCL_Print_Msg,第三個參數控制了是否輸出日誌,可惜被傳了0,估計是一個宏開關,被編譯時指定的。這難不住我,用WinHex把對應的指令位元組碼改掉。

有兩種改法,改IPCL_Print_Msg外部call的傳參,也就是0改成1,把MOV R2指令改成 MOV R2,#0就可以了;還可以進入IPCL_Print_Msg內部去改,去掉對第三個參數的判斷,也就是將前面的LDMEQFD指令改成NOP。

由於IPCL_Print_Msg並不能列印出這個消息是read還是write,因此我使用前一種改法,改出2個文件,libHAL.so.read和libHAL.so.write,並備份原機文件為libHAL.so.bak。另外這個printf的fmt是「 %x 」,輸出內容會很不友好,我改成了 「%02x 」。

有了這樣3個文件,我就隨時可以根據一條shell命令來更換libHAL文件。


恢復libHAL
mount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.bak libHAL.so.1.0.0設置IPCL readmount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.read libHAL.so.1.0.0設置IPCL writemount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.write libHAL.so.1.0.0

由於我替換的是系統關鍵庫,為了避免錯誤發生,我修改了啟動腳本rcS,加入了一個failsafe安全模式功能。改法是這樣的

這樣修改後,在系統啟動時,我有一秒時間來輸入y回車來進入安全模式,防止修改/opt/lib庫文件導致系統關鍵進程無法啟動、系統崩潰。

不過因為沒有喂狗,這個安全模式是有時間限制的,複製粘貼上面的指令能迅速幫我還原備份文件。

首先我替換了libHAL.so.write文件,重啟後串口終端確實列印了大量通信報文。我發現每隔1秒都有一個8位元組的報文送出,且有類似遞增序號的位元組,沒錯這一定是在喂狗!

另外我也抓到了sysupdate在調用SendUpdateStatus(xxx,1)關狗並重啟時的8位元組報文。也在上面的圖片中

這些報文都是vgw進程通過spi_ipcl_write向VIP寫入的。而這些報文的實際發起者其實並不是vgw。喂狗是pwr_agent發起的。關狗重啟是sysupdate發起的。

雖然我可以通過調用libHAL.so的spi_ipcl_write來實現我想要的喂狗和關狗功能了,但是這要編譯一個小程序,編譯程序需要準備交叉編譯環境,還要把這個程序放進去……呀,好麻煩……

為了體現我的高端,我還進一步研究了進程間的通訊,也就是那個vmf消息。比如這個喂狗流程應該是這樣的:pwr_agent定時器,構造了一個包,發給了vmf,vmf轉給了vgw,vgw通過spi喂狗。

是不是很複雜?沒錯,廠商確實是這樣設計的,這套消息也確實是這樣工作的……因為我把vmf殺掉,vgw就收不到消息,不再喂狗了。

首先我想用sysupdate來展開分析工作,我感覺我對這個程序了解的更多一些。我先用IDA定位到SendUpdateStatus(int this, int arg_status)。

這個函數第二個參數就是狀態值,有1、2、3、4、5、6、7……之類的,在這裡關狗重啟status值為1。他構造了一個5位元組的包,傳給了UpdateSendVmfMsg。

構造的包其實就是5個位元組, 8F 19 00 01[StatusByte]

UpdateSendVmfMsg(_BYTE*arg_databuf, int arg_datalen)函數又將收到的包調用PackVmfMsg重構了一下,然後把重構的包調用libvmf_client.so!nw_vmf_send_basic發出去了。先看看包是怎麼被PackVmfMsg重構的。

char __fastcallPackVmfMsg(_BYTE arg_databuf, unsigned int arg_datalen)

目前只是知道了數據包的布局,但是具體的欄位含義還不清楚,例如那個8F是什麼,19是什麼,00 01有可能是BigEndian的包長?不過通過交叉引用vmf的消息處理接收函數nw_vmf_receive(inthandle, char *buf, int bufsize)不難得出,這個8F其實是groupid,19是eventid。

例如下面是對pwr_agent程序的nw_vmf_receive交叉引用分析出來的log_optional。

從這個log_optional的上下文代碼中,我得出了這個vmf的數據包結構:


Offset Type Value0 byte 定值220 byte groupid21 byte eventid24 word payload_len26 byte[] payload

看起來很簡單,只要按照這個數據結構把包發出去就可以了。這時就可以利用前面分析文件系統時發現的/opt/tools/vmf_send。

這個文件很小只有7K,拖進IDA,雖然沒有usage消息,但是很輕鬆就逆出了他的用法:

由上面main函數得出vmf_send的用法


Usage: vmf_send [groupid] [eventid][payload_dec_byte0] [payload_dec_byte1] ...

有了這個命令,理論上我只需要知道groupid和eventid,就可以用vmf_send發送vmf消息給相應的進程,控制其產生相應的動作。例如上面分析到的關狗重啟vmf消息,我可以調用vmf_send命令:


/opt/tools/vmf_send143 25 1

這樣vgw就會收到vmf消息,然後發送8個位元組的SPI報文給VIP,觸發VIP的關狗重啟動作。

有了vmf的相關函數原型以及vmf消息結構,我又逆向了pwr_agent,找到了他的喂狗程序。

然後分析出了喂狗的vmf消息結構,現在終於可以調用tools/vmf_send來發送喂狗消息,我寫了一個腳本來實現後台喂狗;

為了驗證這個腳本是否有效,我重啟進入failsafe模式,順序啟動vmf,啟動hal_init,啟動vgw,然後再運行這個腳本,過了1分多鐘,狗確實被喂的很舒服,沒有出來亂咬!哈哈!

現在就可以完善這個failsafe模式了,修改rcS腳本。

這樣系統就有了具有喂狗功能的failsafe模式,是不是很厲害!


0×09 後記

至此,我已經有了一堆PlanB,我可以放心大膽的折騰這台機器了……

接下來的研究就輕鬆的多了。我又研究了很多有意思的東西,例如:


a)導出187A原廠文件系統
b)做了個升級包能把rootfs導出來。但是不包括藍牙和VIP固件…
c)Hack了512M版本的固件,讓他在256M內存上完美的跑起來了。
d)由於升級後,車機前面板鍵位錯亂,是187B的鍵位,因此我Hack了hmi修改了鍵位。
e)寫了個小程序生成BITMAP並計算哈希,做了個升級包可以替換開機Logo。
f)做了個升級包能進入一次failsafe模式,並載入網卡驅動,啟動ftp…
g)做個原機備份固件。
h)有網友提供了編程器固件,從編程器固件提取uboot、kernel、rootfs。
i)...

等有時間我準備把上面的abcdefgh,和新研究出來的東西發在這裡,作為續集。希望這篇文章,能給同樣愛好折騰硬體折騰軟體的人帶來一些幫助……


*本文原創作者:mengxp,屬Freebuf原創獎勵計劃,未經許可禁止轉載


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 FreeBuf 的精彩文章:

基於Python的遠程管理工具(RAT) – Stitch
這玩意據說是「最先進的USB攻擊平台」,只賣99.99美元
雙尾蠍(APT-C-23):伸向巴以兩國的毒針
Mariadb蜜罐 | 用改造過的服務端攻擊客戶端
遊戲篇——移動 APP 安全行業報告

TAG:FreeBuf |

您可能感興趣

華碩飛馬4A曝光,OPPO R11限量禮盒開始預約,vivo下周有新機,高德車機版升級
9-10.2寸車載大屏暴漲60%,車機廠商快要養不起工廠了!
名爵銳騰互聯網版上市 14.58萬起 車機贊
吉利帝豪GS新車上市:車機更好用/貴3000也值
Uber掌握了多少谷歌無人車機密?400多條簡訊首次曝光
「曝光」Uber掌握了多少谷歌無人車機密?400多條簡訊首次公開
鋼鐵第一龍頭股106慘跌至6元,中報暴增6382%,周三最後上車機會
樂高賽車機械組只要158,陶瓷刀秒殺價29
先鋒發布5款CarPlay車機 無需購買新車也可使用
8天小長假,4G大屏車機助你車上生活更有趣!
5G概念龍頭浮出水面,國家隊增持800億目標68,上車機會已到!
深夜23:05分市場釋放重磅要聞,明日A股迎來搭車機會?
次新5G概念龍頭浮出水面,主力增持10億目標35,上車機會已到
次新5G概念龍頭浮出水面,主力增持18億目標28,上車機會已到!
次新5G概念龍頭浮出水面,主力增持10億目標26,上車機會已到!
[動圖]海康威視泊車機器人:2分鐘停好/精度誤差小於5mm
重磅A股利好消息,100點大漲空間,明天或現最後上車機會!
2017智能車機產業鏈深度解析
5G概念+電子信息龍頭浮出水面,主力增持35億目標48,牛散:上車機會已到!