原文:Art of Anti Detection 2 – PE Backdoor Manufacturing
譯者:MyKings@知道創宇404實驗室
前文回顧:反檢測技術之反病毒檢測

本文主要講述在網絡攻防演練中紅隊如何在PE(Portable Executable)文件中放置后門的幾種方法。為了讓讀者能夠充分掌握本文的內容,您需要具有中級x86匯編知識,并熟悉調試器與PE文件格式。

1. 背景說明

目前幾乎所有的安全研究人員、滲透測試人員和惡意軟件分析師每天都在處理后門程序,將后門放置到系統或具體某個應用程序是一種較為常見的攻擊方式。

本文的大部分內容是關于將后門植入32位PE文件的方法, 但由于PE文件格式是Unix COFF(Common Object File Format, 通用對象文件格式)的修改版本,所以這些方法也可以用于其他可執行二進制文件類型。

此外,后門的隱蔽性尤為重要,這里也會分析一些反檢測技術的方法。在閱讀本文之前,您可以先閱讀 Introduction To AV & Detection Techniques (反檢測技術之反病毒檢測) , 這將有助于您了解反病毒產品的內部工作原理和反檢測技術的基本思想。

2. 專業術語

紅隊(Red Team Pentesting):

在網絡攻防演練中,紅隊是由一群白帽黑客組成,作為攻擊者負責攻擊組織(通常為藍隊)的數字基礎設施,以測試組織的防御能力(通常稱為“滲透測試”)。

其好處體現在先入為主的觀念與挑戰,發現更多的潛在威脅減少安全問題。其次可更準確地了解敏感信息是如何被泄漏的,以及可利用的模式。目前包括微軟在內的一些公司會定期進行紅隊與藍隊的網絡對抗演練。

圖片譯者添加

地址空間布局隨機化(ASLR):

ASLR 是一種針對緩沖區溢出的安全保護技術。為了防止攻擊者能夠直接定位內存中攻擊代碼位置,ASLR 隨機排列進程的關鍵數據區域的內存地址,如: 可執行文件的基址、棧、堆和庫的位置。

代碼洞(Code Caves):

Code Caves是由另一個程序寫入另一個進程的內存的一段代碼。這段代碼可以通過在目標進程內創建遠程線程來執行。代碼的Code Caves通常是對代碼的腳本函數的一部分的引用,該腳本函數具有注入自定義指令的能力。例如,如果腳本的內存允許5個字節,并且只使用3個字節,則剩余的2個字節可以用于向腳本添加外部代碼, 這就是所謂的代碼洞。

校驗和(Checksum):

校驗和是來自數字數據塊的小尺寸數據,用于檢測在其傳輸或存儲期間可能引入的錯誤。它通常從遠端服務器下載到本地接收到之后應用于安裝文件。通過自身,校驗和通常用于驗證數據完整性,但不依賴于驗證數據的真實性。

譯者注: "校驗和" 是冗余校驗的一種形式。 它是通過錯誤檢測方法,對經過空間(如通信)或者時間(如計算機存儲)傳送的數據的完整性進行檢查的一種簡單方法。計算機領域常見的校驗和的方法有: CRC、MD5、SHA家族等。

3. 基本流程

本文中將通過 putty.exe 這個SSH客戶端來做示例演示。這里使用putty的主要原因有如下幾個:

  • putty 客戶端是一個使用多個庫和 Windows API 的本地 C++ 項目;
  • SSH客戶端的后門吸引較少關注,因為程序主要就是執行TCP連接,這將更容易避免藍色團隊網絡監控。

這個后門代碼將使用 metasploit 項目中 Stephen Fever’s 開發的TCP反向鏈接的 ShellCode。 主要將 ShellCode 注入目標PE文件中,并且不影響程序的正常功能。注入的 ShellCode 將在一個新的線程上執行,并不斷地嘗試連接到控制端。完成以上目標后我們還要做一些免殺, 來減少被檢測到的風險。

大致流程主要分以下四個步驟:

  • 完成可用空間的后門代碼(添加區段)
  • 劫持執行流程
  • 注入后門代碼
  • 恢復執行流程

