十種注入技巧 | 通用性進程注入技巧研究

進程注入是一種廣泛應用于惡意軟件和無文件攻擊中的逃避技術,這需要在另一個進程的地址空間內運行自定義代碼。進程注入提高了隱蔽性,一些技術也實現了持久性。 盡管有許多流程注入技術,在本博客中,我提供了十種在現實看到注入另一個進程運行惡意代碼的技術。 我還提供了許多這些技術的屏幕截圖,以便于逆向工程和惡意軟件分析,協助針對這些常見技術進行檢測和防御。

1. 經典的DLL注入方式:通過CREATEREMOTETHREAD和LOADLIBRARY進行注入

這種技術是用于將惡意軟件注入另一個進程的最常用技術之一。 惡意軟件將路徑寫入到其他進程的虛擬地址空間中的惡意動態鏈接庫(DLL),并通過在目標進程中創建遠程線程來確保遠程進程加載它。

圖 1

惡意軟件首先需要定位注入的進程(例如svchost.exe)。這通常通過調用三個應用程序接口(API)來搜索進程:CreateToolhelp32Snapshot,Process32First和Process32Next。
CreateToolhelp32Snapshot是用于枚舉指定進程或所有進程的堆或模塊狀態的API,它返回一個快照。

Process32First檢索快照中有關第一個進程的信息,然后在循環中使Process32Next來遍歷它們。

找到目標進程后,惡意軟件通過調用OpenProcess獲取目標進程的句柄。

如圖2所示,惡意軟件調用VirtualAllocEx有一段空間來寫入其DLL的路徑。

惡意軟件然后調用WriteProcessMemory寫入分配的內存中的路徑。
最后,為了讓代碼在另一個進程中執行,惡意軟件調用API,如CreateRemoteThread,NtCreateThreadEx或RtlCreateUserThread,后兩者是為文檔化的函數。

然而,一般的想法是將LoadLibrary的地址傳遞給這些API之一,以便遠程進程必須代表惡意軟件執行DLL。CreateRemoteThread被許多安全產品跟蹤和標記。
此外,它會在磁盤上的留下惡意DLL文件。考慮到攻擊者注入代碼的目的一般是防御,所以復雜的攻擊者可能不會使用這種方法。
下面的截圖顯示了一個名為Rebhip的惡意軟件便是利用了這種注入技巧。

圖 2 Rebhip 蠕蟲使用了經典的DLL注入方式

2. PE文件注入

惡意軟件不會傳遞LoadLibrary的地址,而是將其惡意代碼復制到現有的打開進程中,并使其執行(通過一個小的shellcode或通過調用CreateRemoteThread)。PE注入相比于LoadLibrary進行注入的一個優點是惡意軟件不必在磁盤上釋放惡意DLL。類似于第一種注入技術,惡意軟件在主機進程(例如VirtualAllocEx)中分配內存,而不是寫入“DLL路徑”,它通過調用WriteProcessMemory寫入其惡意代碼。然而,使用這種方法的缺陷是更改了復制映像的基址。當惡意軟件將其PE注入另一個進程時,它將具有不可預測的新基址,所以要求它動態地重新計算其PE的固定地址。為了克服這一點,惡意軟件需要在主機進程中找到其重定位表地址,并通過循環遍歷其重定位描述符來解析復制的映像的絕對地址。

圖 3

這種技術類似于其他技術,如反射式DLL注入和內存模塊加載,因為它們不會將任何文件釋放到磁盤。然而,內存模塊加載和反射式DLL注入方法甚至更加隱蔽。它們不依賴任何額外的Windows

API(例如,CreateRemoteThread或LoadLibrary),因為它們在內存中加載并執行自身。反射式DLL注入通過創建一個DLL,在執行時將自身映射到內存中,而不依賴于Window的加載器。內存模塊加載類似于反射式DLL注入,注射器或加載器負責將目標DLL映射到內存而不是DLL映射本身。在之前的一篇博文中,這兩種內存方法被廣泛討論。

在分析PE注入時,在調用CreateRemoteThread之前,看到循環(通常是兩個“for”循環,一個嵌套在另一個循環中)是很常見的情況。這種技術在crypter(加密和模糊惡意軟件的軟件)中非常受歡迎。在圖4中,樣本使用的便是這種技術。該代碼有兩個嵌套循環來調整其重定位表,可以在調用WriteProcessMemory和CreateRemoteThread之前看到它。 “and

