Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86395015

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

在本文中,我們將以ANYTONE 878UVII對講機中的固件為例,為大家演示如何對ARM固件映像進行逆向分析。不過,本文中的大部分內容,對於ARM架構來說都是通用的。

本文假設讀者已經熟悉IDA Pro,並且至少分析過一些普通的二進製文件。如果您還不熟悉IDA,只需在網上搜索一下,就能找到許多非常優秀的入門教程,大家可以先通過它們來掌握相關的基礎知識。

固件映像就本文來說,我們只需IDA Pro和ANYTONE 878UVII對講機的固件映像就能搞定我們的實驗。並且,所需的映像還可以從分銷商網站下載。實際上,下載哪個版本並不重要,但本文是將以2.04版本為例進行介紹。

1.png

在下載的更新包中,我們可以找到FW文件夾,其中包含三個文件:CDI、SPI和CDD文件。其中,CDD是最大的文件,它實際上就是我們要分析的固件映像。

這次我們的運氣不錯,因為這個固件映像並沒有加密,否則,事情就會麻煩一些。它只是內部閃存中的映像,甚至連文件頭都沒有。並且,該文件的元數據被拆分為單獨的文件。所以,我們可以直接在IDA Pro中加載CDD文件。

技術背景ANYTONE 878系列對講機使用的是GigaDevice GD32 ARM Cortex-M4微控制器:通過拆開對講機,我們就能看到這些芯片的型號。

除了拆對講機外,實際上還有另一種更方便的方法:查詢FCC。如果您的設備符合FCC的要求,網上應該有關於它的公開信息。這時,我們可以直接在FCC或獨立的數據庫中搜索製造商的信息。大多數情況下,我們會找到一份帶有“內部照片”的文件。這個文件通常能夠提供我們感興趣的信息,比如芯片型號等,這樣,我們就不用拆機了。

1.png

重要的是,我們建議大家下載CPU的數據表,並保存起來供後面使用:後面步驟中需要設置的參數,都可以從中找到。

關於CPU的相關設置首先要做的是,把CDD拖到打開的IDA Pro窗口中,或者通過文件菜單打開它。 IDA會檢測出這是一個二進製文件。然後,將“Processor type”指定為“ARM little-endian”,具體如下圖所示。

1.png

現在,先別按“Ok”按鈕,因為還要對處理器選項進行一些設置。我們知道,這種設備使用的處理器是基於ARMv7E-M架構的。因此,我們必須對處理器選項做相應的修改。最佳設置如下圖所示;為此,需要按下“Processor options”菜單中的“Edit ARM architecture Options”按鈕,這樣就可以找到中間的窗格了。

1.png

由於這個項目與Thumb指令集高度相關,所以也建議在“ARM specific options”中勾選“No automatic ARM THUMB switching”選項。雖然這一點並沒有顯示在上面的截圖中,但對本項目來說的確是一個非常有用的設置。

加載映像現在,我們已經完成了基本的CPU設置。接下來,我們需要將加載的固件映像重新定位到正確的偏移量處。這個固件映像將被加載到IDA數據庫的ROM部分。由於CPU不會從文件中的0x00處開始加載映像,所以,我們必須重新定位。如果跳過這一步,交叉引用將被破壞,反彙編文件將無法正常工作。我們的目標設備中使用的ARM CPU將要求映像從偏移量0x8004000處開始。這裡其實就是映射到物理ROM的內存位置,所以,我們需要將文件映射到這個地址。

在單擊“Load new file”對話框中的Ok按鈕之後,將會出現如下所示的對話框。通常情況下,RAM的大小和ROM的大小並不需要調整。它們現在已經正確地自動填充好了。

1.png

接下來要做的事情,就是創建一個RAM分區。為此,可以勾選“Create RAM section”,分配的RAM將從0x20000000位置開始,長度為0x17FFF。

如何找到正確的內存偏移量如果讀者是第一次接觸這方面的內容,通常會有這樣的疑問:這些值是如何確定的?答案很簡單,我們可以從之前下載的數據手冊中找到它們。

從第17頁的內存映射部分,我們可以找到主閃存(固件文件)的加載地址。而在第16頁中,我們可以找到SRAM偏移量和這段內存的長度。

1.png

很簡單吧?上面所做的只是將文件/映像重新定位到從我們的數據表中獲取的正確位置。關於主閃存有一個小技巧,第一個0x4000似乎是由引導程序獲取的,所以,我們的二進製文件必須位於0x8004000處。

二進製文件的結構對於第一次使用IDA的讀者來說,感覺可能非常奇怪:它並沒有像其他軟件一樣進行自動分析,也沒有展示程序代碼,相反,它只是給出了大量的十六進製字符。難道是我們哪裡做錯了嗎?很可能不是。如果您正在使用IDA Pro分析固件映像,這是非常正常的現象。這裡的難點在於,我們必須自己從頭開始進行分析。

1.png

但這也沒有想像的那麼難。首先,讓我們考察文件的開頭位置。這是ARM CPU開始執行代碼的地方。在這個偏移量處,一個被稱為向量表的結構被定位,它在ARM Cortex通用用戶指南中有很好的詳細描述。

1.png