在每一個步驟中都有一些關鍵操作, 這些細節保證了后門的隱蔽與降低被檢測到的風險。

4. 可用空間問題

第一步我們需要找到可用空間,如何在PE文件中選擇合適的空間來插入后門代碼非常重要, 這將影響到后門被檢測到的風險系數。 有如下兩種方法解決空間大小問題:

4.1 添加新區段

與其他方法相比,這種方法容易被檢測引擎檢測到,但另一個好處是附加了一個新的區段,對于將被植入的后門代碼沒有空間限制。

使用一個匯編程序或PE編輯器(如LordPE),所有的PE文件可以添加一個新的段頭,這是 putty 可執行文件的節表,借助PE編輯器添加了一個 "NewSec" 區段, 大小為 1000 字節,

當創建一個新的區段時,將段標志設置為 “讀/寫/執行” 對于當PE映像映射到內存時運行后門 ShellCode 至關重要。

在添加段頭之后,需要調整文件大小,這可以通過在十六進制編輯器中添加空文件和文件末尾的段大小來實現。

在這些操作之后,新的空段被成功地添加到PE文件中,運行修改后的 putty 文件,如果正常運行, 則新段可以在調試器上被修改。

為了解決空間問題,我們添加一個新的區段,但是幾乎所有的AV產品都能識別不常見的區段,同時給一個不常見的區段所有(讀/寫/執行)權限肯定是非常可疑的。即使向putty可執行文件添加空的完整權限,也會被某些AV產品標記為惡意。

4.2 代碼洞(Code Caves)

解決空間問題的第二種方法是使用目標可執行文件的Code Caves。幾乎所有編譯的二進制文件都有Code Caves,可以在進行后門操作時使用。使用Code Caves而不是新添加的區段的方法將降低被AV產品檢測的風險,因為使用已經存在的公共部分。此外,PE文件的總體大小在添加后門結束時不會被改變,但是該方法也具有缺點。

Code Caves的數量和大小根據文件的不同而不同,與添加區段比通常沒有太多的空間。當使用Code Caves時,后門代碼應盡可能短小。另一個缺點是段標志, 由于應用程序的執行將被重定向到 Caves,包含 Caves 的部分應該具有 “execute” 權限,甚至一些shellcode(以自修改的方式編碼或混淆)也需要 “write” 權限,以便進行更改里面的區段。

使用多個Code Caves將有助于克服空間限制問題,也將后門代碼分割為塊同時降低了被AV檢測的風險,但不幸的是更改段特權將看起來可疑。有一些高級方法可以修改運行時的內存區域權限,來避免直接更改段權限,但由于這些方法需要定制的 ShellCode 編碼和IAT解析技術,它將在下一篇文章中來介紹。

借助于一個名為Cminer的工具,很容易枚舉二進制文件的所有代碼洞,./Cminer putty.exe 300 命令枚舉Code Caves大于300字節。

在這種情況下,有5個好的Code Caves可以使用。起始地址給出了Caves的虛擬內存地址(VMA)。這是Caves的地址,當PE文件加載到內存中時,文件偏移量是以字節為單位的PE文件內的Caves地址。

看來大部分Caves都在數據段內,因為數據段沒有執行特權段標志, 這里需要更改。后門代碼將在400-500字節左右,所以5個Caves應該是足夠的。Caves的起始地址應該被保存,在將段特權更改為R/W/E后,第一步的后門過程就完成了。

下面開始需要重定向執行的時候了。

5. 劫持執行流程

在此步驟中,我們目的是通過修改目標可執行文件的指令將執行流重定向到后門代碼。這里有一個關于選擇將被修改的指令重要細節, 所有二進制指令具有字節大小,為了跳轉到后門代碼地址,將使用5或6字節的長跳躍。 因此,當修補二進制時,將被修補的指令需要與長跳轉指令的大小相同,否則上一條或下一條指令將被破壞。

選擇適當的空間來重定向執行對于繞過AV產品的動態檢測和沙箱分析機制是非常重要的。如果直接發生重定向,則可能在AV的動態掃描分析階段就被檢測到。