0x0fff”指令也是另一個很好的標志,顯示前12位用于獲取到包含重定位塊的虛擬地址的偏移量。現在,惡意軟件已經重新計算了所有必需的地址,所有它需要做的是將其起始地址傳遞給CreateRemoteThread并將其執行。

圖 4 在調用CreateRemoteThread之前,PE注入的循環結構示例

3. 進程HOLLOWING (又名進程替換和RUNPE)

惡意軟件可以執行被稱為進程hollowing的技術,而不是將代碼注入宿主程序(例如,DLL注入)。進程hollowing 發生于惡意軟件從目標進程的內存中清空(鏤空)合法代碼并用惡意可執行文件覆蓋目標進程的內存空間(如,svchost.exe)之時。

圖 5

惡意軟件首先創建一個新進程,以掛起模式托管惡意代碼。如圖6所示,該程序通過調用CreateProcess并將流程創建標志設置為CREATE_SUSPENDED(0x00000004)完成。新進程的主線程被創建為掛起狀態,直到ResumeThread函數被調用才會運行。接下來,惡意軟件需要用惡意的有效載荷來替換合法文件的內容。這可以通過調用ZwUnmapViewOfSection或NtUnmapViewOfSection來取消映射目標進程的內存。這兩個API基本上釋放了一個部分指向的所有內存。現在內存被取消映射,加載器執行VirtualAllocEx為惡意軟件分配新內存,并使用WriteProcessMemory將每個惡意軟件的部分寫入目標進程空間。惡意軟件調用SetThreadContext將entrypoint指向已編寫的新代碼段。最后,惡意軟件通過調用ResumeThread來恢復掛起的線程。

圖 6 Ransom.Cryak實現進程hollowing

4. 線程執行劫持 (又名:掛起,注入,恢復 (SIR))

這種技術與先前討論的進程hollowing技術有一些相似之處。在線程執行劫持中,惡意軟件針對進程的現有線程,并避免任何嘈雜的進程或線程的創建操作。因此,在分析期間,您可能會看到對CreateToolhelp32Snapshot和Thread32First的調用,后跟OpenThread。

圖 7

在獲取目標線程的句柄后,惡意軟件通過調用SuspendThread來將線程置于掛起模式,最終執行注入。惡意軟件調用VirtualAllocEx和WriteProcessMemory來分配內存并執行代碼注入的操作。

該代碼可以包含shellcode,惡意DLL的路徑和LoadLibrary的地址。

圖8給出了使用這種技術的通用木馬程序。

為了劫持線程的執行,惡意軟件通過調用SetThreadContext修改目標線程的EIP寄存器(包含下一條指令的地址)。之后惡意軟件恢復線程來執行它已寫入主機進程的shellcode。

從攻擊者的角度來看,SIR方法可能是有問題的,因為在系統調用中暫停和恢復線程可能導致系統崩潰。為避免這種情況,更加復雜的惡意軟件如果遇到EIP寄存器在NTDLL.dll的范圍內的情況,將會恢復然后重試。

圖 8 一般的木馬正在執行線程執行劫持

5. 通過SETWINDOWSHOOKEX進行HOOK注入

Hooking是一種用于攔截函數調用的技術。惡意軟件可以利用掛鉤函數,在特定線程觸發事件時加載其惡意DLL。這項技術通常通過調SetWindowsHookEx函數來將鉤子例程安裝到鉤子鏈中來完成。

SetWindowsHookEx函數有四個參數。第一個參數是事件的類型。這些事件反映了鉤子類型的范圍,并且從鍵盤上的鍵(WH_KEYBOARD)到輸入到鼠標(WH_MOUSE),CBT等的不同。第二個參數是指向惡意軟件想要在事件中調用的函數的指針執行。第三個參數是包含該函數的模塊。因此,在調用SetWindowsHookEx之前,看到對LoadLibrary和GetProcAddress的調用是非常常見的。該函數的最后一個參數是掛鉤過程與之關聯的線程。如果此值設置為零,則所有線程在觸發事件時執行操作。然而,惡意軟件通常針對一個線程來減少干擾,因此也可以在SetWindowsHookEx之前查看調用CreateToolhelp32Snapshot和Thread32Next來查找和定位單個線程。一旦DLL被注入,惡意軟件代表其線程id被傳遞給SetWindowsHookEx函數的進程執行其惡意代碼。在圖9中,Locky
Ransomware實現了這種技術。

圖 9 Locky Ransomware 的hook注入過程

6. 通過修改注冊表進行注入以及維持注入 (例如APPINIT_DLLS, APPCERTDLLS, IFEO)

