透過QEMU 和 IDA Pro遠端除錯裝置韌體

wyzsk發表於2020-08-19
作者: cssembly · 2015/01/08 9:05

0x00 背景與簡介


這篇文章主要講了如何在模擬環境下除錯裝置韌體。

作者:Zach Cutlip

原文連結:http://shadow-file.blogspot.gr/2015/01/dynamically-analyzing-wifi-routers-upnp.html。

在分析嵌入式裝置的韌體時,只採用靜態分析方式通常是不夠的。你需要實際執行你的分析目標來觀察它的行為。在嵌入式Linux裝置的世界裡,很容易把一個偵錯程式放在目標硬體上進行除錯。如果你能在自己的系統上執行二進位制檔案,而不是拖著硬體做分析, 將會方便很多。這就需要用QEMU進行模擬。

接下來的一系列文章,我將專注於Netgear的一個比較流行的無線路由器,對其UPnP守護程式進行逆向分析。這篇文章將介紹如何在系統模擬環境下執行守護程式,以便可以透過偵錯程式對其進行分析。

0x01 先決條件


首先,建議你讀一下我的工作區以及所使用的工具的描述。這裡是連結http://shadow-file.blogspot.com/2013/12/emulating-and-debugging-workspace.html。

你需要一個MIPS Linux的模擬環境。對於這一點,建議讀者檢視我之前的搭建QEMU的帖子。http://shadow-file.blogspot.com/2013/05/running-debian-mips-linux-in-qemu.html