隱藏在用戶交互下:

繞過沙盒與動態分析階段的第一件事是延遲ShellCode的執行或設計沙箱感知和觸發機制。 但在添加后門時,大多數時候沒有這么多的空間用于在PE文件中添加這些額外的代碼。在匯編級語言中設計防檢測機制這需要大量的時間和知識。

該方法主要是利用與用戶交互來執行操作的功能, 作為一個觸發機制,當一個用戶操作程序時激活后門代碼。如果這個方法可以正確實現,它將有100%的成功率,而且不會增加后門代碼的大小。

putty啟動后的界面中, 點擊 “Open” 按鈕會啟動一個檢查IP地址是否有效的功能。

如果IP地址字段值不為空并且有效,則它啟動嘗試連接給定IP地址的連接功能。如果客戶端成功創建SSH會話,將彈出一個新窗口并請求憑據,

這將是重定向發生的點,因為AV產品不能夠復制這種復雜的環境,植入的后門將不會被自動化沙盒和動態分析機制檢測到。

使用基本的逆向方法,搜索下面的字符串和字符串引用,將不難找到連接函數的地址。客戶端建立與給定IP的連接后,有一個字符串 “login as:” 打印到出現的窗口。 這個字符串將幫助我們找到連接函數的地址,IDA Pro在這方面做得很好。

為了找到 “login as:” 字符串, 在IDA上依次打開 Views->Open Subviews->Strings

找到字符串后,雙擊轉到所在位置,在數據節內部IDA查找所有對字符串的交叉引用,按 “Ctrl+X”,它顯示所有交叉引用,這個引用在打印 “login as:” 字符串的函數內部。

這將是要修補的指令,在進行任何更改之前,請注意上下文的指令。 執行后門代碼后,將再次使用。

通過將PUSH 467C7C指令改為JMP 0x47A478,完成后門過程的重定向階段。 重要的是注意下一個指令地址。它將在執行后門代碼后用作返回地址。

接下來將是注入后門代碼的環節。

6. 注入后門代碼

在注入后門代碼時,首先需要做的是在執行后門之前保存寄存器中的內容。所有寄存器中的每個值對于程序的執行是非常重要的。通過在代碼的OEP(程序入口點)放置PUSHEDPUSHED指令,所有寄存器內的值和寄存器標志都存儲在堆棧中。 這些值將在執行完后門代碼之后彈出,以便程序可以繼續執行而沒有任何問題。

如前所述,使用的后門代碼是來自metasploit項目的meterpreter反向TCP ShellCode。但是在ShellCode中需要做少量修改。 通常,反向TCP ShellCode會有嘗試連接到處理程序的次數或時間限定,如果連接失敗,則通過調用ExitProcess API調用關閉進程。

這是問題的所在,如果連接到處理程序失敗,putty客戶端的執行將停止。改變幾行ShellCode使其每次連接失敗時ShellCode將重試連接到處理器,這樣也會相應的減少ShellCode的體積。

在匯編代碼中進行更改后,使用nasm -f bin stager_reverse_tcp_nx.asm命令進行編譯。現在反向的TCP ShellCode已經可以使用了,但是它不會被直接放置, 我們的目標是在新線程上執行ShellCode。 為了創建一個新的線程實例,需要另一個ShellCode,使CreateThreadAPI調用指向反向TCP ShellCode。這里使用Metasploit項目中創建線程的ShellCode

如上, 將 createthread.asm 文件中的代碼轉換為十六進制格式的ShellCode,使用nasm -f bin createthread.asm命令進行編譯。在這里,ShellCode準備插入到Caves中,但在插入ShellCode之前,它應該被編碼以便繞過AV產品的靜態/特征分析機制。因為Metasploit項目中的所有編碼器被大多數AV產品所知,所以強烈建議使用自定義編碼器。 本文不會覆蓋這種自定義ShellCode編碼器的制作,它將在下一篇文章中介紹到,這里還可以使用多個Metasploit編碼器來工作。在每個編碼過程完成之后,將編碼的ShellCode上傳到線上的病毒檢測站點,根據檢測分數。 嘗試每個組合,直到它不被檢測到或等待下一篇文章。

