基于QEMU的NVRAM仿真
本文翻譯自 http://www.devttys0.com/2012/03/emulating-nvram-in-qemu/
能夠在Qemu中模擬嵌入式應(yīng)用程序非常有用,但并非沒有陷阱。我遇到的最常見的問題可能是的二進制程序試圖從NVRAM中讀取配置數(shù)據(jù)。由于二進制文件在Qemu中運行,而不是在目標(biāo)設(shè)備上運行,因此顯然沒有要讀取的NVRAM。
嵌入式應(yīng)用程序通常通過共享庫與NVRAM交互。該庫又與包含設(shè)備當(dāng)前配置設(shè)置的MTD分區(qū)接口交互。如果沒有NVRAM配置數(shù)據(jù),許多程序?qū)o法正常運行,需要我們攔截NVRAM庫調(diào)用并返回有效數(shù)據(jù),以便在Qemu中正確執(zhí)行應(yīng)用程序。
這是從固件更新映像中提取的Web服務(wù)器,該二進制程序拒絕在Qemu下啟動:
看起來httpd無法啟動,因為它不知道要綁定到哪個IP地址。IP無法通過命令行參數(shù)設(shè)置,因此必須從其他位置獲取此數(shù)據(jù)。讓我們啟動IDA并開始破解吧!
快速瀏覽httpd的主要功能可以發(fā)現(xiàn)罪魁禍?zhǔn)住ttpd服務(wù)器嘗試通過調(diào)用nvram_get來獲取IP地址和協(xié)議設(shè)置。如果這些調(diào)用失敗,則會打印出我們在上面看到的錯誤消息:
nvram_get函數(shù)是從共享庫中導(dǎo)入的,使用LD_PRELOAD可以很容易地進行攔截:
但是,在我們開始攔截函數(shù)調(diào)用之前,我們需要了解有關(guān)nvram_get的更多信息。它似乎只接受一個參數(shù),該參數(shù)是一個字符串(特別是上面的“l(fā)an_ipaddr”和“l(fā)an_proto”),但是它返回什么類型的數(shù)據(jù)?
從前面的反匯編中可以看出,nvram_get(“ lan_proto”)的返回值保存在寄存器R5中。后來,使用strcmp將R5指向的數(shù)據(jù)與字符串“ static”和“ dhcp”進行比較:
同樣,nvram(“ lan_ipaddr”)的返回值保存在寄存器R6中,該值稍后作為第一個參數(shù)傳遞給inet_aton:
因此,nvram_get的參數(shù)是鍵值對中的鍵字符串并返回相應(yīng)的值字符串。我們可以使用以下代碼輕松模擬此功能以及一些虛擬配置數(shù)據(jù):
我們需要將此代碼作為共享庫進行交叉編譯,并將其復(fù)制到squashfs-root目錄中,這個目錄是我們運行qemu的目錄:
eve@eve:~$ arm-linux-gcc -shared nvram.c -o nvram.so eve@eve:~$ cp nvram.so squashfs-root/nvram.so現(xiàn)在,我們將嘗試再次在Qemu中運行httpd,這一次在LD_PRELOAD環(huán)境變量中指定nvram.so文件的路徑:
eve@eve:~/squashfs-root$ sudo chroot . ./qemu-arm -E LD_PRELOAD="/nvram.so" usr/sbin/httpd usr/sbin/httpd: relocation error: /nvram.so: symbol __register_frame_info, version GLIBC_2.0 not defined in file libgcc_s.so.1 with link time reference看起來nvram.so文件期望引用__register_frame_info函數(shù),該函數(shù)符號在目標(biāo)系統(tǒng)的libgcc_s.so庫中不存在。發(fā)生這種情況是因為我們用來構(gòu)建nvram.so的工具鏈與供應(yīng)商用來為目標(biāo)系統(tǒng)構(gòu)建固件的工具鏈不同。我們希望__register_frame_info存在,而他們卻沒有。
由于供應(yīng)商未為其系統(tǒng)發(fā)布GPL代碼,因此我們不能簡單地使用其工具鏈來重新構(gòu)建nvram.so。我們可以向公司發(fā)起GPL請求,但是有一種更簡單(更快!)的方法。我們只需要在nvram.c中為__register_frame_info符號添加占位符定義(函數(shù)聲明):
#include <stdio.h> #include <string.h>void __register_frame_info(void) { } void __deregister_frame_info(void) { } void __unregister_frame_info(void) { }char *nvram_get(char *key) {char *value = NULL;if(strcmp(key, "lan_ipaddr") == 0){value = strdup("127.0.0.1");}if(strcmp(key, "lan_proto") == 0){value = strdup("static");}printf("nvram_get(%s) == %s\n", key, value);return value; }然后重新構(gòu)建nvram.so,再次嘗試運行httpd
eve@eve:~/squashfs-root$ sudo chroot . ./qemu-arm -E LD_PRELOAD="/nvram.so" usr/sbin/httpd httpd server started at port 80 (delay 0 second) nvram_get(lan_ipaddr) == 127.0.0.1 nvram_get(lan_proto) == static我們已成功攔截nvram_get調(diào)用,httpd錯誤消息已消失,服務(wù)器似乎正在運行。讓我們測試一哈:
成功!httpd現(xiàn)在可以與IDA的調(diào)試器進行一對一的交互了。
總結(jié)
以上是生活随笔為你收集整理的基于QEMU的NVRAM仿真的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 1247(Hat’s Words
- 下一篇: who is