惡意軟件可以使用Appinit_DLL, AppCertDlls, 以及 IFEO (映像劫持)這三個注冊表項可以用于注入和維持注入,這三個注冊表項具體的位置如下:

AppInit_DLLs

惡意軟件可以將其惡意dll文件的位置插入到Appinit_Dlls注冊表項下,以使其他進程加載這個dll文件。

此注冊表項下的每個dll文件都會隨著User32.dll的加載而同樣加載到進程中。
User32.dll是用于存儲圖形元素(如對話框)的非常常用的庫。 因此,當惡意軟件修改這個注冊表子項時,大多數進程都將加載惡意dll文件。

圖10顯示了木乃伊依賴這種技術進行注入和維持注入的方法。
它只需打開Appinit_Dlls注冊表項,方法是調用RegCreateKeyEx,并通過調用RegSetValueEx來修改它的值。

圖 10 Ginwui修改AppIniti_DLLs注冊表項

AppCertDlls

這種方法與AppInit_DLLs方法非常相似,只是將此注冊表項下的DLL加載到調用CreateProcess,CreateProcessAsUser,CreateProcessWithLogonW,CreateProcessWithTokenW和WinExec的每個進程中。

映像劫持 (IFEO)

IFEO通常用于調試目的。開發人員可以在此注冊表項下設置“調試器值”,將程序附加到另一個可執行文件進行調試。
因此,每當啟動可執行文件時,將附加到該程序。 要使用此功能,您可以簡單地給出調試器的路徑,并將其附加到要分析的可執行文件。
惡意軟件可以修改此注冊表項以將其注入到目標可執行文件中。 在圖11中,Diztakun木馬通過修改任務管理器的調試器值來實現此技術。

圖11 : Diztakun木馬修改IFEO注冊表項

7. APC 注入以及 AtomBombing內存注入

惡意軟件可以利用異步過程調用(APC)控制另一個線程通過將其附加到目標線程的APC隊列來執行其自定義代碼。

每個線程都有一個APC隊列,它們在目標線程進入可警醒狀態時等待執行。如果調用SleepEx,SignalObjectAndWait,MsgWaitForMultipleObjectsEx,WaitForMultipleObjectsEx或WaitForSingleObjectEx函數,線程將進入可警醒狀態。

惡意軟件通常會查找處于可警醒狀態的任何線程,然后調用OpenThread和QueueUserAPC將APC排隊到線程。QueueUserAPC有三個參數:1)目標線程的句柄;
2)指向惡意軟件想要運行的函數指針; 3)和傳遞給函數指針的參數。
在圖12中,Amanahe惡意軟件首先調用OpenThread來獲取另一個線程的句柄,然后使用LoadLibraryA調用QueueUserAPC作為函數指針,將其惡意DLL注入另一個線程的APC隊列中。

AtomBombing是一種首先由enSilo研究引入的技術,然后用于Dridex V4。 正如我們在前一篇文章中詳細討論的[譯者注:鏈接見文末],該技術也是依賴APC注射。 但是,它是使用atom表寫入另一個進程的內存。

圖12: Almanahe執行APC注入

8. 通過SETWINDOWLONG 進行窗口內存注入 (EWMI)

EWMI依靠注入資源管理器托盤窗口的額外窗口內存,并在惡意軟件家族中被多次使用使用,如Gapz和PowerLoader。在注冊窗口類時,應用程序可以指定一些額外的內存字節,稱為額外的窗口存儲器(EWM)。

然而,EWM并不算是塊很充裕的空間。

為了規避這個限制,惡意軟件將代碼寫入explorer.exe的共享部分,并使用SetWindowLong和SendNotifyMessage來指定一個指向shellcode的函數指針,然后執行它。

圖13 PowerLoader注入托盤窗口的額外窗口內存

當涉及到向共享部分的寫入數據時,惡意軟件有兩個選擇:它可以也創建一個共享空間,并將其映射到自身和另一個進程(例如,explorer.exe);第二個選擇就是簡單地打開已經存在的共享部分。

前者具有分配堆空間和調用NTMapViewOfSection以及其他一些API調用的開銷,因此后一種方法被更頻繁地使用。

惡意軟件在共享部分中寫入其shellcode后,使用GetWindowLong和SetWindowLong訪問并修改“Shell_TrayWnd”的額外窗口內存。

GetWindowLong是用于將指定偏移量的32位值檢索到窗口類對象的額外窗口存儲器中的API,SetWindowLong用于更改指定偏移量的值。
通過這樣做,惡意軟件可以簡單地更改窗口類中的函數指針的偏移量,并將其指向寫入共享部分的shellcode。