在正確編碼ShellCode之后,就可以把它插入Code Caves。選擇在PUSHFD下的指令,然后在免調試器上按下 “Ctrl + E”,ShellCode將以十六進制格式粘貼。

使用xxd -ps createthread命令,以十六進制格式打印編碼創建線程的ShellCode或使用十六進制編輯器打開ShellCode并復制十六進制值。當將十六進制值粘貼到調試器時,請注意字節限制,這些修補操作是用免試器進行的,免調試器在粘貼到編輯代碼窗口時有一個字節限制。 它不會粘貼所有ShellCode,記住粘貼的ShellCode的最后2個字節在編輯代碼窗口內,按下OK按鈕后繼續粘貼字節,當所有ShellCode粘貼到Code Cave時后門代碼就插入完了。

7. 恢復執行流程

在創建后門代碼線程之后,程序需要恢復到其正常執行流程,這意味著EIP應該跳回到將執行重定向到Cave的函數。但是在跳回到該函數之前,應該檢索所有保存的寄存器。

通過在ShellCode的末尾放置POPFDPOPAD指令,所有保存的寄存器都以相同的順序從堆棧中彈出。在檢索寄存器后,還有一件事要做,執行被劫持的指令。為了將程序的執行重定向到Code Cave, 我們將PUSH 467C7C指令替換為了JMP 0x47A478。 現在把PUSH 467C7C指令放在最后,被劫持的指令也被檢索。現在是返回到通過插入JMP 0x41CB73指令將執行重定向到Cave的函數的時候了,結果代碼應該如下圖所示。

最后選擇所有修補和插入的指令,按右鍵單擊并復制到可執行文件。此操作應對已修改的每個指令執行。當所有指令被復制并保存到文件時,關閉調試器并測試可執行文件,如果可執行文件運行順暢,則后門可以使用。

最后,建議固定最終文件校驗和,以保持文件的真實性,而不是看起來可疑,這也可能對降低檢測分數有影響。

8. 總結與預防措施

最后,當所有操作都正常完成后,產生的后門是完全不會被檢測到的。針對以上的兩種代碼注入方式,下面給出這些相應技術的對策,這些策略可以幫助系統管理員、惡意軟件記錄器、反病毒與反惡意軟件產品的開發人員。

8.1 區段特權控制

當談論后門文件時,區段的特權對于檢測異常是非常重要的,編譯器永遠不會設置對區段的完全權限,除非開發人員強制添加。特別是像.data.rdata這樣的數據段不應該有執行權限,類似.text的代碼段不應該有寫權限,這些異常應該被認為是可疑的行為。

8.2 不常見區段識別

如果開發人員不進行任何配置, 編譯器通常創建5-6個通用類型的區段,所有安全產品應該具有識別不常見和可疑段的機制,這種機制可以尋找段內的熵和數據對齊,如果一個段包含高熵和異常排序的數據,它應該被認為是可疑的。

8.3 簽名檢查

這種對策非常經典,也是最有效的,當下載一個新的程序或任何一塊可執行文件,檢查sha1簽名來驗證程序是否被修改。

8.4 檢查文件校驗和

當內部鏡像和文件的實際校驗和的值之間存在差異時,這表明該文件已被修改過,安全產品和系統管理員應計算實際校驗和并與鏡像頭比較,來檢查文件的真實性。

9. 原文鏈接

  • http://NoDistribute.com/result/image/Ye0pnGHXiWvSVErkLfTblmAUQ.png
  • https://github.com/secretsquirrel/the-backdoor-factory
  • https://www.shellterproject.com/
  • https://en.wikipedia.org/wiki/Red_team
  • https://en.wikipedia.org/wiki/Address_space_layout_randomization
  • https://en.wikipedia.org/wiki/Code_cave
  • https://en.wikipedia.org/wiki/Checksum

10. 譯者參考

  • https://ccdcoe.org/publications/LockedShields13_AAR.pdf

Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/264/