標籤:

以DVRF(路由器漏洞靶機)為例解讀JEB固件漏洞利用

在本文中,我將介紹JEB的MIPS反編譯器是如何幫助你查找和利用嵌入式設備中的軟體漏洞。為此,我將使用由@b1ack0wl編寫的DVRF。

DVRF

DVRF(Damn_Vulnerable_Router_Firmware) 是一個基於路由器Linksys E1550的路由器固件,裡面包含了開發者寫的一些存在漏洞的二進位文件,可以在路由器中安裝該固件進行安全測試。

DVRF模擬了一個比較真實的環境,比較適合初學路由器漏洞挖掘,不過前提是對其他CPU架構(MIPS)有一個基本的了解。

對於有興趣挑戰的讀者,我建議你遵循DVRF教程,並獲得完整的MIPSEL Debian QEMU映像,因為該映像可以在Linux上使用常用的漏洞開發利用工作流程,而不會對可用工具產生任何限制。

JEB

JEB是一個功能強大的為安全專業人士設計的Android應用程序的反編譯工具。用於逆向工程或審計APK文件,可以提高效率減少許多工程師的分析時間。具有以下4大特點:

1.全面的Dalvik反編譯器

JEB的獨特功能是,其Dalvik位元組碼反編譯為Java源代碼的能力。無需DEX-JAR轉換工具。

2.交互性

分析師需要靈活的工具,特別是在處理混淆的或受保護的代碼塊時。JEB的強大的用戶界面,使你可以檢查交叉引用,重命名的方法,欄位,類,代碼和數據之間導航,做筆記,添加註釋,以及更多。

3.可全面測試APK文件內容

檢查解壓縮的資源和資產,證書,字元串和常量等。追蹤你的測試進展情況。

不會讓以前研究的工作付諸東流,可以保存你的分析,對JEB資料庫文件,通過JEB的修訂歷史記錄機制和跟蹤進展。

4.多平台

JEB支持Windows,Linux和Mac OS。

漏洞利用環境設置

首先,我從二進位解壓縮固件中提取二進位文件。我先對第一個文件做一些分析:

載入到JEB後,我可以看到幾個有趣的功能:

在一些經典的libc有趣的常式中(system,strcpy……),我注意到了被命名為「dat_shell」的函數。

正如上圖所顯示的,此函數可以幫你解決問題,並通過調用系統產生一個shell。現在,我要將執行流重定向到dat_shell函數。接下來,我看到二進位調用「strcpy」,這可能只是緩衝區溢出。如下圖所示,通過檢查main函數,我發現strcpy被調用。

原因有三:

首先,它會檢查我是否提供了命令行參數;

其次,它會將用戶輸入複製到局部變數中,並列印輸入的內容;

最後,它會告訴我「再試一次」然後返回。幸運的是,strcpy不檢查其輸入大小,否則,將導致棧緩衝區溢出。

構建利用

和x86二進位程序中的情況類似,我會先用一個大的參數運行調試器中的二進位文件來驗證是否會發生溢出。

為此,我在我的QEMU VM上啟動了一個gdbserver,並使用JEB的調試器介面(參見調試手冊了解更多信息)。在MIPS ISA中,來自常式調用的返回地址存儲在名為$ra的特定寄存器中,該寄存器也通過棧填充,就像通常在x86上看到的那樣,然後跳轉到保存的返回地址。

在我的二進位文件中,我通過提供一個大的參數(一系列0x4F位元組)來確認返回地址是可以被用戶控制的,並在strcpy調用後顯示寄存器狀態:

我檢查了以下我重構的棧框架,以計算適當的填充。你可以使用你選擇的函數中的Ctrl+Alt+k快捷方式訪問該視圖。我將變數buf的類型更改為變數開始和下一個之間的所有可用大小的char數組,其中有200位元組。

實際上,變數var04和var08是保存的返回地址和主函數保存的幀指針。結果發現,這個偏移量是204位元組,因為我用200位元組填充緩衝區,並用另外四個字元覆蓋保存的幀指針。讓我嘗試以下漏洞:

#!/usr/bin/pythonn npadding = "O"* 204n ndat_shell_addr = "x50x09x40" # Partial overwrite with little-endian archn npayload = padding + dat_shell_addrn nwith open("input", "wb") as f:n nf.write(payloadn

漏洞利用過程

令人驚訝的是,我的虛擬攻擊使位於地址0x400970中的程序segfaults出現在dat_shell常式中。來看看JEB中的這個地址:

我可以在上圖中看到地址的存儲器訪問嗎,該地址是通過將偏移量0x801C添加到全局指針寄存器$gp而計算出的結果。但這裡的問題是$gp最初設置在$t9寄存器的程序開頭(見上圖的0x4000958)。

那麼$t9中的值來自哪裡?通常在MIPS(調用約定)上調用常式:$t9寄存器首先設置為目標常式的地址,然後再傳達到例如jalr $t9指令(請參閱MIPS ISA 的第50頁)。全局指針$gp然後用$t9進行初始化,用於計算各種偏移量,特別是將調用的其他函數,因此必須保證絕對正確。

換句話說,如果$t9的值在執行此常式時不是dat_shell的地址,則在常式執行期間存在無效內存訪問的可能性就會變得很大。為了構建一個成功的漏洞利用,我需要先從棧中載入任意值到$t9,然後再進行傳遞,因為它是一個真正的函數調用。

