Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86371811

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.

使用Raspi配置raspi-config是一個用戶空間工具,它允許我們配置樹莓派的各個方面,其中之一是啟用各種外部接口。我們將使用raspi-config來啟用UART接口,首先啟動工具,如下所示:

sudo raspi-config 這將導致出現以下結果:

33.png

接下來,我們將選擇Interface Options,然後是Serial Port,如下圖所示:

34.png

選擇這個選項後,我們會遇到兩個問題:

1.你希望通過串行方式訪問登錄shell嗎?

2.你想啟用串行端口硬件嗎?

我們現在已經在樹莓派上啟用了UART,接下來,我們需要將它連接到我們的機櫃。我們將機櫃的Tx連接到Pi的Rx,將機櫃的Rx 連接到Pi 的Tx:

35.png

UART工具使用樹莓派上的UART接口,我們可以嘗試連接到目標設備上的這個Serial Port。為了與這個Serial Port交互,我們將使用屏幕實用程序。當與UART接口時,屏幕要求我們傳遞一個設備和波特率,由於我們知道上一段的波特率,我們將按如下方式運行:

sudo screen -L -Logfile cabinet-bootup.log /dev/ttyS0 115200

-L -Logfile cabinet-bootup.log——將會話記錄到cabinet-bootup.log文件;

/dev/ttyS0——要使用的串行設備;

115200——波特率;

我們現在可以在配置我們的UART 和啟動屏幕後打開機櫃。當我們打開機櫃電源時,我們看到以下內容:

36.png

最終,我們發現自己在一個控制台:

37.png

我們現在有一個根控制台,可以探索文件系統,查看目標上正在運行的內容,並了解有關它是如何構建的更多信息。如果可能,我們的下一步將是對分區進行映像;讓我們先看看掛載了哪些分區:

38.png

我們的根文件系統是以只讀的形式掛載的,並且使用的是squashfs格式。此外,還掛載了標記為userdata的另一個分區。如果我們檢查可用的block設備,我們會看到以下內容:

39.png

我們可以看到,SPI flash設備大概位於/dev/rkflash0。要獲得這個block設備的圖像,我們可以將USB插到機櫃的USB端口並使用dd實用程序。當我們插入一個USB閃存驅動器時,它在/dev/sda 中被枚舉,我們可以用以下命令將SPI閃存的內容映射到USB驅動器:

Sudoddif=/dev/rkflash0of=/dev/sdastatus=progress如果我們將USB 驅動器插入Pi 並檢查分區表,我們會看到相應的分區已映射到驅動器。

40.png

現在我們有了閃存的備份,這是我們嘗試修改嵌入式系統時應該採取的第一步;在我們嘗試修改任何內容或重新刷新任何分區之前,我們應該確保我們有辦法恢復它們;為此,我們將調查引導加載程序。作為起點,讓我們注意啟動日誌開頭的以下行:

41.png

如果我們在為機櫃供電時在屏幕提示中按住Ctrl-c,我們會看到以下內容:

42.png

我們現在有一個UBoot 提示符,在深入探討之前,讓我們先談談UBoot 及其工作原理。

UBOOTUBoot是嵌入式系統中常用的開源引導加載程序。它支持各種架構和CPU類型。但是,UBoot 的職責通常是為嵌入式系統加載操作系統內核或主應用程序。

UBoot 還包括在你的逆向工程工作中有用的調試實用程序;最值得注意的是UBoot 命令提示符。

UBoot命令UBoot 控制台可以包含大量的內置實用程序,這些實用程序可以在標準引導過程中(通常通過環境變量)或在UBoot 命令行中使用。可用的命令將根據UBoot映像的構建方式而有所不同。

現在我們已經發現了一個UBoot 控制台,讓我們首先通過運行help 命令查看哪些命令是公開可用的。

43.1.png

43.2.png

43.3.png

在查看每個命令之前,讓我們重新審視一下我們的主要目標,即能夠從引導加載程序讀取和寫入根文件系統分區,以防我們以後需要恢復這個機櫃。下面的命令非常醒目,因為它們涉及內存讀取和寫入:

44.png

接下來,我們可以使用printenv 命令查看此引導加載程序配置的環境變量。這將為我們提供更多關於該平台如何啟動、正在使用的內存地址以及其他可用接口的背景信息。