正如我們在用戶指南的圖形中所看到的,偏移量0x0000(0x08004000)處包含初始堆棧指針。 CPU將在這個地址加載接下來的四個字節,並將其用作指向未來堆棧的指針。

復位處理程序接下來的字節是各種處理程序,最重要的是複位處理程序(reset handler)。它正是CPU要啟動或重新啟動時將會跳轉到的地方。

1.png

它又是一個4字節的地址,對於我們的映像來說,這個地址很容易解析。正如鍊接的ARM用戶指南文章所告訴我們的,如果地址的最低有效位為1,則處理程序為Thumb。

在我們的例子中,該地址的最後一個字節是0xF9,二進制形式為11111001B。我們可以看到,這裡的最低有效位確實是1。因此,我們需要將復位處理程序的入口點改為Thumb。實際上,復位處理程序的實際偏移量也由於該位的值而移動了一個字節。

0xF9=11111001b (with Thumb indicator)

0xF8=11111000b (without)

單擊這個偏移量,就會跳轉到復位處理程序的地址減1個字節的地方。現在,請按“Alt+G”,這時會打開一個對話框,我們需要將下面的部分定義為Thumb(CODE16)。

1.png

這個項目主要涉及Thumb指令集,因此,您也可以從ROM段的第一個字節開始使用Thumb代碼。請記住,這一點並非適用於所有的ARM項目。但對於這個項目來說,這是沒問題的。

將當前偏移量改為CODE16後,只需按“C”,就能在該偏移量處創建代碼了。現在,我們就應該可以看到復位處理程序的代碼了。

1.png

查找其他代碼和字符串上面介紹的方法雖然能用,但是通過手動方式來創建所有的代碼是相對繁瑣的。別擔心,我們可以藉助於腳本來完成這些任務。實際上,Maddie Stone已經為IDA Pro創建了許多非常方便的腳本,能夠給我們帶來極大的便利。

由於她的腳本不能用於較新的IDA版本(在寫這篇文章時,最新的版本為7.7),所以,我們專門把適用於IDA 7.x版本的腳本上傳到了Github上,讀者可以從https://github.com/alexander-pick/IDAPythonEmbeddedToolkit下載。為了支持基於ARM的項目,我已經對這些代碼做了相應的處理。

首先,我們可以使用腳本define_code_functions.py,在0x08004000到0x080963DC大致範圍內創建代碼。如果腳本詢問是否要撤銷現有的代碼,請選擇No。

IDA Pro應該可以正常工作了,此時的ROM部分應該開始變得更有趣了。

1.png

接下來,我們可以使用make_strings.py腳本,在ROM的其餘部分創建字符串。這時,你會在其中發現許多我們感興趣的字符串。

關於字符串引用分析這個固件時,我們會發現一個奇怪的現象。由於ANYTONE的開發人員為多國語言創建了固件,所以,他們使用了引用表。因此,這可能導致我們會遺漏某些字符串的引用。之所以會發生這種情況,是因為這些字符串是根據選擇的語言來動態加載的。遺憾的是,基於IDA的靜態分析是無法解決這個問題的。

不過,引導過程中的一些字符串是直接嵌入的,所以它們解析起來問題不大。因此,我們可以從這些字符串開始下手。

1.png

為了做進一步的分析,我們需要能夠識別一些基本的OS函數,即操作嵌入字符串的函數,比如“print”或“read”函數等。當然,類似“memcpy”這樣的函數在各種操作系統中都是非常常見的。

非常值得注意的是“print_string”函數(一旦識別出來,我就把它重命名為這個名字)。它接受一些坐標和一個字符串作為參數,並將字符串顯示在屏幕上給定的位置處。這個函數在啟動菜單中被大量使用。

從固件鏡像中的字符串可以識別出設備使用的RTOS(實時操作系統)是μC/OS-II。 μC/OS-II是一個用ANSI C編寫的免費實時操作系統。關於該系統的進一步介紹,以及相關文檔,讀者可以在這裡找到;而相關代碼則可以從這裡下載。感興趣的讀者可以參考這些資料,它們應該對您有很大的幫助。

I/O和外圍設備像這樣基於ARM的CPU通常使用特殊的內存區域來處理地址總線、GPIO、I/O或簡單的定時器和時鐘,具體請參閱數據表。實際上,在第14頁中,大家可以找到我們用來指定加載偏移量的內存映射。該映射還包含要添加到數據庫中的特殊內存區域。

打開IDA中的內存區域視圖(segments view)並將它們添加到數據庫中,結果應該與下圖類似。如果你想偷懶,則可以使用這個IDC(https://github.com/alexander-pick/useful-script-and-code/blob/master/GD32F303xx_segments.idc)來完成這個過程。

1.png

現在,請重新運行自動分析(Options - General - Reanalyse program)以創建交叉引用。

一旦你完成了上面的步驟,就可以查看感興趣的內存區域,看看是否有對它們的交叉引用。這些可以幫助您找到使用特定總線、GPIO或I/O的函數。

如果您查找操作UART的函數,只需檢查UART區域,就會找到對它的引用。這在沒有或只有很少字符串作為引用的情況下是特別有用的。

小結我認為,到目前為止,您應該已經具備了自己研究這一主題所需的一切。請隨時給我留言。如果您還有什麼問題,儘管問。我總是很高興看到人們分享有趣的發現。

閱讀愉快!