我想從逆向的角度做了深入了解JTAG,JTAG是許多嵌入式CPU使用的硬件級別調試機制,我希望通過這篇文章從逆向工程師的角度解釋如何使用JTAG,并在此過程中提供一些實際示例。
通過這篇文章,我希望做到以下幾點:
1. 解釋JTAG的工作原理;
2. 演示如何發現和利用未知目標上的JTAG端口/接口;
3. 提供一些當前可用于與JTAG接口交互的OSS工具的概述;
4. 利用JTAG提取固件并調試目標。
另外,在概述之前,我列出一些學習JTAG的資源
·?Cyphunk’s Embedded Analysis Page
·?FPGA4Fun JTAG Overview
·?Blackbox JTAG Reverse Engineering
JTAG是一種硬件接口,旨在幫助開發人員和測試人員進行調試。JTAG最初是為了測試集成電路而開發的,更具體地說,是對被測目標上的IO引腳進行采樣。這種類型的調試接口使工程師可以在不需要物理引腳本身的情況下測試PCB上的連接。JTAG接口通過以下概述的狀態機進行控制:
關于此級別的JTAG,要記住的重要事情之一是它涉及兩個寄存器,即指令寄存器和數據寄存器。要使用這些寄存器,必須使用以下接口信號輸入上述狀態機中的正確狀態:
使用TMS和TCK線瀏覽狀態機,同時分別通過TDI和TDO寫入或讀取數據。在TCK的上升沿對TMS進行采樣,這意味著必須先聲明TMS線,然后才能將TCK切換為在狀態機中導航。然后根據JTAG狀態機的狀態將數據移入指令寄存器(IR)或數據寄存器(DR)。當完成一個操作(或更新DR / IR相后)所得到的數據可以被移位通過輸入DR的Shift-DR狀態。有了這些原語,制造商可以實現他們希望通過JTAG實現的任何功能。
JTAG標準將IR和DR視為移位寄存器,因此,可以將多個目標鏈在一起。
簡而言之,JTAG定義了一個狀態機,該狀態機至少使用4個信號進行導航。有了此狀態機,最終用戶可以從兩個移位寄存器IR和DR進行寫入和讀取。
JTAG寄存器
JTAG利用兩個主要寄存器,指令寄存器和數據寄存器。指令寄存器用于確定JTAG控制器將要執行的功能,例如存儲器讀取或存儲器寫入。數據寄存器然后用作指令寄存器的附加輸入,對于前面的示例,它們可以用于提供要讀取或寫入的地址。這些寄存器的大小可以根據其功能而有所不同。
要寫入寄存器,將執行以下步驟,我們以IR為例:
1. 輸入Test Logic Reset狀態(TLR)(可以通過斷言TMS線路并循環CLK5次來完成此操作);
2. 進入Select IR Scan狀態;
3. 進入Capture IR狀態;
4. Enter Shift IR–這是我們將數據從TDI加載到IR的地方;
5. 進入Exit IR狀態;
6. 進入Update IR狀態–此階段將值“鎖存”到IR中。
此后,如果不需要數據寄存器,則將執行該操作,并將結果(如果有)加載到數據寄存器中以移出。但是,許多指令也需要在操作之前填寫數據寄存器。在這種情況下,一旦數據寄存器被寫入并更新,就將執行該操作,并且結果可以移出數據寄存器。
某些指令不需要加載DR,例如,如果我們已將IDCODE指令加載到IR(1110b)中,則會將處理器的IDCODE值加載到數據寄存器中,以便我們計時并繼續讀取TDO。要從中讀取結果TDO,將導航到該Shift-DR狀態,并在上輸入32位TDI,這將導致數據寄存器中的數據TDO在線上移出。請參見下圖,直觀地了解如果向IR加載IDCODE指令后會發生什么情況。
重要的是要記住,IR并且DR可以將其視為移位寄存器,這意味著當我們使用新值更新它們時,舊值隨后會移出TDO。
JTAG標準定義了以下指令寄存器:
·??BYPASS
·?該指令連接TDI并TDO
·?在此Shift DR狀態下,數據從傳輸TDI到TDO的延遲為一個TCK周期
·?Capture DR狀態期間將0裝入數據寄存器
·?這可用于確定掃描鏈中有多少個設備
·??IDCODE
·?加載時,將設備代碼ID寄存器選擇為TDI和TDO之間的串行路徑
·?在Capture-DR狀態下,將32位設備ID代碼加載到此移位部分中
·?在Shift-DR狀態下,此數據被移出,最低有效位在前
·?核心JTAG概念:
·?該狀態機被導航用4個信號:TCK,TMS,TDO和TDI
·?TDI用于提供輸入,TDO用于輸出
·?使用此狀態機,可以將數據移到IR(Shift IR)和DR(Shift DR)中
·?可以將指令寄存器(IR)視為函數,而將數據寄存器(DR)視為該函數的參數
·?隨著數據移入DR和IR,先前的內容移出TDO
·?一旦將數據移入這些寄存器,就可以執行操作(除少數保留指令外,完全取決于主機實現)
·?數據被讀出通過將其移動到目標的出TDO從數據在寄存器Shift DR狀態。
因此,既然我們已經研究了JTAG的底層工作原理,那么我們應該討論為什么我們會關心它,以及該接口如何為逆向工程師授予對有用功能的訪問權限。JTAG接口最常用的應用程序之一是硬件級調試(因此,本文的標題)。這是由芯片制造商實現的,并且可能因芯片而異,但是,針對ARM目標的硬件級調試的最常見實現之一是ARM的CoreSight調試接口。這與我在上一篇文章中通過SWD進行通信的實現相同,只是在這種情況下,調試訪問端口是通過JTAG進行通信的。JTAG實現的細節可以在這里找到。對我們來說幸運的是,可以使用一些出色的OSS工具與這些端口進行通信-這篇文章將重點介紹使用OpenOCD。
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0314h/DDI0314H_coresight_components_trm.pdf?
https://wrongbaud.github.io/stm-xbox-jtag/?
https://static.docs.arm.com/ihi0031/c/IHI0031C_debug_interface_as.pdf
OpenOCD負責利用JTAG或SWD接口向最終用戶授予通過CoreSight DAP公開的調試接口提供的各種原語。Coresight / DAP體系結構相當復雜,在本篇文章(已經很長時間)中無法涵蓋,因此我有可能將其保存在另一篇文章中。
從逆向工程師的角度進行此類操作時,對協議基礎知識有扎實的了解非常重要。當進行逆向硬件(或軟件)時,由于總是存在無限的未知數,因此你希望掩蓋自己的基本事實。接下來的幾節將討論如何利用我們對這些協議的低級知識來幫助我們走上通過JTAG進行硬件級調試的途徑。我們需要做的第一件事是確定引腳排列,以及是否暴露的引腳允許訪問JTAG接口。
確定引腳排列
JTAG信號線通常組合在一起,有時(如果非常幸運的話),你將看到以下標頭之一:
但是,如果你發現類似的內容,則可能沒有確切的信號分組,因此,我們將討論如果假設某個引腳用于JTAG,則如何確定引腳。在進行類似這樣的逆向工程時,你想從已知的知識開始。因為我們知道大多數制造商至少會進行IDCODE,所以BYPASS我們看看如何利用這兩個說明。
如果你確定自己認為是潛在的JTAG標頭或引腳,但不知道引腳,則可以使用這兩個寄存器的行為來確定引腳。
由于該IDCODE寄存器通常作為默認IR加載,因此可以通過執行以下操作來測試假定的引腳排列:
1. 將角色分配給潛在的輸出引腳(TMS,TCK等);
2. 輸入Test Logic Reset狀態;
3. 輸入Select DR Scan,Capture DR,Shift DR;
4. 時鐘32點的值TDI,并監測TDO一個有效的IDCODE值;
5. IDCODE如果看起來有效,請檢查移出的值!否則,請重新分配引腳并重復!
除了利用IDCODE默認情況下經常將寄存器加載到IR中這一事實外,我們還可以利用IR和DR都充當移位寄存器這一事實,因此,如果我們假設一個通用的寄存器長度(32位通常有效),我們可以嘗試執行以下操作以強行設置插腳:
1. 將角色分配給潛在的輸出引腳(TMS,TCK等);
2. 使用這些假定值輸入Test Logic Reset狀態;
3. 輸入Shift IR狀態;
4. 移入一個唯一的32位值 TDI;
5. TDI在監視你在TDO上的唯一模式時,繼續將1切換為開(請確保至少進行32次操作!)。
6. 如果發現了模式,那就恭喜!否則,為引腳選擇新的分配并重復!
這兩種方法是通過前面提到的使用JTAGEnum腳本,還有JTAGULATOR。
確定指令長度
一旦確定了目標的引腳排列,即可開始真正的分析。下一步是確定IR / DR的長度。為此,從IR開始,進入Shift IR狀態,并TDI使用1024或4096之類的大數字以1的on填充鏈,然后以0 TDI計數。一旦完成,只需繼續以1的on 計數,計數即可在出現0之前花費的時鐘周期數TDO。這將告訴你IR的長度。有了該名稱后,就可以輸入Shift DR狀態并重復此過程以確定DR的狀態。
http://urjtag.org/
本文的目標將是我最近從一臺較舊的筆記本電腦中恢復的三星M.2 SSD,在查看了PCB并找出可能是JTAG接頭的地方之后,我想從頭到尾概述一下該過程。
實際示例:查找JTAG標頭/確定引腳排列
如前所述,JTAG線路經常被分組-因此,從硬件角度看一個新平臺時,尋找大于5的引腳分組總是一個好的開始。幸運的是,在這個目標上,PCB外側有9個過孔。讓我們開始檢查驅動器在正常操作狀態下這些引腳的電壓電平。
從最初開始-這些電壓值不會告訴我們任何信息,那么我們可以根據已有的信息確定什么?首先,我們有一個GND,通過在萬用表上使用連續性模式并針對USB連接器的屏蔽層(當然要拔掉目標!)進行測試,很容易確定GND。接下來,我們有一條1.8V的線,通常會期望它是TMS,因為在大多數文檔中建議將其保持在高電平。
為了確定引腳排列,我們將使用Raspberry Pi和JTAGEnum項目。該腳本使用上述方法來嘗試識別JTAG引腳。同樣重要的是,這里的邏輯電平為1.8V,因此,如果要與該目標接口,我們將需要使用邏輯電平轉換器。JTAGEnum.sh使用Raspberry Pi的GPIO線來激活目標接口,在shell腳本中,它們包含GPIO值的映射,如下所示:
?# define BCM pins (mapped directly to /sys/class/gpio/gpio${pin[N]})
?# 5v 5v? g 14 15 18? g 23 24? g 25? 8? 7? 1? g 12? g 16 20 21
?# 3v? 2? 3? 4? g 17 27 22 3v 10? 9 11? g? 0? 5? 6 13 19 26? g
使用上表,我們將以下GPIO連接到未知頭:
JTAGenum.sh我們將pins變量修改如下:
pins=(9 11 25 2 3 10)?
pinnames=(pin1 pin2 pin3 pin4 pin5 pin6)
現在將引腳連接好,并且邏輯電平轉換器就位,我們可以運行了JTAGenum.sh。
運行如下所示連接的腳本會產生大量結果,可以在此處看到輸出。對我們來說幸運的是,它正確地標識了兩種可能的配置,如下所示:
?FOUND!? ntrst:pin4 (RPi GPIO 2) tck:pin6 (RPi GPIO 10) tms:pin1 (RPi GPIO 9) tdo:pin3 (RPi GPIO 25) tdi:pin2 (RPi GPIO 11) IR length: 4
?FOUND!? ntrst:pin5 (RPi GPIO 3) tck:pin6 (RPi GPIO 10) tms:pin1 (RPi GPIO 9) tdo:pin3 (RPi GPIO 25) tdi:pin2 (RPi GPIO 11) IR length: 4
接下來,腳本運行ID掃描。你可能會注意到為此生成了很多結果,我們如何過濾這些結果?你可以執行一些操作來篩選結果,例如,掃描鏈上可能只有1-2個設備(CPU和閃存),因此我們可以立即忽略那些具有2-3個以上條目的設備。接下來,你可以排除序列長(大于4-5)為1或0的序列。幸運的是,在此列表中,有一個我之前見過的ID:0x4ba00477 -該ID用于ARM Cortex內核,在嘗試訪問Beaglebone Black時,我已經見過它。
?ntrst:pin4 tck:pin6 tms:pin1 tdo:pin3 tdi:pin2? devices: 1
?0x4ba00477
?ntrst:pin4 tck:pin6 tms:pin1 tdo:pin3 tdi:pin5? devices: 1
?0x4ba00477
?ntrst:pin5 tck:pin6 tms:pin1 tdo:pin3 tdi:pin2? devices: 1
?0x4ba00477
?ntrst:pin5 tck:pin6 tms:pin1 tdo:pin3 tdi:pin4? devices: 1
?0x4ba00477
你會注意到,在進行IDCODE掃描時,for的值會TDI有所不同,這是因為此方法完全不依賴,TDI因此只是一種猜測。
幸運的是,其中一些結果與模式掃描非常吻合,因此我們現在可以假設我們知道JTAG接口的引腳排列!
實際示例:使用UrJtag確定指令長度
盡管OpenOCD非常適合與DAP控制器接口和連接到調試內核,但是UrJTAG項目非常適合與底層JTAG接口。我們可以使用它們通過有用的discover命令來檢測各種DR長度。此方法使用前面提到的相同原理來選擇,IR然后將大量的1移入DR,然后移入0,然后對多個1進行計時,直到在TDO上讀取0!
UrJTAG可以使用位于~/.jtag/rc我的rc文件如下
?pi@raspberrypi:~ $ cat .jtag/rc?
?cable gpio tck=10 tms=9 tdi=11 tdo=25
?detect
?discover
下面我們可以看到使用這些命令運行UrJTAG的結果:
?pi@raspberrypi:~ $ sudo -E jtag?
?UrJTAG 2019.12 #
?Copyright (C) 2002, 2003 ETC s.r.o.
?Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors
?UrJTAG is free software, covered by the GNU General Public License, and you are
?welcome to change it and/or distribute copies of it under certain conditions.
?There is no warranty for UrJTAG.
?warning: UrJTAG may damage your hardware!
?Type "quit" to exit, "help" for help.
?Initializing GPIO JTAG Chain
?IR length: 4
?Chain length: 1
?Device Id: 01001011101000000000010001110111 (0x4BA00477)
? ?Unknown manufacturer! (01000111011) (/usr/local/share/urjtag/MANUFACTURERS)
?Detecting IR length ... 4
?Detecting DR length for IR 1111 ... 1
?Detecting DR length for IR 0000 ... 1
?Detecting DR length for IR 0001 ... 1
?Detecting DR length for IR 0010 ... 1
?Detecting DR length for IR 0011 ... 1
?Detecting DR length for IR 0100 ... 1
?Detecting DR length for IR 0101 ... 1
?Detecting DR length for IR 0110 ... 1
?Detecting DR length for IR 0111 ... 1
?Detecting DR length for IR 1000 ... 35
?Detecting DR length for IR 1001 ... 1
?Detecting DR length for IR 1010 ... 35
?Detecting DR length for IR 1011 ... 35
?Detecting DR length for IR 1100 ... 1
?Detecting DR length for IR 1101 ... 1
?Detecting DR length for IR 1110 ... 32
我想在這篇文章中重點介紹UrJTAG,因為在查看具有完全未知的掃描鏈或DAP架構的目標時,它非常有用。對我們來說幸運的是IDCODE,此目標的告訴我們它是ARM架構,我們很可能將能夠使用CoreSight DAP,為此,我們將使用OpenOCD。如果你正在尋找一無所知的掃描鏈,那么我通常從UrJtag開始,只是要獲取所有寄存器的映射。UrJTAG的python綁定也可以很好地工作,并且可以用于與JTAG進行低級接口。
由于我們知道目標上JTAG接口的引腳排列,因此我們現在可以繼續使用OpenOCD與之通信。我之所以選擇OpenOCD是因為它具有對ARM MCU的出色調試支持,尤其是使用CoreSight的Cortex系列。我們需要做的第一件事是選擇一個硬件適配器,我們將使用FT2232H中斷模塊。
通過FT2232H進行JTAG調試
了解了引腳排列后,我們現在可以嘗試使用OpenOCD與DAP進行通信。為此,我們將使用FT2232H適配器,在本文中,我將使用標準的FT2232H分支板。這些板可用于與多個硬件級別的接口交互,并具有出色的軟件支持。你可能還記得我曾經將它們用于SWD以及轉儲SPI閃存。使用該板,以及3.3V至1.8V邏輯電平轉換器,我們可以將其連接到目標,如下所示:
接下來,我們將從關于目標的已知變量開始編寫配置文件。
?source [find target/swj-dp.tcl]
?# This is using the name on the SoC
?if { [info exists CHIPNAME] } {
? ?set _CHIPNAME $CHIPNAME
?} else {
? ?set _CHIPNAME s4ln045x01
?}
?# This is the TAP ID that we discovered in the previous step
?if { [info exists CPUTAPID] } {
? ?set _CPUTAPID $CPUTAPID
?} else {
? ?set _CPUTAPID 0x4ba00477
?}
?# Set the speed of our adapter
?adapter_khz 200
?# We are indeed using JTAG
?transport select jtag
?# We don't have a SRST pin, only TRST it would seem
?reset_config trst_only
?# Here we create the JTAG TAP/DAP, defining the location and characteristics of our DAP
?swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
?dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
?set _TARGETNAME $_CHIPNAME.cpu
當我們使用此配置文件運行openocd時,結果如下:
?wrongbaud@wubuntu:~/blog/samsung-jtag$ sudo openocd -f minimodule.cfg -f config.cfg?
?Open On-Chip Debugger 0.10.0+dev-01040-ge7e681ac (2020-01-27-18:55)
?Licensed under GNU GPL v2
?For bug reports, read
? ? ? ? ?http://openocd.org/doc/doxygen/bugs.html
?Info : auto-selecting first available session transport "jtag". To override use 'transport select '.
?Warn : Transport "jtag" was already selected
?Info : clock speed 200 kHz
?Info : JTAG tap: s4ln045x01.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
?Info : Listening on port 6666 for tcl connections
?Info : Listening on port 4444 for telnet connections
?Info : JTAG tap: s4ln045x01.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
?Warn : gdb services need one or more targets defined
現在讓我們看一下DAP,看看那里是否還有其他相關信息:
?> dap info 0
?DAP transaction stalled (WAIT) - slowing down
?DAP transaction stalled (WAIT) - slowing down
?AP ID register 0x24770002
? ? ? ? ?Type is MEM-AP APB
?MEM-AP BASE 0x80000000
? ? ? ? ?ROM table in legacy format
? ? ? ? ? ? ? ? ?Component base address 0x80000000
? ? ? ? ? ? ? ? ?Peripheral ID 0x0000080000
? ? ? ? ? ? ? ? ?Designer is 0x080,? ? ? ? ? ? ? ? ? Part is 0x0, Unrecognized
? ? ? ? ? ? ? ? ?Component class is 0x1, ROM table
? ? ? ? ? ? ? ? ?MEMTYPE system memory not present: dedicated debug bus
? ? ? ? ?ROMTABLE[0x0] = 0x1003
? ? ? ? ? ? ? ? ?Component base address 0x80001000
? ? ? ? ? ? ? ? ?Peripheral ID 0x04008bbc14
? ? ? ? ? ? ? ? ?Designer is 0x4bb, ARM Ltd.
? ? ? ? ? ? ? ? ?Part is 0xc14, Cortex-R4 Debug (Debug Unit)
? ? ? ? ? ? ? ? ?Component class is 0x9, CoreSight component
? ? ? ? ? ? ? ? ?Type is 0x15, Debug Logic, Processor
? ? ? ? ?ROMTABLE[0x4] = 0x2003
? ? ? ? ? ? ? ? ?Component base address 0x80002000
? ? ? ? ? ? ? ? ?Peripheral ID 0x04008bbc14
? ? ? ? ? ? ? ? ?Designer is 0x4bb, ARM Ltd.
? ? ? ? ? ? ? ? ?Part is 0xc14, Cortex-R4 Debug (Debug Unit)
? ? ? ? ? ? ? ? ?Component class is 0x9, CoreSight component
? ? ? ? ? ? ? ? ?Type is 0x15, Debug Logic, Processor
? ? ? ? ?ROMTABLE[0x8] = 0x3003
? ? ? ? ? ? ? ? ?Component base address 0x80003000
? ? ? ? ? ? ? ? ?Peripheral ID 0x04008bbc14
? ? ? ? ? ? ? ? ?Designer is 0x4bb, ARM Ltd.
? ? ? ? ? ? ? ? ?Part is 0xc14, Cortex-R4 Debug (Debug Unit)
? ? ? ? ? ? ? ? ?Component class is 0x9, CoreSight component
? ? ? ? ? ? ? ? ?Type is 0x15, Debug Logic, Processor
? ? ? ? ?ROMTABLE[0xc] = 0x4003
? ? ? ? ? ? ? ? ?Component base address 0x80004000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x10] = 0x5003
? ? ? ? ? ? ? ? ?Component base address 0x80005000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x14] = 0x6003
? ? ? ? ? ? ? ? ?Component base address 0x80006000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x18] = 0x7003
? ? ? ? ? ? ? ? ?Component base address 0x80007000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x1c] = 0x8003
? ? ? ? ? ? ? ? ?Component base address 0x80008000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x20] = 0x9003
? ? ? ? ? ? ? ? ?Component base address 0x80009000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x24] = 0xa003
? ? ? ? ? ? ? ? ?Component base address 0x8000a000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x28] = 0xb003
? ? ? ? ? ? ? ? ?Component base address 0x8000b000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x2c] = 0xc003
? ? ? ? ? ? ? ? ?Component base address 0x8000c000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x30] = 0xd003
? ? ? ? ? ? ? ? ?Component base address 0x8000d000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x34] = 0xe003
? ? ? ? ? ? ? ? ?Component base address 0x8000e000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x38] = 0xf003
? ? ? ? ? ? ? ? ?Component base address 0x8000f000
? ? ? ? ? ? ? ? ?Invalid CID 0x00000000
? ? ? ? ?ROMTABLE[0x3c] = 0x0
? ? ? ? ? ? ? ? ?End of ROM table
首先要指出的是這是Cortex R4,有了這些附加信息,我們可以在配置文件中創建目標,該目標應授予對MEM-AP的訪問權限,以便進行調試。這可以通過添加以下行來完成:
target create $_TARGETNAME.1 cortex_r4 -endian $_ENDIAN -dap $_CHIPNAME.dap
在這一行中,我們可以嘗試通過halt命令暫停目標并通過mdwOpenOCD提示符讀取內存:
?> halt
?MPIDR not in multiprocessor format
?target halted in Thumb state due to debug-request, current mode: Supervisor
?cpsr: 0x80000133 pc: 0x0001abfc
?D-Cache: disabled, I-Cache: disabled
?> mdw 0x800000000 10
?DAP transaction stalled (WAIT) - slowing down
?0x800000000: eafffffe ea000005 ea000006 ea000006 ea00000b e320f000 ea00000e eafffffe
?0x800000020: ea0000e3 eafffffe
在這里,我們測試逐步運行的固件:
?> halt
?MPIDR not in multiprocessor format
?target halted in ARM state due to debug-request, current mode: Supervisor
?cpsr: 0x80000113 pc: 0x0000e10c
?D-Cache: disabled, I-Cache: disabled
?> step
?target halted in ARM state due to breakpoint, current mode: Supervisor
?cpsr: 0x80000113 pc: 0x0000e110
?D-Cache: disabled, I-Cache: disabled
成功運行,我們可以單步調試固件。接下來,讓我們使用此功能獲取一些RAM轉儲,此頁面概述了內存模型,因此我們可以將其用作參考。可以使用OpenOCD通過dump_image命令將內存轉儲到文件中。
?> halt
?MPIDR not in multiprocessor format
?target halted in ARM state due to debug-request, current mode: Abort
?cpsr: 0x200001d7 pc: 0x00000048
?D-Cache: disabled, I-Cache: disabled
?Data fault registers? ? ? ? DFSR: 00000008, DFAR: 9f7e3000
?Instruction fault registers IFSR: 00000000, IFAR: 00000000
?> dump_image SDRAM.bin 0x20000000 0xA0000000
?> dump_image RAM.bin 0 0xFFFFFFF
最后,讓我們看一下這些RAM轉儲并將它們加載到GHIDRA中,看它們是否有意義:
太好了,我們有一些外部參照,并且init代碼看起來還不錯。看起來還好像在UART上提供了某種調試菜單,這很可能是我們引腳上的8/9引腳!可以肯定地說這是一個有效的RAM轉儲,并以此結束本文。
這是一篇很長的文章,實際上,它可能應該分成2-3個部分。通過這篇文章,我們學習了JTAG的底層功能,以及如何使JTAG成為逆向工程師的利器。我們還能夠通過JTAG訪問未記錄的目標,提取內存并單步運行固件。這里還有很多事情要做,例如確定閃存芯片本身是否可以通過JTAG轉儲,RE固件以尋找有趣的方式來從驅動器中恢復數據。
http://www2.futureware.at/~philipp/ssd/TheMissingManual.pdf
·?https://github.com/thesourcerer8/SSDdiag
·?http://www2.futureware.at/~philipp/ssd/TheMissingManual.pdf
參考及來源:https://wrongbaud.github.io/jtag-hdd/