記一次RTEMS系統的固件解密
1、前言
近期翻閱之前的工作,發現在考勤機系列的安全研究里,有一篇很早就整理好但是沒發出來的文章,考慮到相關設備的漏洞已經提交了快兩年了,想必該修復的也修復了,設備可能都已經不再生產了。這篇文章我們主要聊一下這個設備的分析過程,著重描述一下這個設備的固件解密。
2、IoT設備啟動概述
IoT設備的安全分析中,分析人員的主要工作是分析設備的邏輯功能及其代碼實現,從而挖掘設備中的漏洞。大多數分析工作是從解析固件開始的,如果這一步就不順利的話,后續可能會更加麻煩。不巧的是,這次的設備在起步階段就很曲折:固件被加密了,并不能直接開始分析。
在此我們再簡單總結一下那些常見IoT設備的啟動流程,如下圖所示:
圖2-1 IoT設備大致的啟動流程
上圖大致可以分為4個階段:
(1)首先,芯片上電后首先運行的是boot rom,執行完畢后會跳轉到bootloader,如果設備啟用了固件簽名,那么此處會對固件進行校驗;
(2)然后,bootloader的作用類似于PC啟動過程的引導,主要功能就是為操作系統的運行做準備工作,在復雜的設備中,bootloader會進一步分成多個階段;
(3)此時,操作系統就開始接管對MCU的控制,上圖中把操作系統和app分成了兩個部分,是為了對標PC方便大家理解,實際上在有些設備里跑的操作系統和app是混合在一起的,甚至可能沒有操作系統;
(4)最后,各個app被加載運行,開始執行設備的邏輯功能,此處往往是我們想要著重分析的地方。
上圖中,bootloader、kernel和app這三個階段的代碼通常是由開發者編寫并燒錄到Flash中的,我們所說的固件指的就是這部分內容。請將此圖放在腦海中,后續所有工作都將以此圖為模板展開分析和敘述。
PS:本次分享討論的是固件可以提取但是無法分析的情況,一些由于讀保護機制導致固件不被提取的情況,暫不在本篇的討論范疇中。
3、情況簡介
通過熱風槍可以取下Flash芯片,然后通過編程器可以拿到Flash中的固件,這些基本功各位一定已經非常熟悉了,這里就不再贅述。固件文件包含一個FAT12格式的文件系統,可以通過7z工具直接提取出文件系統中的所有內容,提取內容截圖如下:
圖3-1 固件文件系統內容
顯而易見,上圖中的App文件夾中肯定包含了這款門禁考勤機的主程序。不過,事情肯定沒有那么順利,該文件夾內只有一個文件是可以解析的ELF格式,其他文件均不可解析,僅存在可解析文件叫main.bin,用IDA加載之后,內容看起來也有些過于簡單,截圖如下:
圖3-2 main.bin程序內容
上圖中,雖然函數符號都還在,可以大概推斷出函數的作用,但是函數看起來很古怪,比如RT_CreateProcess函數內容是下圖中的樣子:
圖3-3 RT_CreateProcess函數內容
上圖中的gFuncEntryKern看起來有點像虛表指針,指向一個函數地址表,而這個指針在程序啟動時被賦值。
程序main.bin很短,很快就逆完了,看起來最后創建了一個新的進程,但除了main.bin程序之外,其他程序全都無法解析。即便是main.bin自身,看起來也不太正常,很多函數只有跳轉stub,缺少實質內容,看起來像是PC中加了保護導入表的殼。那么,接下來還是從頭開始啃一下這個設備固件吧。
4、kernel分析與解密
按照圖2-1所示,我們決定先看看bootloader,在解壓獲得的完整文件系統中,可以看到Product.ini文件,從里面能夠找到設備的分區表,如下圖所示:
圖4-1固件分區表
我們此前解壓縮得到的FAT12文件系統即為0x20000偏移處,順便吐槽一下binwalk,為啥binwalk識別不出FAT12文件系統,因為太古老了嗎?
結合設備上電后串口的輸出字符串,可以推斷出0x20000之前的固件內容即為程序的bootloader,接下來用IDA載入bootloader部分代碼進行分析,并結合串口的輸出日志,可以定位到關鍵位置,如下圖:
圖4-2 bootloader加載kernel文件的過程
上圖中,我們根據串口打印出來的字符串來定位程序的關鍵位置,找到了kernel文件其實就是rootfs中的Rtbio_3760_R4502文件,且串口打印出來的信息包含了kernel的加載基址和入口地址,根據這些信息,可以分析kernel文件了。
使用IDA加載kernel文件之后,IDA導航條如下圖所示:
圖4-3 直接解析Rtbio文件時的IDA導航條
可以看到此時kernel只被解析出了一小部分,絕大多數內容都是unexplored狀態,實際上這部分內容還是處于加密或壓縮狀態。由于執行流程已經離開bootloader而進入kernel階段,那么kernel代碼肯定是自解密或自解壓的,這很正常,一般情況下linux kernel都是自解壓的,但我們沒辦法直接解壓就很奇怪。通過逆向分析,可以在入口點附近看到多處異或解密代碼,如下圖所示:
圖4-4 異或解密代碼
上圖中,0x79E1即為異或解密使用的密鑰,類似上圖中的異或解密代碼在多個位置都有出現,原來再自解壓之前還有一步自解密過程,所以沒法直接解壓。
耐心分析這些已經解析的代碼,可以將kernel的啟動流程整理為下圖所示內容:
圖4-5 kernel文件的解密過程分析
可以看到,kernel既包含自解密部分,也包含自解壓部分。將我們在PC端脫殼的經驗用到此處,待程序完成自解密和自解壓之后,dump完整的內存,就可以獲得可以逆向閱讀的kernel二進制文件。
然而我們并沒有找到設備調試接口,寫脫機解密腳本又太繁瑣,最終選擇用QEMU加載kernel,運行其自解密和自解壓代碼,待所有工作完畢之后dump內存。最后,用ida加載dump下來的內核文件,就可以看到很多代碼和明文的字符串,如下圖:
圖4-6 載入并分析dump kernel
在眾多字符串中,我們還注意到了一個版權信息,如下圖:
圖4-7 版權信息字符串
上圖中的版權信息表明此固件可能使用了RTEMS系統。該系統一款開源的RTOS系統,在github上就可以找到源碼,代碼參考鏈接:https://github.com/RTEMS/rtems。
與我們此前分析云丁鹿客智能門鎖那篇很類似,當確定了固件使用的操作系統,那么逆向工作就變得相對簡單,畢竟有源碼可以參考。通過對比源碼,我們可以分辨出大量函數,如open、close、read等。查找這些函數的交叉引用,我們發現了一張很大的函數表,如下圖右側所示:
圖4-8 導出函數表
上圖左側中,我們展示了第3章main.bin的幾個函數調用,并與右側kernel中的函數表相互對應。還記得gFuncEntryKern指針嗎?看起來這個指針所指向的函數表就是上圖右側中的函數表。到此,依靠這張函數表,我們就可以正常分析main.bin程序中的所有函數了。
到此,bootloader和kernel部分可以告一段落了,在開始分析APP之前,還有一點需要提一下,與傳統PC操作系統不同的是,該設備并不存在用戶態和內核態,kernel和app處于相同的特權級別,所以兩者之間可以直接相互調用,不需要上下文的切換。
5、app分析與解密
在這個設備固件中,除了kernel需要解密解壓之外,大部分app也是需要解密解壓的。除main.bin之外的程序,我們都無法用IDA直接分析,就是因為這些程序尚未解密解壓,而解密解壓的關鍵就在RT_UnzipFile函數中,將該函數的關鍵位置截圖如下:
圖5-1 RT_UnzipFile函數的代碼片段
上圖中可以看到read、xor、write等幾個關鍵點,進一步分析可以判定RT_UnzipFile函數同樣包含解密和解壓這兩個過程,異或密鑰也沒有變化,同樣是0x79E1。
根據以上結論我們可以寫一個用于解密和解壓每個bin文件的腳本,將這些文件恢復成可以分析的ELF格式。通過腳本,我們將Root_00.bin解密解壓,root_00.bin就是main.bin在執行最后創建的新進程,用IDA載入解密解壓后的ELF文件,截圖如下:
圖5-2 通過IDA載入解密后的Root_00.bin文件
可以看到,Root_00.bin已經可以分析了。至此,我們已經完全理解了這個設備和固件,可以隨意分析其中的文件了。
6、固件程序的編寫
門禁考勤機作為一個企業的門戶,往往承擔了保衛企業的任務,如果門禁考勤機自身變成了打入企業內網的潛伏者,想必是件很搞笑的事情。當我們發現了門禁考勤機的漏洞,想植入后門時,就可以來閱讀一下這第6章的內容。
雖然與開發傳統的Linux程序比較類似,但由于我們沒有與之匹配的SDK,而只能選擇公版ARM編譯器,所以在開發過程中,需要額外注意兩點:
(1)系統調用。通過逆向分析被解密解壓的多個固件程序,我們可以確定程序是沒有導入表的,系統調用是通過gFuncEntryKern和gFuncEntryLibc等幾個指針實現。由于我們沒有官方SDK,這就導致沒辦法像常規正向開發一樣進行各種系統調用,但是按照shellcode開發思路,直接寫匯編肯定是沒問題的,最終結果如下圖所示:
圖6-1 模擬系統調用
上圖中,我們參考IDA的逆向代碼用匯編實現socket、bind等系統調用,具體的邏輯功能代碼還是可以照常用C來編寫。
(2)生成文件格式。通過查看其他已經解密解壓的多個固件程序,我們可以確定ELF文件是relocatable格式,而不是executable格式的,如下圖所示:
圖6-2 查看main.bin文件格式
因此,使用gcc編譯程序時,需要指定-c參數,用于生成僅編譯和匯編的文件;同時,使用ld鏈接程序時,指定-r參數,用于生成relocatable文件。
完成以上工作后,將編譯的程序,按照第三章的分析做好壓縮、加密處理后,并通過某些方式植入設備中,設備上電后即可看到程序開始執行,tcp回連nc監聽的42240端口,如下圖:
圖6-3 反彈socket通信的進程
上圖中,我們以發送hello world字符串來說明問題。
當然,我們也可以修改固件中已有的文件,例如開機界面的圖片,更多內容我們這里不再展示。
圖6-4 修改考勤機開機界面
7、總結
本篇我們著重討論了一款固件加密的門禁考勤機設備,并借鑒PC端app脫殼的技巧,解密解壓了固件中的kernel以及app。其實,本篇分享的固件加密只是各種加密方式的一小類,更常見的情況應該是固件文件完整加密,如果以后有機會我們也會分享那些完整加密的情況,感興趣的可以等我們后續的分享。