像上面提到的大多數其他技術一樣,惡意軟件需要觸發它編寫的代碼。

在以前討論的技術中,惡意軟件通過調用API(如CreateRemoteThread,QueueUserAPC或SetThreadContext)來實現這一點。

在EWMI方法中,惡意軟件通過調用SendNotifyMessage觸發注入的代碼。
在執行SendNotifyMessage之后,Shell_TrayWnd接收并將控件傳遞給由SetWindowLong先前設置的值指向的地址。

在圖13中,名為PowerLoader的惡意軟件使用這種技術。

9. SHIMS注入

Microsoft向開發人員提供了Shims[譯者注:Shim是一個工程術語,描述為了讓兩個物體更好地組裝在一起而插入的一塊木頭或金屬。在計算機編程中,shim是一個小型的函數庫,用于透明地攔截API調用,修改傳遞的參數、自身處理操作、或把操作重定向到其他地方。Shim也可以用來在不同的軟件平臺上運行程序。],主要是為了向后兼容。

Shims允許開發人員將修補程序應用于程序,而無需重寫代碼。 通過利用Shims,開發人員可以告訴操作系統如何處理其應用程序。

Shims本質上是一種嵌入API并針對特定可執行文件的方式。 惡意軟件可以利用Shims來實現注入可執行文件并維持注入。

Windows運行Shim引擎時,它加載二進制文件以檢查shimming數據庫,以便應用適當的修補程序。

有許多可以使用的修復程序,但是惡意軟件還是更偏愛那些安全相關的(例如DisableNX,DisableSEH,InjectDLL等)。要安裝shimming數據庫,惡意軟件可以使用各種方法。

例如,一個常見的方法是簡單執行sdbinst.exe,并將其指向惡意的sdb文件。 在圖14中,廣告軟件“Search Protect by Conduit”使用Shims進行注入和維持。 它在Google
Chrome中執行“InjectDLL”shim以加載vc32loader.dll。

現在有一些用于分析sdb文件的工具,但是對于下面列出的sdb的分析,我使用了python-sdb,而沒有使用現成的工具。

圖14 Search Protect用于注入的SDB

10. IAT HOOKING和INLINE HOOKING (又名應用層ROOTKITS)

IAT hooking 以及 inline hooking通常被稱為用戶級rootkit. 惡意軟件可以利用IAT HOOKING技術更改導入地址表。

當合法應用程序調用位于DLL中的API時,將執行替換的函數,而不是原始代碼。 相比之下,使用Inline Hooking,惡意軟件可以修改API函數本身。 在圖15中,惡意軟件FinFisher通過修改CreateWindowEx指向的位置執行IAT HOOKING。

圖 15 FinFisher 通過更改CreateWindowEx指向的位置實現IAT HOOKING

總結

在這篇文章中,我介紹了惡意軟件在另一個進程中隱藏其活動的十種不同技術。
通常,惡意軟件直接將其shellcode注入到另一個進程中,或者強制另一個進程加載其惡意DLL。
在表1中,我對各種技術進行了分類,并提供了樣品,作為觀察本文所涵蓋的每種注射技術的參考。
整篇文章中的數字將有助于研究人員在反轉惡意軟件時識別各種技術。

表格1: 流程注入可以通過直接將代碼注入到另一個進程中,或通過強制將DLL加載到另一個進程來完成

攻擊者和研究人員經常發現新的技術來實現注入并提供隱藏自身的目的。這篇文章詳細介紹了十種常見和新興的技術,但還有其他的沒有提及,如COMM劫持。 防御者在其使命中將永遠不會“完成”檢測和防止隱形進程注入的任務,因為入侵者永遠不會停止創新。

在EndGame[譯者注:原文發表的網站名稱為EndGame],我們不斷研究先進的隱藏技術,并將這些技術帶入我們的產品中,給產品提供保護。我們的層級功能可以檢測加載某些維持注入(如AppInit DLL,COM Hijack等)的惡意DLL,通過我們的shellcode注入防護軟件,可以實時防止許多形式的代碼注入,并且可以檢測在內存中運行的惡意注入的有效負載。我們正在申請專利的無文件攻擊檢測技術可以讓我們的平臺比市場上任何其他產品更有效地防止代碼注入,同時還通過新興的代碼注入技術最大限度地提高繞過的彈性。

本文由看雪翻譯小組 skeep 編譯,來源Ashkan Hosseini@endgame’s blog

【via@看雪社區