UBoot環境變量在為設備構建或配置UBoot映像時,可以配置各種環境變量。這些環境變量控制啟動時執行的操作。存儲這些變量的方法有很多種。有時它們被硬編碼到二進制中,它們也可以駐留在閃存分區上,允許用戶從UBoot提示符修改它們。

我們可以使用printenv 命令檢查環境變量:

45.1.png

45.2.png

我想在下表中指出一些有趣的變量:

46.png

此時,如果我們交叉引用我們在硬件檢查期間收集的信息,我們會看到一致的結果。在我們的硬件檢查之後,我們假設SPI flash是主要的存儲方法,這個假設在UBoot環境變量和可用的命令中得到驗證。

讓我們從檢查rksfc命令開始,通過搜索,這是RockChip的SPI SFC(串行flash控制器)接口工具。該命令包含以下子命令:

47.png

可以通過以下命令獲取SPI flash的信息:

48.png

使用這些命令,我們可以了解更多關於SPI flash的信息。我們可以看到塊大小為512,該芯片總共包含220672 (0x35E00)塊,被分成5個分區:

uboot ——可能包含我們的UBoot 映像/第一階段引導加載程序;

trust ——可信執行環境映像;

boot ——內核映像/ramdisk;

rootfs ——我們最大的分區,內核的根文件系統;

user data——用戶特定數據,可能用於高分、用戶設置等;

注意,該數據與我們之前在根控制台提示符中看到的內容相匹配。我們現在了解了閃存是如何分區的以及可能有哪些數據可用,但是我們如何在不向板上焊接額外線路的情況下讀取/寫入這些數據呢?如果我們檢查usb 命令,我們會看到以下內容:

49.png

使用機櫃側面的USB 端口,如果我們插入設備並運行USB start 後跟USB info,則會生成以下輸出:

50.1.png

這樣,我們就可以看到USB堆棧成功枚舉並檢測到我們的大容量存儲設備。

在繼續之前,讓我們回顧一下我們對UBoot 環境的了解:

通過檢查環境變量,我們可以在RAM中找到可用的地址;

使用rksfc讀取實用程序,我們可以讀取SPI閃存扇區到RAM;

使用USB命令,我們可以枚舉一個USB設備並寫入它;

我們可以將SPI flash讀入RAM,連接USB設備,然後使用USB寫入命令將SPI flash數據寫入USB設備。如果這種方法有效,我們還應該能夠通過反向步驟恢復閃存圖像,從USB驅動器讀取數據,並使用rksfc write寫入閃存。讓我們從測試讀取開始。

首先,我們將嘗試使用以下命令將整個SPI 閃存讀入RAM 以獲取目標地址,我們將嘗試存儲在$ramdisk_addr_r 中的地址,即0x6a200000:

51.png

這不起作用,我們以某種方式觸發了未定義的指令異常。我們可能破壞了UBoot 正在使用的一些東西,讓我們看看當我們嘗試另一個內存較低的地址時會發生什麼:

52.png

移動到RAM 中的較低地址允許讀取完成而不會破壞任何內容,讓我們看看我們現在是否可以將這些數據寫回USB 驅動器:

53.png

現在我們來看看這個驅動器的內容,把它插入樹莓派,看看我們有什麼:

54.png

此時,我們可以看到USB驅動器上的分區表與rksfc part 0命令的輸出相匹配。接下來,我們將使用dd實用程序提取用於分析的各個分區。

55.png

到目前為止,該數據與我們在查看正在運行的系統上的掛載輸出和UBoot 菜單中的分區表時看到的數據相匹配。因此,我們可以通過unsquashfs 提取squashfs 分區並嘗試掛載ext2 分區以確認它們是有效的:

56.png

看起來我們有一個有效的根文件系統,現在我們可以開始逆向工程軟件了,並了解更多關於我們如何修改這個系統來玩更多遊戲或運行自定義固件的信息。

現在我們已經確認可以讀取flash,讓我們測試一下,看看我們是否可以使用上面描述的方法將這張圖片寫回flash:

57.png

現在我們重新啟動,希望我們重新刷新的圖像仍然有效。

58.jpg

