超級任天堂(SNES,Super Nintendo Entertainment System)是任天堂全球知名主機NES(國內稱為小霸王)的後續主機,主機採用16位色表現,令主機的畫面表現在當時非常之棒。而作為當時的主機霸主,任天堂SNES主機上出現了非常多經典的遊戲,現在大紅大紫的遊戲系列很多都是在SNES上發跡的。像勇者斗惡龍系列、傳說系列、最終幻想系列、超時空之輪系列等等。當年的超級任天堂憑藉全球數千萬台的銷量一直佔據著遊戲機市場的鰲頭,在這個優秀的平台上,誕生過無數優秀的精品遊戲,很多作品即使拿到現在與PS2,XBOX的遊戲相比在遊戲性方面也毫不遜色(其實是比他們還要好很多)。如果你對那些令人激動的遊戲念念不忘的話,而Snes9x可以在你的電腦上網模擬超級任天堂,讓你再次回到童年。軟體可根據不同硬體方便的調節聲音,圖像等。

上圖中的那個程序是一個 SNES 模擬器,很多遊戲愛好者都使用過它。從網上找到這些東西並不難,但我不會在文章里說,因為從技術上講,這麼做屬於傳播盜版。
首先,我拿出舊的外部硬碟,找到了我的SNES9x模擬器的壓縮副本,啟動它,就發現了一個 DLL 劫持漏洞。
Snes9x是款讓你重溫童年遊戲的SNES模擬器,能夠在Windows平台上運行經典SNES/SFC遊戲的模擬器軟體,支持.smc, .sfc, .fig, 和 .1等格式的遊戲,可用鍵盤,也能用手柄進行操作,支持鍵位修改。
以 x86 和 x64 架構編寫的程序利用動態鏈接庫 (DLL) 在軟體開發過程中提供靈活性和可移植性。 DLL 基本上是包含可重用代碼、資源和變數的小程序。就其性質而言,它們沒有入口點並且需要父級可執行文件在運行時調用它們。如果你只有一個 DLL,則可以使用 Rundll32.exe 之類的東西來運行該特定 DLL 的內容,而無需父級程序。否則,DLL 中的函數可以由父級可執行文件調用,使用 LoadLibrary API 調用將它們動態導入到程序中。
有時軟體開發並不完全按計划進行,並且你可能會經常編寫一個程序來調用載入一個不存在的 DLL。或者,在 SNES 模擬器的情況下,你可能會遇到相當於路徑漏洞的問題,這基本上意味著程序嘗試從當前工作目錄載入 DLL,然後在別處查找。
以下就是我載入Procmon並運行SNES模擬器時的情況:

在上圖中,SNES 模擬器已放置在我的 FlareVM 主機的桌面上。當程序嘗試載入opengl32.dll時,它首先檢查當前工作目錄C:UsersHuskyDesktopSNES32bit。當它在這裡找不到指定的 DLL 時,它會轉到SysWOW64目錄,並載入成功存在其中的DLL。這個SNES模擬器是一個32位應用程序,因此它檢查SysWOW64是否需要dll是有意義的。
注意,System32和SysWOW64有點像冰島/格陵蘭的情況。在標準的x64設備上,64位系統目錄是System32, 32位系統目錄是SysWOW64。
總之,這是一個漏洞。程序試圖從一個可以寫入的目錄中裝入DLL。這是因為該程序已被複制到桌面,而不是安裝在標準程序目錄中,例如「程序文件」。
這就很容易發生這個軟體被共享即從硬碟驅動器共享它,然後將文件複製到他們自己的筆記本電腦上。
另外,在這裡需要注意的是,SNES模擬器有DEP但沒有ASLR,將來可能會回到那個狀態。

現在在一些攻擊場景中,DLL劫持是通過以下方式實現的:只需要做一個MSFVenom DLL有效載荷,並將其替換為程序試圖載入4head的載荷即可。直到程序崩潰或無法載入:

DOS不在這個範圍內,要做得更好,可以進入DLL代理。
DLL 代理
DLL 代理實現 DLL 劫持的成功率更高。

你可能能夠從 DLL 劫持中獲得 shellcode 執行,但程序仍然需要解析它想要從原始 DLL 進行的函數調用。而且你的 MSFVenom 生成的 DLL 不知道如何處理這些請求的函數,所以calc.exe運行,程序崩潰。

在 DLL 代理中,你可以創建一個新的 DLL,其中包含指向原始 DLL 的導入函數的指針。有效載荷隱藏到這個DLL的一個部分中,並使用剩餘的空間將可執行文件指向它想要載入的原始DLL。
該程序以其原始預期功能執行,得到有效載荷執行。
使用 Procmon,過濾以下內容:

打開一個可執行文件或 10 並確定一個嘗試載入到 DLL 中但沒有成功的程序。在本文的示例中,我專註於 OpenGL32.dll:

重新配置過濾器,以查看該DLL是否在程序執行的任何時刻被成功載入。因此,只需過濾即可擴大你的搜索條件:

如果你已經找到一個好的DLL代理候選,你可能會看到如下內容:

可以看到,將成功載入的 DLL 從主機複製到攻擊者的設備上,並將其命名為 [dllName]_original.dll。幸運的是,這個DLL可能在所有Windows系統上都是本地的,因此你甚至可能不需要從目標主機複製它,只需從你自己的 Windows 主機複製它即可。
在攻擊者的設備上,使用這個簡單的Python腳本從原始DLL中取出導出的函數並將它們寫入一個模塊定義文件 (.def):

請注意引用原始DLL的兩個位置,並確保相應地更改這些值。

在編譯程序時,模塊定義文件向編譯器提供有關鏈接導出的信息。在本文示例中,我們將告訴編譯器創建代理DLL,並將它鏈接到原始DLL,以指向它導出的所有函數。

所以,每當可執行文件問「嘿,DLL,函數在哪裡?」代理DLL便回復到:「哦,是的,去檢查[dllName]_original.dll,它應該在那裡。」
現在,我們製作我們的代理 DLL。這是一個用 C 編寫得非常簡單的程序,它導出一個 DLLMain 函數作為 DLL 的入口點。在 DLLMain 方法中,我們偷偷調用了 Payload 函數。該函數執行,然後所有其他請求的函數調用都傳遞給 [dllName]_original.dll:
創建此 C 文件並將其命名為 [dllName].c:

到目前為止,一切順利。
最後,我們需要創建這個代理 DLL 並將它與我們的模塊定義文件鏈接起來。這可以通過 mingw-w64 來完成,它擁有編譯DLL所需的必要工具鏈。注意這裡的架構:我代理了32位SNES模擬器,所以我需要為32位架構編譯它。
如果你的攻擊設備上沒有 mingw-w64,只需輸入:

然後,編譯我們的 DLL:

當 DLL 編譯時,你現在應該有四個文件可以使用:

[dllName]_original.dll:我們從主機上拉下來的原始DLL,重命名為「_original」
[dllName].c:包含我們的有效載荷的代理 DLL 的 C 代碼。
[dllName].def:使用Python腳本從原始dll中提取導出的函數調用創建的模塊定義文件。
[dllName].dll:新編譯的代理DLL。
最後一步是將原始DLL和代理DLL在目標主機的程序目錄下登陸,這兩個 DLL 必須與彼此和原始程序位於同一目錄中。

找到兩個 DLL 後,啟動程序!

此時,已經有了一個載入到代理DLL中的功能完整的程序。沒有崩潰,沒有段錯誤,只有calc。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/221846.html
微信掃一掃
支付寶掃一掃