你還需要一個MIPS Linux的交叉編譯器。我不會詳細描述交叉編譯器的建立過程,因為它們一團糟。有時候,你需要較舊的工具鏈,而其他時候,你需要較新的工具鏈。最好使用uClibc buildroot project(http://buildroot.uclibc.org/)同時建立big endian和little endian的MIPS Linux工具鏈。除此之外,每當我發現其他交叉編譯工具鏈時,我都會儲存他們。類似D-Link和Netgear公司釋出GPL版本tarballs是舊工具鏈的好來源。

一旦你有了目標架構的交叉編譯工具鏈,你需要為目標建立GDB偵錯程式。你至少需要適合目標架構的被靜態編譯的gdbserver。如果要使用GDB進行遠端除錯,你需要編譯GDB,以便在你的本地機器架構(如X86-64)上執行,來對目標架構(如MIPS或mipsel體系結構)進行除錯。同樣,我也不會去討論這些工具的構建,如果你建立了你的工具鏈,這應該很容易了。

後面我將描述如何使用IDA Pro來進行遠端除錯。但是,如果你想使用gdb,可以看看我的MIPS gdbinit檔案:https://github.com/zcutlip/gdbinit-mips

0x02 模擬一個簡單的二進位制


假設你已經建立了上述工具,並能正常工作,你現在應該能夠透過SSH進入您的模擬MIPS系統。正如我在Debian MIPS QEMU文章中所述,我喜歡連線QEMU的介面到VMWare的NAT介面,這樣就能夠用我的Mac透過SSH來接入,而不需要先登陸我的Ubuntu虛擬機器。這也可以讓我透過NFS將我的Mac工作區掛載到QEMU系統。這樣,無論我工作在主機環境中,或是Ubuntu中,還是在QEMU中,我都在用相同的工作區。

[email protected]:~ (130) $ ssh [email protected]
[email protected]'s password:
Linux debian-mipsel 2.6.32-5-4kc-malta #1 Wed Jan 12 06:13:27 UTC 2011 mips

[email protected]:~# mount
/dev/sda1 on / type ext3 (rw,errors=remount-ro)
malastare:/Users/share/code on /root/code type nfs (rw,addr=192.168.127.1)
[email protected]:~#cd code
[email protected]:~/code#

一旦登陸到模擬系統,cd到從裝置的韌體中提取的檔案系統中。你應該能夠chroot到韌體的根檔案系統。需要使用chroot,因為目標二進位制是和韌體的庫連結的,很可能不能跟Debian的共享庫一起工作。

[email protected]:~#cd code/wifi-reversing/netgear/r6200/extracted-1.0.0.28/rootfs/
[email protected]:[email protected]e ./bin/ls
./bin/ls: symbolic link to `busybox'
[email protected]:[email protected]e ./bin/busybox
./bin/busybox: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), stripped
[email protected]:[email protected]oot . /bin/ls -l /bin/busybox
-rwxr-xr-x    1 10001    80         276413 Sep 20  2012 /bin/busybox
[email protected]:~/code/wifi-reversing/netgear/r6200/extracted-1.0.0.28/rootfs#

在上面的例子中,我已切換到所提取的檔案系統的根目錄中。然後使用file命令,我瞭解到busybox是little endian MIPS可執行檔案。然後,chroot到提取根目錄,並執行bin/ls,它是busybox的符號連結。

如果試圖簡單的透過“chroot .”來地啟動一個shell,將無法正常工作。因為你的預設shell是bash,而大多數嵌入式裝置沒有bash。

[email protected]:[email protected]oot . chroot: failed to run command `/bin/bash': No such file or directory [email protected]:~/code/wifi-reversing/netgear/r6200/extracted-1.0.0.28/rootfs#

相反,你可以chroot並執行bin / sh:

[email protected]:[email protected]oot . /bin/sh

BusyBox v1.7.2 (2012-09-20 10:26:08 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

#
#
#exit
[email protected]:~/code/wifi-reversing/netgear/r6200/extracted-1.0.0.28/rootfs#

0x03 硬體解決方法


即使有了必要的工具,建立了模擬環境且工作正常,你仍然可能遇到障礙。雖然QEMU在模擬核心晶片組包括CPU上都做的很不錯,但是QEMU往往不能提供你想執行的二進位制程式需要的硬體。如果你試圖模仿一些簡單的像/bin/ls的程式,通常能夠正常工作。但更復雜的東西,如肯定有特定的硬體依賴的UPnP守護程式,QEMU就不能夠滿足。尤其對於管理嵌入式系統硬體的程式更是這樣,例如開啟或關閉無線介面卡。

你將遇到的最常見問題是在執行系統服務,如Web伺服器或UPnP守護程式時,缺乏NVRAM。非易失性RAM通常是包含配置引數的裝置快速儲存器的一個分割槽。當一個守護程式啟動時,它通常會嘗試查詢NVRAM,獲取其執行時配置資訊。有時一個守護程式會查詢NVRAM的幾十甚至上百個引數。

為了解決在模擬條件下缺乏NVRAM的問題,我寫了一個叫nvram-faker的庫。當你執行二進位制程式時,應該使用LD_PRELOAD對nvram-faker庫進行預載入。它會攔截通常由libnvram.so提供的nvram_get()呼叫。nvram-faker會查詢你提供的一個INI風格的配置檔案,而不是試圖查詢NVRAM。

附帶的README提供更完整的說明。這裡有一個連結:https://github.com/zcutlip/nvram-faker

即使解決了NVRAM問題,該程式可能會假設某些硬體是存在的。如果硬體不存在,該程式可能無法執行,或者即便它執行了,行為可能也與在其目標硬體上執行時有所不同。在這種情況下,你可能需要修補二進位制檔案。採用二進位制補丁的情況各不相同。這取決於期望什麼硬體,以及它不存在時的行為是什麼。如果硬體缺失,你可能需要修補一個被執行到的條件分支。也可能需要修補針對特殊裝置的ioctl()呼叫,如果你想將其替代為針對常規檔案的讀取和寫入時。這裡我將不談論修補的細節,但在我的BT HomeHub文章以及44CON的相應講座中進行了討論。

這裡是這些資源的連結:http://shadow-file.blogspot.com/2013/09/44con-resources.html

0x04 附加偵錯程式


一旦在QEMU中執行了二進位制程式,就可以附加偵錯程式了。當然你需要gdbserver。同樣,這個工具應該適合目標架構並被靜態編譯,因為你會在chroot下執行它。你需要將它複製到提取的檔案系統的根目錄中。

# ./gdbserver
Usage: gdbserver [OPTIONS] COMM PROG [ARGS ...]
gdbserver [OPTIONS] --attach COMM PID
gdbserver [OPTIONS] --multi COMM

COMM may either be a tty device (for serial debugging), or
HOST:PORT to listen for a TCP connection.

Options:
  --debug               Enable general debugging output.
--remote-debug        Enable remote protocol debugging output.
--version             Display version information and exit.
  --wrapperWRAPPER --  Run WRAPPER to start new programs.
  --once                Exit after the first connection has closed.
#

你可以將gdbserver附加到正在執行的程式,或者用它來直接執行二進位制程式。如果你需要除錯只發生一次的初始化程式,你可以選擇後者。

另一方面,你可能要等到守護程式被建立。據我所知沒有辦法讓IDA跟蹤建立的程式(forked processes)。你需要單獨的附加到它們。如果採用這種方式,你可以在chroot外,附加到已經執行的程式。

以下shell指令碼將在chroot下執行upnpd。如果DEBUG設定為1,它會附加在upnpd上,並在1234埠上暫停等待遠端除錯會話。

#!bash
ROOTFS="/root/code/wifi-reversing/netgear/r6200/extracted-1.0.0.28/rootfs"
chroot$ROOTFS /bin/sh -c "LD_PRELOAD=/libnvram-faker.so /usr/sbin/upnpd"

#Give upnpd a bit to initialize and fork into the background.
sleep 3;

if [ "x1" = "x$DEBUG" ];
then

$ROOTFS/gdbserver --attach 0.0.0.0:1234 $(pgrepupnpd)
fi

你可以在recvfrom()呼叫之前建立一個斷點,然後當你向upnpd傳送M-SEARCH包時,驗證偵錯程式斷點。

enter image description here

然後,在IDA的Debugger選單中的Process選項中設定“主機名”為你的QEMU系統的IP地址,並設定埠為gdbserver正在監聽的埠。我用的是1234。

enter image description here

接受設定,然後透過IDA的CTRL+8熱鍵連線到遠端除錯會話。再次按Ctrl+8繼續執行。你應該能夠傳送一個M-SEARCH包1,可以看到偵錯程式命中斷點。

enter image description here

顯然還有很多需要探索,也會遇到有很多這裡未提及的情況,但希望這可以讓你開始。

我推薦Craig Heffner用於UPnP分析的miranda工具:https://code.google.com/p/miranda-upnp/

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章