幾年前我就開始做BIOS rootkits方面的東西(在UEFI成為主流之前)。我知道在初始化啟動過程的后期階段,大多數硬件都有一個BIOS類型設置 ,我的主要關注GPU和硬盤。本文我所做的是我曾經 在 spritesmods 上看到的一些東西。
硬盤破解
我發現一個老版本的西部數碼硬盤驅動器很適合現在的研究,所以我把控制器卸下來。
Spritesmods上的那個家伙把固件的閃存芯片弄下來然后把里面的內容全部拷貝出來了,這里唯一的問題是紅圈中閃存芯片這個地方。
紅圈中是Marvell 88i8846-TFJ2 ARM處理器,有內部的閃存。我不想為了訪問內存而手工把整個CPU弄下來,所以我決定使用JTAG方法。
JTAG的頭是很知名的,雖然可以被顛倒(在我的案例中頭部的第一個pin點用’1’標識)。Pins 6到11是我們需要的JTAG金屬圈。
正如你可以看到的,我們決定不焊接pins點。主要原因是其有點生銹並且離得太近,所以很容易把單板弄壞掉。作為替代我決定使用測試點,這可以用萬用表的“連續”模式實現。
通過設置萬用表的這個模式能夠得到兩點之間的電阻,‘1’代表完全絕緣(這意味着這兩點是不通電的),‘0.01’代表互通性很好。當電阻很低的時候,儀表會發出聲音(難以忍受的噪音),所以我們只需要通過聲音來判斷兩點之間是否連接即可。
將硬盤驅動器斷開,只要把你要測的兩點用萬用表測一下即可。然后移動其中一段到其他點上,直到聽到蜂鳴聲為止。在我的單板上你會發現從頭部的pin點到測試點有可見的數據行,這給了你很好的入口(前提是你的視力很好)。
我不想將硬盤插入到我的電腦電源上以免出現一些錯誤,並且我的電腦在房間的對面,所以我也不想搞個10米長的SATA數據線。下面是我的解決方案:
如果你有備用電源,在沒有連接到主板的情況下,你可以將ATX的第三個和第四個pin點短路來將它開啟。我的備用電源很老並且少一個風扇,所以我很驚訝居然沒有短路和起火(我的房子的所有設備都在一個斷路器上,所以短路的話我得花一個小時重啟所有設備)。
我使用5美元的SATA來連接USB,這是一個很好的方法。右邊的紅色單板使用了一個30美元的TIAO USB多協議適配器,基於FT2232H同時以可以用SPI和JTAG。
在這里我有一個愚蠢復雜的設置,由於我的windows機器放在房間的另一邊,iMac為JTAG軟件運行了一個linux虛擬機(FTDI驅動和OpenOCD)因為這在windows和OSX上安裝很麻煩。 Windows系統運行IDA來逆向和調試(當我開始動態調試時我打算在本地網絡上用IDA連到OpenOCD的GDB服務器上去)。
現在所有要連接的東西都已經准備好了,給硬盤插上電源然后輸入下面的命令:
openocd -f interface/<your interface here>.cfg -f target/test.cfg
需要先為你的硬盤控制CPU配置test.cfg文件,對於大部分marvell的CPU這個配置都有效。我不知道khz適配器行不行,所以我將mine設置成100(由於這個值低於它正常的工作值)。
如果一切正常,你會看到這些信息。現在你可以telnet到4444端口然后發送命令了。
硬盤控制器用的Marvell芯片沒有公開的文檔,所以如果你想了解相關信息比如內存布局,你需要在NDA上注冊然后付費。作為替代,我想要做的是盡可能在固件上和通過探測電路找到更多的信息。
如果你們沒有辦法焊下閃存並導出信息要得到固件並不容易,所以我們將會在boot進程下工作。 大部分ARM CPU的起始執行地址是0xFFFF0000,這是復位向量。如果我們從這個地址導出65536字節,我們將會找到啟動代碼,這是一個很好的入口點。
為了導出內存,我們首先要停止CPU,可以使用命令”reset halt”(這是必要的因為我們沒有辦法在任何一個階段都能停下來)。如果這個命令沒有效果可能是JTAG的RST pin點沒有連接,你需要斷開並重連硬盤的電源然后快速的修復這個JTAG問題。內存導出用以下命令
“dump_image <file name> <address> <size>”
當我們將導出的鏡像文件反匯編時,它是一個很小的只有4KB的啟動代碼,這段代碼能夠引導剩下的固件。
我發現JTAG的重置點不是真的系統重置(SRST)只是一個TAP重置(TRST),這對調試不是很有用。這里是對系統重置信號的添加(這樣允許重置停止命令在重置向量上中斷下來,在任何指令執行之前)。
在我的例子中沒有SRST行的測試點,但是在序列標簽下面有暴露出非常小的鍍銅位,這個可以用來連接CPU的SRST pin點。
紅迪網上的Ceriand指出JTAG頭跟MICTOR連接器很像(通常是38或40個pin點)。所以如果你不想做任何焊接工作你可以找一個MICTOR連接器和數據線。
同時我發現老版本的PSU硬件無法在低電壓下使用(內部的組件可能會爆炸),所以我推薦為Molex電源適配器買一個好的AC(不要買便宜的,一天就壞掉了)。
最后,由於JTAG頭有一個RTCK連接器,你需要將opencd的adapter_khz配置為0. 這樣JTAG能夠使用自適應時鍾,這樣你能夠防止所有超時錯誤。
引導和引導程序
通過一些逆向我確定第二部分的引導代碼無法在正常的啟動中使用。執行的時候在一個端口上等待一些數據(最有可能是串行端口),然后采取相關的行動。如果沒有數據到來,這段代碼將進入一個死循環驅動將永遠不會啟動。
PCB周圍的端口和測試點映射到CPU的0x1C00A000-0x1C00AFFF范圍上。現在,由於我沒有錢買示波器或者像樣的邏輯分析儀。我不得不通過這些端口映射,這樣會使事情變得更容易。
所有的這些代碼都是為了基於一些值讀取進入系統特殊模式的開關:
4-不確定,當它為了一些端口的值進行無限循環。我猜這些值是允許開發者讀取/寫入/ 擦除處理器內部的閃存。
3-跳轉到R4的地址(我的例子中這個值為0,但可能是設計的原因)
6-串行端口的串行控制台可以用ASCII字節(r,w,j,h),可以讓開發者發送讀取, 寫入,跳轉和停止命令。
我對端口如何映射到內存不太熟悉,0x1C00A030總是為0,0x1C00A03A總是為0xFFFF(我認為這一個是低電壓常數一個是高電壓常數)。
有趣的是在“cmp R1,#R3”上設置斷點將R3設置成3,代碼會跳到地址0然后正常啟動(這就是我認為為什么0不代表未初始化)。讓我們看看地址0有什么。
地址0通常是RAM,但已經有一些有效的代碼了,所以很可能是在啟動過程中CPU臨時映射地址0到一些內部只讀存儲器。這是標准的ARM IVT,你可以在任何ARM設備的啟動地址看到;使我想到CPU檢測到JTAG附加進來時0xFFFF0000上的啟動只是被執行了。在我買到邏輯分析儀並找到哪個端口允許我控制啟動模式跳轉之前,唯一通過JTAG正常啟動硬件的辦法是在校驗之前執行“重置”然后將R1設置成3.
在這個例子中啟動代碼是節與節之間差距最大的地方,后續有機會我會將它進行映射,導出,並逆向。
*參考來源:malwaretech.com