成功!我們現在可以使用我們的USB 驅動器從UBoot 讀取/寫入SPI 閃存;這對於測試補丁和固件修改很有用!

現在我們可以用UBoot 讀/寫這個機櫃的flash,如果我們可以自動擦除flash 的各個分區和段,而不需要每次手動輸入範圍,那就太好了。為此,我們將使用Depthcharge 實用程序來自動化我們的UBoot 交互!

使用DEPTHCHARGE 編寫UBOOT在使用UBoot環境時,我們經常需要自動化交互。例如,在我們的示例中,我們可能希望自動重寫特定的閃存分區,而不必每次都手動輸入地址偏移量。對我們來說幸運的是,NCC集團的人已經組裝了一個工具來幫助我們,這個工具叫做深度充電。我們可以使用這個自動化的過程,從我們的閃存芯片和外部USB驅動器讀取數據。我們的腳本將需要執行以下操作:

連接到UART並識別UBoot提示符;

通過rksfc讀寫命令對SPI flash進行讀寫操作;

通過USB讀寫命令對USB驅動器進行讀寫;

首先,我們需要安裝模塊,可以通過執行命令sudo pip install depthcharge.o在Pi上安裝depthcharge。

連接到UART並識別UBoot提示符

我們可以使用以下python代碼連接到UBoot提示符:

微信截图_20220208150823.png

在上面的函數中,我們創建了一個Console對象,它要求我們提供一個到Serial Port和波特率的路徑。然後這個控制台對像被用來製作Depthcharge上下文,我們將使用它來訪問Depthcharge所提供的功能。 depthcharge文檔中有一個很好的例子,詳細描述了安裝過程。

Flash 通過depthcharge 讀寫現在我們已經連接到接口,我們需要實現rksfc讀寫命令。我們可以使用depthcharge的send_command() API來做到這一點。這個API調用允許我們生成UBoot命令並將其發送到命令提示符並返迴響應。在下面的例子中,我們在cmd_str變量中構造了read命令,並確保參數被正確格式化,然後使用send_command() API發出命令。

59.png

現在我們已經實現了對閃存的讀寫,接下來我們需要枚舉USB堆棧,然後從閃存驅動器中讀寫。

USB 通過depthcharge 讀寫與我們實現rksfc 命令的方式類似,接下來我們將實現usb 命令。該過程將類似於用於rksfc 命令的過程:

60.png

使用Depthcharge 轉儲閃存現在我們已經定義了適當的函數,我們可以嘗試以下操作:

61.png

如果我們運行這個腳本,就會看到如下輸出:

62.1.png

62.2.png

當我們將u盤插入Pi時,就會會看到以下分區:

63.png

成功!我們已經使用Depthcharge 將SPI 閃存提取到USB 設備!

文件系統內容現在我們有了一種可靠的讀取和寫入flash的方法,讓我們簡要地檢查一下內容。有趣的文件位於/moo文件夾中。此文件夾包含仿真器及其相關資源。 Moo是一個使用自定義ROM格式的自定義模擬器,2020年,一些研究人員在模擬器的另一個版本上進行了測試。然而,如果我們查看目錄內容,會發現一些有趣的現象:

64.png

在這個系統上肯定不可能有PE32 Windows 可執行文件,如果我們將此文件複製到Windows 機器上並嘗試執行它:

65.jpg

它運行了!顯然,這是一個構建工件,開發者沒有意識到它存在於系統中。

使用本文介紹的方法,我們現在可以使用UBoot 將SPI 閃存讀寫到USB 驅動器。我們已經提取了根文件系統並確定了核心模擬組件。我們的下一個目標將是對該目標上的一些二進製文件進行逆向工程,以確定運行自定義固件的困難程度。

總結我們在本文中介紹瞭如何使用我們的萬用表/邏輯分析儀執行嵌入式設備的初始拆卸和識別潛在的調試頭。然後進一步詳細介紹瞭如何分析未知的UART 流量並使用帶有Raspberry Pi 的屏幕連接到Serial Port。連接到Serial Port後,我們發現可以通過按Ctrl-C來訪問UBoot控制台。在查看了UBoot 控制台之後,我們編寫了一個depthcharge 腳本來將每個SPI 閃存分區提取到一個外部閃存驅動器中。所有使用的腳本和工具都可以在github上找到。