為了做到這一點,我需要一個「gadget」,在搜索這個gadget時,我首先檢查使用「libs」調試器命令載入的動態庫。

幸運的是,我有三個庫以固定的內存地址載入:libc.so.0,libgcc_s.so.0和ld-uClibc.so.0。

JEB的ROP Gadget查找插件

使用Gadget是構建返回導向編程技術(Return-Oriented Programming,ROP)漏洞的常見方法,所以我決定開發一個Gadget查找插件。而且,我不是從本機指令中搜索Gadget,而是決定使用JEB中間表示(IR),例如我可以公開的在JEB處理的所有架構上找到Gadget。

最終的結果是,當在JEB中載入libc.so.0,libgcc_s.so.0和ld-uClibc.so.0庫時,該插件會創建一個包含所有Gadget的視圖:

輸出沒有重複的Gadget,按字母順序排列,以方便查找有趣的Gadget。

那麼,它是如何工作的?使用JEB的API,插件將本機代碼轉換為我的反編譯管道第一階段使用的IR。在這個階段,本地指令的所有缺點都被暴露出來了,並且還沒有進行優化。

要查找Gadget,以分支結尾的一系列指令,我只需在程序計數器寄存器中搜索指定並向後迭代,直到該寄存器上的另一個賦值為止。最後一步是過濾掉相對轉移,不過這一步在漏洞利用中是不可能真正控制的。這樣我就得到了一個很好的ROPGadget列表。

同樣,因為它僅使用IR是,所以該方法適用於所有架構。例如,以下就是運行在ARMv7二進位文件的相同代碼:

公開的代碼可以在這裡找到。

現在在libc庫使用我剛剛找到的插件,我發現以下Gadget在偏移0x6b20處:

它將棧頂部的值複製到$t9寄存器中,並分支到$t9寄存器。

因此,該方法就是使用易受攻擊的strcpy來首先執行這個Gadget,這樣dat_shell地址將被調用為正常的常式調用。在我的測試設備上停用地址空間布局隨機化(ASLR)後,我可以使用之前找到的libc基地址進行漏洞利用。最後的漏洞看起來像這樣:

現在開始漏洞利用。

至此為止,我利用我的JEB ROPGadget查找器已在第一個棧緩衝區成功實現了溢出。下面,讓我們來看看第二和第三個緩衝區溢出。

第二緩衝區溢出過程與第一個一樣,首先進行漏洞利用環境設置

首先對文件進行分析:

接下來,我會檢查主要函數。

它看起來與第一個緩衝區溢出幾乎完全相同,只有在strcpy()調用中會出現不同的緩衝區大小。在確認我沒有獲取相關函數後,我可以重定向執行。

構建利用

由於棧是可執行的,藉助易受攻擊的strcpy(),我可以寫一個相當大的緩衝區(508位元組)。

首先,我從shellstorm中獲取了一個MIPS shellcode,然後我將它翻譯成了little-endian,這是為MIPSEL編譯的目標二進位文件。接下來,我需要找到跳轉的確切的棧地址。為了簡化進程,我決定在shellcode前添加 NOP sled前綴。

為了構建NOP sled,我不能簡單地使用MIPS NOP指令,因為它已被編碼為四個空位元組,因此不能用strcpy()複製。使用Keystone彙編器,我搜索了一個等效的指令,最後使用xor$ t0,$t0,$t0,其編碼不包含空位元組。

我只需要將所有的部分合併在一起,就會有完整的漏洞利用代碼:

可以看到shellcode已成功執行,現在我有一個shell!

第三個緩衝區溢出

類似於第二個緩衝區溢出,但是涉及一個用開放的網路socket來接收用戶輸入:

它以常用的socket樣板代碼開始,並綁定在指定為命令行參數的埠上。接受連接後,它將讀取500位元組,並發回用500位元組輸入格式化的字元串「nom nom nom, you sent me %s」。

該漏洞來自很小的sprintf()緩衝區,它只有52個位元組長,如你在JEB stackframe中看到的那樣:

我的策略與之前的漏洞類似,不過shellcode將是一個反向shell。

幸運的是,Jacob Holcomb已經對該方法有了詳細的介紹,唯一的缺點是它連接到的IP是硬編碼的:

為了方便使用這個shellcode,我添加了一條不能指向127.0.0.1或任何包含空位元組的IP地址的指令。為了確保它的工作原理和調試偏移量,我會在JR $RA指令之前設置斷點(Ctrl+B)並逐步用我的shellcode來運行JEB調試器中的漏洞。

然後我可以使用stepo調試器命令(或使用F6快捷方式),跳轉到內存代碼。

讓我在埠31337上啟動一個帶有netcat的監聽socket,並確認有一個shell:

本文編譯自pnfsoftware.com/blog/fipnfsoftware.com/blog/fi,如若轉載,請註明原文地址: 4hou.com/technology/738 更多內容請關注「嘶吼專業版」——Pro4hou

推薦閱讀:

鎮守最後一道防線:三種逃逸沙盒技術分析
現在優秀信息安全的公司招實習生標準是什麼?
發現隱藏在偽造的Flash更新中的持續威脅
黑客是怎麼一步步解鎖你被盜的iphone

TAG:信息安全 |