日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
物聯(lián)網終端安全入門與實踐之玩轉物聯(lián)網固件

本篇將系統(tǒng)性介紹終端設備固件仿真的概念、技術、工具和框架,以及手動固件仿真的過程和技巧。

0x01 背景

在漏洞研究過程中,我們會遇到若干不可控的因素影響實體設備的使用,比如:

  • 目標設備比較昂貴,采購預算不足
  • 國外設備不易采購,缺乏采購渠道
  • 調試過程中的設備損耗導致設備數量不足

固件仿真就可以很好解決以上問題,原因如下:

  • 無需采購,零成本
  • 調試更加靈活可控
  • 突破數量限制,可無限制仿真設備

當然,固件仿真也有不少缺點,比如:

  • 固件運行環(huán)境碎片化,仿真成功率低
  • 仿真設備在某些方面無法完美模擬真實設備
  • 部分固件的仿真配置比較繁瑣,有一定的技術門檻

無論如何,固件仿真與實體設備之間是相輔相成、互為補充的關系,都是物聯(lián)網漏洞挖掘的基礎環(huán)境。( ps:如果不差錢,還是實體設備香?。?/p>

0x02 應用場景

固件仿真技術可應用于:

  • 漏洞研究
  • 模糊測試
  • 漏洞靶場
  • IoT蜜罐

0x03 概念介紹

本章梳理了仿真技術的分類分級、仿真工具和仿真框架,便于讀者系統(tǒng)性了解仿真技術的概念。

3.1 仿真概念

首先,什么是仿真?仿真是利用模型復現實際系統(tǒng)中發(fā)生的本質過程,并通過對系統(tǒng)模型的實驗來研究存在的或設計中的系統(tǒng),又稱模擬。而固件仿真其實就是固件模擬運行。

那么,固件仿真可以達到什么樣的效果呢?

利用成熟的仿真工具/框架,模擬運行固件中的全部或特定服務,提供與真實設備服務盡可能相似或無差別的體驗,支撐漏洞研究、靶場、蜜罐應用。

固件仿真技術的分類有哪些呢?

目前固件仿真是主要技術分為用戶態(tài)仿真和系統(tǒng)級仿真 (將會在3.2.1 和3.2.2分別展開講解)。

在此之上,還有人提出了一些仿真技術的思想:

應用級仿真——指并不執(zhí)行程序,而是僅僅加載網絡應用對應頁面的方式。最簡單的應用級仿真是直接用對應架構的操作系統(tǒng)系統(tǒng),將網頁文件復制出來,使用常用的網絡服務啟動。

代碼片段仿真——只執(zhí)行二進制文件中的一部分代碼,使用Patch、預設數據等方式使得代碼可以正常執(zhí)行

3.1.1 用戶態(tài)仿真技術

用戶態(tài)仿真是在宿主機上主要針對單個可執(zhí)行程序進行的仿真,調試和運行方便,無需配置其他的環(huán)境,如內核、磁盤映像以及虛擬網橋等。例如,在x86架構宿主機上運行一個arm架構的程序,同時可提供該arm程序的gdb調試入口。

3.1.2 系統(tǒng)級仿真技術

系統(tǒng)仿真是在宿主機上對指定架構的操作系統(tǒng)的模擬運行(包括CPU和其他周邊設備),既可以讓單個可執(zhí)行程序正常運行,也可以支持多個可執(zhí)行程序并行。

例如,在x86架構宿主機上模擬出arm架構的操作系統(tǒng)環(huán)境,運行固件解包后得文件系統(tǒng)中的啟動腳本/etc/rcS(其內部執(zhí)行了多個程序)。

3.2 仿真工具

以下講述了常用的2種固件仿真工具的相關介紹

3.2.1 QEMU

QEMU是一個通用的開源機器仿真器和虛擬化器。當用作機器仿真器時,QEMU可以在另一臺機器(例如自己的PC)上運行為一臺機器(例如ARM架構的操作系統(tǒng)和程序)。通過使用動態(tài)翻譯,它實現了非常好的性能。用作虛擬化器時,用其他VMM(Xen,KVM,etc)來使用硬件提供的虛擬化支持,創(chuàng)建接近于主機性能的虛擬機。QEMU 在 Xen 虛擬機管理程序下執(zhí)行或在 Linux 中使用 KVM 內核模塊時支持虛擬化。使用 KVM 時,QEMU 可以虛擬化 x86、服務器和嵌入式 PowerPC、64 位 POWER、S390、32 位和 64 位 ARM 以及 MIPS 客戶機。QEMU仿真   主要使用的兩種運作模式如下:

  • qemu-user:啟動不同CPU架構的linux程序,模擬程序運行
  • qemu-system:模擬包括CPU及其它外設的整個操作系統(tǒng),支持對應架構的多個程序在其中同時運行

3.2.2 Unicorn

Unicorn是基于qemu的CPU仿真跨平臺架構框架,主要目的就是在QEMU之上構建自己的工具。Unicorn 只關注 CPU 操作,可以在沒有上下文的情況下模擬原始代碼。使用Unicorn可以從 CPU 執(zhí)行到內存訪問的各種事件注冊自定義處理程序,為程序員提供了在仿真環(huán)境下監(jiān)視和分析代碼所需的所有功能。QEMU 不能同時處理多個 CPU。相比之下,Unicorn被設計和實現為一個框架,以便一個程序可以在一瞬間模擬不同類型CPU的多個代碼。

3.3 仿真框架

為什么要使用仿真框架?手動仿真時需要對錯誤逐一修復,耗時耗力。而仿真框架封裝并融合了仿真工具和周邊配套系統(tǒng)的能力,對已知錯誤做了內部處理,并且進行了仿真自動化的工程建設,自動化程度比較成熟,極大提高了仿真的效率。下表列舉了一些常見或經典的仿真框架,并對各個框架進行了簡單的介紹。

框架名稱

底層依賴

框架介紹

??Firmadyne??

qemu

以系統(tǒng)級仿真為基礎,使用定制動態(tài)鏈接庫完成庫函數劫持支撐NVRAM設備調用,基于定制內核完成操作系統(tǒng)啟動、探測網絡結構、虛擬硬件,通過系統(tǒng)配置完成網絡構建,調用QEMU仿真異架構操作系統(tǒng)完成仿真

??Firmware Analysis Toolkit??

簡化firmadyne執(zhí)行流程的腳本 (??AttifyOS??已集成)

??FirmAE??

基于Firmadyne:但相比Firmadyne,提高了仿真成功率

??Firmware Analysis Plus??

基于Firmadyne、Firmware Analysis Toolkit:精簡不必要組件,優(yōu)化仿真流程,優(yōu)化網絡環(huán)境大幅壓縮安裝時間,提高了仿真成功率

??qiling??

unicorn

由國內京東牧者安全實驗室在2019年Defcon首次推出, 以用戶態(tài)仿真為思想,相比qemu支持更多平臺,包括Windows,MacOS,Linux和BSD的一款分析框架。(由于一直在更新,對應demo無法運行且缺少對應版本固件仿真說明文檔,不適合入門使用)

0x04 仿真邏輯

本章分別講解qemu-user和qemu-system固件仿真邏輯

4.1 用戶態(tài)仿真邏輯

在宿主機環(huán)境內,chroot改變根目錄到固件文件系統(tǒng)(一個正常固件通常包含uboot、kernel和文件系統(tǒng)3部分,對固件解包就可以獲取到文件系統(tǒng))的目錄下,使用qemu-user執(zhí)行待仿真程序。

4.2 系統(tǒng)仿真邏輯

首先,在宿主機環(huán)境內架設虛擬網橋,然后使用qemu-system加載內核和磁盤鏡像啟動仿真系統(tǒng),此時宿主機與仿真系統(tǒng)間能夠進行正常的網絡通信。接下來,將固件解包后提取的文件系統(tǒng)拷貝到仿真系統(tǒng)中,掛載文件系統(tǒng)到指定目錄。最后,使用chroot命令改變根目錄到固件文件系統(tǒng)目錄,運行目標程序或腳本文件,比如 httpd服務程序、/etc/rcS啟動腳本等。

0x05 仿真實踐

本章以D-link DIR-816A2_v1.10CNB03_D77137.img固件為例,手動模擬啟動固件中的web服務goahead。注:部分仿真框架(如Firmadyne、FirmAE、FAT等)無法自動化仿真上述固件的web服務。

5.1 環(huán)境安裝

宿主機系統(tǒng):kali-linux-2022.2-amd64 工具:

  • binwalk (kali已集成)
  • qemu 安裝
sudo apt install qemu-user
sudo apt install qemu-user-static
sudo apt install qemu-system

網橋工具

sudo apt install bridge-utils uml-utilities

5.2 仿真示例

5.2.1 用戶態(tài)模擬

下圖描述的固件中的二進制程序的架構是mipsel32架構,所以需要使用適配mips架構的qemu-mipsel-static程序進行仿真。

將qemu-mipsel-static拷貝到當前固件的文件系統(tǒng)目錄中。

接下來,使用chroot切換根目錄,使用qemu-mipsel-static工具翻譯執(zhí)行程序goahead。我們使用chroot命令的原因是為了程序查找相對路徑下的動態(tài)鏈接庫。

如上圖所示,程序執(zhí)行出現錯誤:"cannot open pid file"。根據錯誤信息,在ida中對字符串調用定位報錯點,發(fā)現報錯原因:無法打開 /var/run/goahead.pid。查看文件系統(tǒng)內并沒有此文件,通過touch ./var/run/goahead.pid命令創(chuàng)建該文件可以解決該錯誤。

完成第一個報錯修復后重新仿真程序,程序繼續(xù)執(zhí)行時出現錯誤:"waiting for nvram_daemon",如下圖所示。

如下圖,根據字符串定位在ida中發(fā)現了報錯原因:無法打開/var/run/nvramd.pid。查看文件系統(tǒng)內并沒有此文件,通過touch ./var/run/nvramd.pid命令創(chuàng)建該文件可以解決該錯誤。

已經修復了2處報錯點。再次重新運行程序,出現了第三個報錯:"failed to convert to binary ip data",如下圖所示。

如下圖所示,ida中提示報錯原因:nvram_bufget函數無法讀取lan_ipaddr,而nvram_bufget是從/dev/nvram中讀取數據。在Linux操作系統(tǒng)中,硬件設備也被看做文件來處理,/dev/nvram是非易失性存儲器nvram設備(具體概念在5.3.2章節(jié)進行介紹)。為此,我們將分別講解劫持動態(tài)鏈接庫和patch共2種方法來解決仿真過程中設備缺失的問題。

5.2 .1.1 使用LD_PRELOAD方式劫持動態(tài)鏈接庫實現nvram設備的模擬

劫持動態(tài)鏈接庫是什么意思呢?例如,程序nvram_xxx函數都是通過動態(tài)鏈接方式來鏈接libnvram-0.9.28.so這個函數庫的,我們只要在加載libnvram-0.9.28.so之前加載我們自己的so文件就可以劫持這些函數,所以我們需要實現一個自己的so文件。FirmAE提供的libnvram庫(https://github.com/pr0v3rbs/FirmAE/tree/master/sources/libnvram)已經寫好了最關鍵的nvram_bufget函數,如下圖所示。并且libnvram目錄下中的config.h中已經提供了一部分nvram中的初始數據。

為了適配我們的環(huán)境,需要對config.h做一下修改:

設置nvram讀取掛載點 (創(chuàng)建目錄存放nvram數據),為此我們需要在文件系統(tǒng)中創(chuàng)建目錄mkdir ./mnt/libnvram.

config.h —— 修改啟動web IP地址 為eth0網卡 IP。

修改完成后,進行動態(tài)鏈接庫libnvram.so的編譯。

mipsel-linux-gnu-gcc -c -O2 -fPIC -Wall nvram.c -o nvram.o
mipsel-linux-gnu-gcc -shared -nostdlib nvram.o -o libnvram.so

手動加載修改后的libnvram.so再次運行,如下圖所示,仍然遇到報錯,發(fā)現還是缺少相關鍵值對!

根據報錯信息提示,利用ida進行字符串定位,簡易分析獲取鍵值,在config.h添加對應數據,再次編譯。這個過程需要耐心。由于每個人分析方法不同,填入的值不同,最終面臨的報錯就不同。以下是修復后的config.h (65-68行的IP根據個人環(huán)境修改)。

#ifndef INCLUDE_CONFIG_H
#define INCLUDE_CONFIG_H

// Determines whether debugging information should be printed to stderr.
#define DEBUG 1
// Determines the size of the internal buffer, used for manipulating and storing key values, etc.
#define BUFFER_SIZE 256
// Determines the size of the "emulated" NVRAM, used by nvram_get_nvramspace().
#define NVRAM_SIZE 2048
// Determines the maximum size of the user-supplied output buffer when a length is not supplied.
#define USER_BUFFER_SIZE 64
// Determines the unique separator character (as string) used for the list implementation. Do not use "\0".
#define LIST_SEP "\xff"
// Special argument used to change the semantics of the nvram_list_exist() function.
#define LIST_MAGIC 0xdeadbeef
// Identifier value used to generate IPC key in ftok()
#define IPC_KEY 'A'
// Timeout for the semaphore
#define IPC_TIMEOUT 1000
// Mount point of the base NVRAM implementation.
#define MOUNT_POINT "/mnt/libnvram/"
// Location of NVRAM override values that are copied into the base NVRAM implementation.
#define OVERRIDE_POINT "/mnt/libnvram.override/"

// Define the semantics for success and failure error codes.
#define E_FAILURE 0
#define E_SUCCESS 1

// Default paths for NVRAM default values.
#define NVRAM_DEFAULTS_PATH \
/* "DIR-505L_FIRMWARE_1.01.ZIP" (10497) */ \
PATH("/var/etc/nvram.default") \
/* "DIR-615_REVE_FIRMWARE_5.11.ZIP" (9753) */ \
PATH("/etc/nvram.default") \
/* "DGL-5500_REVA_FIRMWARE_1.12B05.ZIP" (9469) */ \
TABLE(router_defaults) \
PATH("/etc/nvram.conf") \
PATH("/etc/nvram.deft") \
PATH("/etc/nvram.update") \
TABLE(Nvrams) \
PATH("/etc/wlan/nvram_params") \
PATH("/etc/system_nvram_defaults") \
FIRMAE_PATH("/image/mnt/nvram_ap.default") \
/* "DCS-931L_FIRMWARE_1.04B1.ZIP" by SR */\
FIRMAE_PATH("/etc_ro/Wireless/RT2860AP/RT2860_default_vlan") \
FIRMAE_PATH("/etc_ro/Wireless/RT2860AP/RT2860_default_novlan") \
/* "DGN3500-V1.1.00.30_NA.zip" */\
FIRMAE_PATH2("/usr/etc/default") \
/* "JR6150-R6050-V1.0.0.22.zip" by SR */ \
FIRMAE_PATH("/image/mnt/nvram_whp.default") \
FIRMAE_PATH("/image/mnt/nvram_rt.default") \
FIRMAE_PATH("/image/mnt/nvram_rpt.default") \
FIRMAE_PATH("/image/mnt/nvram.default")

// Default values for NVRAM.
#define NVRAM_DEFAULTS \
/* Linux kernel log level, used by "WRT54G3G_2.11.05_ETSI_code.bin" (305) */ \
ENTRY("console_loglevel", nvram_set, "7") \
/* Reset NVRAM to default at bootup, used by "WNR3500v2-V1.0.2.10_23.0.70NA.chk" (1018) */ \
ENTRY("restore_defaults", nvram_set, "1") \
ENTRY("sku_name", nvram_set, "") \
ENTRY("wla_wlanstate", nvram_set, "") \
ENTRY("lan_if", nvram_set, "br0") \
/* eth0 IP */\
ENTRY("lan_ipaddr", nvram_set, "192.168.0.128")\
ENTRY("lan_bipaddr", nvram_set, "192.168.0.255")\
ENTRY("oldlan_ipaddr", nvram_set, "192.168.0.50")\
ENTRY("lan_netmask", nvram_set, "255.255.255.0") \
/* Set default timezone, required by multiple images */ \
ENTRY("time_zone", nvram_set, "PST8PDT") \
/* Set default WAN MAC address, used by "NBG-416N_V1.00(USA.7)C0.zip" (12786) */ \
ENTRY("wan_hwaddr_def", nvram_set, "01:23:45:67:89:ab") \
/* Attempt to define LAN/WAN interfaces */ \
ENTRY("wan_ifname", nvram_set, "eth0") \
ENTRY("lan_ifnames", nvram_set, "eth1 eth2 eth3 eth4") \
/* Used by "TEW-638v2%201.1.5.zip" (12898) to prevent crash in 'goahead' */ \
ENTRY("ethConver", nvram_set, "1") \
/* Used by "Firmware_TEW-411BRPplus_2.07_EU.zip" (13649) to prevent crash in 'init' */ \
ENTRY("lan_proto", nvram_set, "dhcp") \
ENTRY("wan_ipaddr", nvram_set, "0.0.0.0") \
ENTRY("wan_netmask", nvram_set, "255.255.255.0") \
ENTRY("wanif", nvram_set, "eth0") \
/* Used by "DGND3700 Firmware Version 1.0.0.17(NA).zip" (3425) to prevent crashes */ \
ENTRY("time_zone_x", nvram_set, "0") \
ENTRY("rip_multicast", nvram_set, "0") \
ENTRY("bs_trustedip_enable", nvram_set, "0") \
/* Set default MAC address, used by "linux-lzma(550A)" by SR */ \
FIRMAE_ENTRY("et0macaddr", nvram_set, "01:23:45:67:89:ab")\
/* Used by "AC1450-V1.0.0.34_10.0.16.zip" to prevent crashes by SR */ \
FIRMAE_ENTRY("filter_rule_tbl", nvram_set, "") \
/* Used by Netgear "R6200V2-V1.0.1.14_1.0.14.zip" by SR */ \
FIRMAE_ENTRY("pppoe2_schedule_config", nvram_set, "127:0:0:23:59") \
FIRMAE_ENTRY("schedule_config", nvram_set, "127:0:0:23:59") \
/* Used by Netgear WNDR3400v3, WNDR3500v3 "WNR3500L-V1.2.0.18_40.0.67" to prevent crashes due to following "atoi" func by SR */ \
FIRMAE_ENTRY("access_control_mode", nvram_set, "0") \
FIRMAE_ENTRY("fwpt_df_count", nvram_set, "0") \
FIRMAE_ENTRY("static_if_status", nvram_set, "1") \
/* R8500 patch to prevent crashes in httpd */ \
FIRMAE_ENTRY("www_relocation", nvram_set, "") \
FIRMAE_FOR_ENTRY("usb_info_dev%d", nvram_set, "A200396E0402FF83@1@14.4G@U@1@USB_Storage;U:;0;0@", 0, 101) \
/* R6200V2, R6250-V1, R6300v2, R6400, R6700-V1, R7000-V1, R7900, R8000, R8500 patch to prevent crashes in httpd */ \
FIRMAE_FOR_ENTRY("wla_ap_isolate_%d", nvram_set, "", 1, 5) \
/* R6200V1 patch to prevent crashes in httpd */ \
FIRMAE_FOR_ENTRY("wlg_ap_isolate_%d", nvram_set, "", 1, 5) \
FIRMAE_FOR_ENTRY("wlg_allow_access_%d", nvram_set, "", 1, 5) \
/* R6400-V1, R7900-V1, R8000, R8500 patch to prevent crashes in httpd */ \
FIRMAE_FOR_ENTRY("%d:macaddr", nvram_set, "01:23:45:67:89:ab", 0, 3) \
FIRMAE_FOR_ENTRY("lan%d_ifnames", nvram_set, "", 1, 10)\
ENTRY("portal_manage_enable", nvram_set, "0") \
ENTRY("TZ", nvram_set, "EST5EDT") \
ENTRY("OperationMode", nvram_set, "2") \
ENTRY("wanConnectionMode", nvram_set, "DHCP") \
ENTRY("AuthMode", nvram_set, "0") \
ENTRY("IEEE8021X", nvram_set, "0") \
ENTRY("BssidNum", nvram_set, "11") \
ENTRY("WscModeOption", nvram_set, "7") \
ENTRY("WscConfMethods", nvram_set, "0x680") \
ENTRY("WscConfigured", nvram_set, "0")\
ENTRY("telnetEnabled", nvram_set, "0")\
ENTRY("Language", nvram_set, "EN")\
ENTRY("Login", nvram_set, "admin")\
ENTRY("Password", nvram_set, "")\
ENTRY("ProductModemVersion", nvram_set, "")\
ENTRY("HardwareVersion", nvram_set, "A2")\
ENTRY("Login_encode", nvram_set, "")\
ENTRY("FirmwareVersion", nvram_set, "")\
ENTRY("IPPortFilterRules", nvram_set, "0")\
ENTRY("IPPortFilterRules0", nvram_set, "0")\
ENTRY("acl_rules", nvram_set, "web")\
ENTRY("portal_addr", nvram_set, "")\
ENTRY("HostName", nvram_set, "")\
ENTRY("NTPEnable", nvram_set, "")\
ENTRY("NTPServerIP", nvram_set, "")\
ENTRY("NTPSync", nvram_set, "1")
#endif

手動加載修改后的libnvram.so再次運行,web界面已經可以正常打開了。

使用提前設置好的用戶名密碼也可以正常登錄進入后臺啦~

5.2.1.2 使用patch方式實現關鍵跳轉的繞過

使用qemu并將程序掛載在23946端口,等待調試。

在報錯跳轉處地址0x45cdbc下斷點。

ida遠程連接調試端口,按F9運行 (調試連接IP為eth0網卡 IP)。

斷點斷下來后,將V0寄存器原值0xFFFFFFFF 修改為非-1值后可跳過報錯,然后繼續(xù)執(zhí)行程序。

輸入eth0 本機IP 192.168.0.128 可以跳轉,無法正常對頁面加載。

由于缺少nvram中l(wèi)an_ipaddr值,所以只能手動補全url:192.168.0.128/dir_login.asp 可以正常訪問登錄網頁,但輸入用戶名和密碼登錄依然進行報錯。

問題出在登錄檢驗。由于缺失nvram,無法讀取相關數據,必須強行修改跳轉。在地址0x4570fc和0x457118下斷點。

重復之前的步驟,成功打開登錄界面后,輸入用戶名密碼點擊登錄后會在斷點斷下,將V0寄存器值都修改為0跳過報錯,繼續(xù)運行。

發(fā)現可以成功跳轉到后臺頁面。

手動補全url后:192.168.0.128/index.asp 可以正常訪問后臺界面了。

注:此固件是mipsel架構的,熟悉此架構的小伙伴可以通過ida在之前的跳轉處修改opcode保存,再次運行時可以不用再重復以上的調試步驟。

5.2.2 系統(tǒng)級模擬

5.2.2.1 配置網絡

首先根據下表依次操作:

#0.安裝網橋
sudo apt-get install bridge-utils uml-utilities

#1.配置橋接網卡
sudo gedit /etc/network/interfaces
#追加寫入以下內容
auto br0
iface br0 inet dhcp
bridge_ports eth0
bridge_maxwait 0

#2.創(chuàng)建QEMU的網絡接口啟動腳本
sudo gedit /etc/qemu-ifup
#追加在最后寫入以下內容:
#!/bin/sh
echo "Executing /etc/qemu-ifup"
echo "Bringig $1 for bridged mode..."
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
sudo /sbin/brctl addif br0 $1
sleep 3


#3.重啟網絡
sudo ifup br0
sudo /etc/init.d/networking restart

完成上述操作后,如果發(fā)現eth0 IP地址與br0 IP地址一樣,需要手動修改:ifconfig eth0 192.168.0.200/24,否則會影響到與qemu虛擬機的通信。

5.2.2.2 啟動qemu虛擬機

  • 下載對應架構內核和硬盤鏡像
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_squeeze_mipsel_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-2.6.32-5-4kc-malta
  • 打包文件系統(tǒng)
tar -czvf DIR-816.tar ./squashfs-root/
  • 啟動虛擬機 用戶名和密碼都是 root
sudo qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap -nographic
  • 此時狀態(tài),互相之間都可以正常通信

kali br0:192.168.0.128

kali eth0:192.168.0.200

qemu eth0 : 192.168.0.121

5.2.2.3 移植修改文件系統(tǒng)

  • 將kali中打包的文件系統(tǒng)tar包以及之前修改好的libnvram.so 上傳到qemu虛擬機中
scp DIR-816.tar libnvram.so root@192.168.0.104:/root/
  • 在qemu虛擬機中解壓
tar xzvf DIR-816.tar
  • 切換根目錄固件文件系統(tǒng)
mount -o bind /dev ./squashfs-root/dev/
mount -t proc /proc/ ./squashfs-root/proc/
chroot squashfs-root sh

創(chuàng)建目錄防止報錯

mkdir /var/run
touch /var/run/goahead.pid
touch /var/run/nvramd.pid
mkdir /mnt/libnvram

5.2.2.4 運行待仿真程序

手動加載修改的libnvram.so 運行程序。

LD_PRELOAD="./libnvram.so" /bin/goahead

如下圖,運行過程仍然遇到了報錯:缺少wscd命令。

發(fā)現固件中本身缺少相關程序,本著缺什么補什么的思想,從D-link其他型號固件中找到了相同架構的wscd程序并提取其依賴動態(tài)庫上傳至qemu虛擬機中。

測試wscd程序并運行,發(fā)現依然報錯,暫時無法解決報錯。

在實體設備中利用漏洞獲取shell后,發(fā)現也并沒有wscd程序。遂更換思路,發(fā)現只需要nvram中 OperationMode設置為2(滿足!='3' && !='0' && != '1'條件),即可避免執(zhí)行wscd相關命令。

config.h 中修改OperationMode值。并修改lan_ipaddr值,重新編譯(注:qemu eth0要與kali br0進行通信,IP重復沖突的話會導致qemu中程序運行起來而kali虛擬機無法訪問)。

重新上傳libnvram.so到qemu虛擬機中,并掛載運行,能正常訪問登陸界面,且輸入用戶名密碼也能正常登錄后臺。

5.3 仿真問題匯總

本章講述仿真過程中在文件、設備中出現的問題以及解決方案

5.3.1 文件

進程在執(zhí)行時需要進程本身的可執(zhí)行文件、可執(zhí)行文件依賴的動態(tài)鏈接庫文件、用于配置程序的配置文件,以及用于寫入臨時文件、日志文件、進程當前信息的目錄等文件與目錄環(huán)境。在仿真時通常會通過加載原本固件的文件系統(tǒng)的方式來構建文件系統(tǒng)的運行環(huán)境,但是設備固件并不遵循統(tǒng)一的標準,提取出的文件系統(tǒng)可能并不完整,會存在部分文件無法找到的情況。另外,有的文件是設備在運行時動態(tài)創(chuàng)建的,簡單的文件系統(tǒng)提取并不能獲取對應的文件。

我們總結了問題的解決方法,其中最關鍵的方法就是根據報錯信息定位報錯點,再一步步修復即可。以下是幾個常見的案例:

如下圖中缺失文件,只需要對應路徑創(chuàng)建文件。

從文件讀取的內容不匹配無法完成正常的跳轉,此時需要手動修改文件內容填入正確的值。

5.3.2 設備

物聯(lián)網設備通常需要大量的外部硬件設備參與運行,主要是運算與控制設備、網絡設備、存儲設備與輸入輸出設備。模擬器僅對常見的硬件設備進行了支持,其中包含了運算與控制設備、部分內存與磁盤設備、部分輸入輸出設備。但是物聯(lián)網設備中存在著大量的定制外部設備,如定制的NVRAM、Flash存儲設備、網絡設備等,在執(zhí)行到和這些設備相關的系統(tǒng)調用時,可能會面臨缺少輸入輸出設備與網絡設備,設備的硬件調用得不到宿主機支持等問題。

下圖是程序與nvram的交互流程:程序加載動態(tài)鏈接庫,動態(tài)鏈接庫根據標準用戶庫中的標準輸入輸出相關的函數構造對應的系統(tǒng)調用轉發(fā)到內核層,內核根據系統(tǒng)調用對應執(zhí)行設備驅動中的代碼。

對于缺少nvram的問題,有以下幾種解決方案:

  • 自定義動態(tài)鏈接庫在軟件層劫持相關的調用,通過預加載的方式通過該鏈接庫控制對硬件的調用,當程序調用對應函數的時候,會優(yōu)先調用自定義的動態(tài)鏈接庫,從而模擬NVRAM功能,使仿真程序正常運行
  • 通過調試的方式:

在nvram相關函數返回數據后,手動修改寄存器,給與正常的數據使仿真程序正常運行

強行修改跳轉,使仿真程序繼續(xù)運行

  • 自定義內核模塊的方式來實現虛擬的設備:在Linux操作系統(tǒng)中,硬件設備也被看做文件來處理,有對應的文件標準操作。根據驅動定義標準設計內核模塊,對于每一種設備,以內核驅動的方式,模擬實現文件的標準操作,通過定制內核模塊完成外部設備的軟件形式實現

當然,解決方案不恒定,需要根據實際情況思考并使用。

0x06 總結

本文系統(tǒng)性講解了固件仿真的概念、技術、工具和框架,并從用戶態(tài)、系統(tǒng)級2個角度進行了實際的手動仿真實踐。仿真過程中會遇到一些文件、設備等方面的問題和錯誤,本文也給出了相應的解決方案。

希望各位讀者朋友讀完此文能有所收獲!

0x07 參考文章

[1]https://blog.lyle.ac.cn/2021/07/09/uemu/

[2] https://www.freebuf.com/sectool/264053.html

[3] https://www.ics-cert.org.cn/portal/page/121/8b078dd28bcf42dfaf894e585d880cea.html

[4] https://www.freebuf.com/sectool/264053.html?


當前文章:物聯(lián)網終端安全入門與實踐之玩轉物聯(lián)網固件
當前地址:http://www.5511xx.com/article/djhohso.html