1. 程式人生 > >10種常見的程序注入技術的總結

10種常見的程序注入技術的總結

http://p0.qhimg.com/t0189831cc51efb99b5.jpg

0x00 前言

程序注入是一種廣泛應用於惡意軟體和無檔案攻擊中的逃避技術,這意味著可以將自定義程式碼執行在另一個程序的地址空間內。程序注入提高了隱蔽性,也實現了持久化。儘管有非常多的程序注入技術,但是本文我只列舉了10種常見的技術。我還提供了這些技術的相關截圖以便逆向和惡意軟體的分析,並幫助防禦這些技術。

0x01 通過CreateRemoteThread和LoadLibrary的DLL注入

這是程序注入最常見的技術。惡意軟體將惡意的動態連結庫的路徑寫入另一個程序的虛擬地址空間內,通過在目標程序中建立遠端執行緒來確保遠端程序載入它。

http://p1.qhimg.com/t0140045ec12c9f16f1.png

惡意軟體首先需要選擇目標程序(例如svchost.exe)。通常使用API:CreateToolhelp32Snapshot, Process32First, 和 Process32Next來完成。CreateToolhelp32Snapshot是個用於列舉指定程序或所有程序的堆或模組的狀態,並且它返回一個快照。Process32First得到快照中的第一個程序的資訊,然後Process32Next來遍歷所有的程序。在找到目標程序後,惡意軟體呼叫OpenProcess得到目標程序的控制代碼。

如上圖所示,惡意軟體呼叫VirtualAllocEx得到寫入路徑的記憶體空間。然後呼叫WriteProcessMemory在分配的記憶體中寫入路徑(動態連結庫)。最後,呼叫API(如CreateRemoteThread、NtCreateThreadEx、RtlCreateUserThread)使得另一個程序執行程式碼。後兩個API是未文件化的。然而,通常想法是將LoadLibrary的地址傳入這些API中的一個,以便遠端程序執行DLL。

CreateRemoteThread被許多安全產品跟蹤並標記。而且,它在磁碟上面留下了一個惡意的DLL可供檢測。考慮到攻擊者注入程式碼最常見的目的是逃避防禦,高明的攻擊者不會使用這種方式。下面是名為Rebhip(Sha256: 07b8f25e7b536f5b6f686c12d04edc37e11347c8acd5c53f98a174723078c365)的惡意軟體使用了這種技術。

http://p1.qhimg.com/t015953793fe4b1b377.png

0x02 可執行檔案注入(PE注入)

惡意軟體並不傳入LoadLibrary的地址,而是拷貝惡意程式碼到開啟的程序中並執行(通過小段shellcode或者呼叫CreateRemoteThread)。與LoadLibrary相比,PE注入的優勢是惡意軟體不需要在磁碟中釋放一個惡意的DLL。與上個技術類似,惡意軟體在目標程序中分配記憶體,呼叫WriteProcessMemory將惡意程式碼而不是DLL路徑寫入記憶體。然而,這種方式的缺陷是被複制的映像的基址的改變。當一個惡意軟體注入PE到另一個程序,它的新基址是不可預料的,需要動態重新計算PE的地址。為了完成這個,惡意軟體需要找到目標程序的重定位表,並根據它的重定位描述解析被複制映像的絕對地址。

http://p1.qhimg.com/t01f0d9c7071cfb9eba.png

這種技術和其他技術很類似,如反射DLL注入和記憶體模組載入,因為他們都不釋放任何檔案到磁碟。但是,記憶體模組和反射DLL注入更加隱蔽。他們不依賴Windows API(如CreateRemoteThread或LoadLibrary),因為他們在記憶體中載入並執行自身。反射DLL注入通過在記憶體中建立一個DLL對映執行,而不依賴Windows的載入器。記憶體模組載入和反射DLL注入類似,其不同之處只是在於記憶體模組載入的注入器或載入器負責對映目標DLL到記憶體中而不是DLL自身對映。在之前的博文中,討論過這兩種技術。

當分析PE注入時,在呼叫CreateRemoteThread之前通常能看見迴圈(通常是兩個for迴圈,一個巢狀在另一箇中)。這種技術在crypter(加密和混淆軟體)中非常流行。下圖中的樣本(Sha256: ce8d7590182db2e51372a4a04d6a0927a65b2640739f9ec01cfd6c143b1110da)充分利用了這種技術。在呼叫WriteProcessMemory和CreateRemoteThread之前有兩層迴圈來處理重定位。“and 0x0fff”指令也是一個比較好的表徵,它標明瞭頭12位用於得到包含重定位塊的虛擬地址的偏移量。現在惡意軟體重新計算了所有需要的地址了,只需要將起始地址傳入CreateRemoteThread並執行就行了。

http://p9.qhimg.com/t01f85d795b2cdc8564.png

0x03 程序hollow(又名程序替換和RunPE)

惡意軟體有一種技術叫程序hollow,而不是注入程式碼到程式中(如DLL注入)。程序hollow發生在惡意軟體unmap目標程序的合法記憶體程式碼,並使用惡意的程式碼覆寫目標程序的記憶體(如svchost.exe)的時候。

http://p3.qhimg.com/t0116deee4505a63f3d.png

惡意軟體首先以掛起模式建立一個新程序來容納惡意程式碼。如下圖(Sha256: eae72d803bf67df22526f50fc7ab84d838efb2865c27aef1a61592b1c520d144),以CREATE_SUSPENDED (0x00000004)為引數呼叫CreateProcess。新程序的主執行緒建立後就處於掛起狀態,直到呼叫ResumeThread才會繼續執行。接下來,惡意軟體需要使用惡意的payload來填充合法檔案的內容。呼叫ZwUnmapViewOfSection或者NtUnmapViewOfSection來unmap目標程序的記憶體。這兩個API將釋放section指向的所有記憶體。記憶體unmap之後,使用WriteProcessMemory將惡意軟體的節寫入目標程序。呼叫SetThreadContext將入口點指向它已寫入的新的程式碼節。最後,呼叫ResumeThread恢復掛起程序的執行。

http://p3.qhimg.com/t01106bf8827e00947f.png

0x04 執行緒執行劫持(又名掛起、注入並恢復)

這種技術類似於程序hollow。線上程執行劫持中,惡意軟體的目標是程序中已存在的執行緒,而且沒有建立任何程序或執行緒。因此,在分析期間你可能看見CreateToolhelp32Snapshot和Thread32First、OpenThread。

http://p4.qhimg.com/t01a8f5eee4da871bf3.png

在得到目標執行緒的控制代碼後,惡意軟體呼叫SuspendThread將執行緒掛起。呼叫VirtualAllocEx和WriteProcessMemory來分配記憶體並執行程式碼注入。程式碼包含shellcode,惡意DLL的路徑和LoadLibrary的地址。

下圖(Sha256: 787cbc8a6d1bc58ea169e51e1ad029a637f22560660cc129ab8a099a745bd50e)描述了一個普通木馬是如何使用這種技術的。為了劫持執行緒的執行,惡意軟體呼叫SetThreadContext修改目標執行緒的EIP暫存器(包含下條執行指令的地址的暫存器)。隨後,惡意軟體恢復執行緒繼續執行它已寫入到宿主程序的shellcode。從攻擊者的角度看,這種方式是有問題的,因為在系統呼叫的中途掛起並恢復執行緒可能引起系統崩潰。為了避免這種情況的發生,更復雜的利用技術是,一旦EIP暫存器在NTDLL.dll中就恢復並重試。

http://p8.qhimg.com/t0141eaa35b05d7bc65.png

0x05 通過SetWindowsHookEx鉤子注入

鉤子是用於攔截函式呼叫的一種技術。惡意軟體能利用指定執行緒中事件觸發來載入他們的惡意DLL。通常使用SetWindowsHookEx來安裝訊息鉤子。SetWindowsHookEx有4個引數。第一個引數是事件的型別。事件有很多的型別,有鍵盤按鍵(WH_KEYBOARD)和滑鼠輸入(WH_MOUSE)等。第二個引數是個函式指標,指向惡意軟體想要處理事件的函式。第3個引數是包含函式的模組。因此,通常可以看見LoadLibrary、GetProcAddress、SetWindowsHookEx。最後一個引數是訊息鉤子關聯的執行緒。如果值為0,則針對所有執行緒。然而,只針對某個執行緒的目標會小很多,因此也可能看見CreateToolhelp32Snapshot和Thread32Next。一旦DLL被注入後,惡意軟體將執行惡意程式碼。下圖中,勒索軟體Locky(Sha256: 5d6ddb8458ee5ab99f3e7d9a21490ff4e5bc9808e18b9e20b6dc2c5b27927ba1)就使用了這種技術。

http://p6.qhimg.com/t01e2dd4174a11fb5ba.png

0x06 通過登錄檔修改(如AppInit_DLLs,AppCertDlls,IFEO)

Appinit_DLL, AppCertDlls, IFEO(映像劫持)可以用於注入和持久化。完整的路徑如下:

http://p1.qhimg.com/t010bb2abc9d38fe67d.png

AppInit_DLLs

惡意軟體能在AppInit_DLLs鍵下插入惡意的DLL的路徑,以便其他程序載入。該鍵下每個DLL會被載入到所有的載入User32.dll的程序中。User32.dll是常見的Windows基礎庫。因此,當惡意軟體修改這個子鍵時,大量程序將載入惡意的DLL。下圖中,木馬Ginwui(Sha256: 9f10ec2786a10971eddc919a5e87a927c652e1655ddbbae72d376856d30fa27c)依賴了這種技術。它通過呼叫RegCreateKeyEx開啟AppInit_DLLs鍵,並呼叫RegSetValueEx修改它。

http://p6.qhimg.com/t01ee81af5664384e09.png

AppCertDlls

這種方式類似與AppInit_DLLs,除了該鍵下的DLL會載入到呼叫Win32 API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW, WinExec的程序中。

IFEO

IFEO通常用於除錯。開發者能在該鍵下設定偵錯程式,來附加除錯。因此,當可執行檔案啟動時,附加到它的程式也會啟動。為了使用這功能,你能簡單的設定偵錯程式的路徑,並附加到你想分析的可執行檔案上。下圖,木馬Diztakun(Sha256: f0089056fc6a314713077273c5910f878813fa750f801dfca4ae7e9d7578a148)使用了這種技術,它修改了工作管理員的偵錯程式的值。

http://p6.qhimg.com/t011e2ee5119c6dac5c.png

0x07 APC注入和AtomBombing

惡意軟體利用非同步過程呼叫(APC)來強制另一個執行緒執行附加到APC佇列的自定義程式碼。每個執行緒都有一個APC佇列,當執行緒進入可變狀態(編輯注: 這裡疑為英文原文的拼寫錯誤,有兩處使用了alterable state一詞,而一處使用了alertable state,疑應為alterable state)時,可以被執行。當呼叫SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx,  WaitForSingleObjectEx時進入可變狀態。惡意軟體通常查詢執行緒是否處於可變狀態,然後呼叫OpenThread和QueueUserAPC來向執行緒插入APC。QueueUserAPC有3個引數:1. 目標執行緒的控制代碼 2. 惡意軟體想要執行的函式指標 3. 傳給函式的引數。下圖,惡意軟體Amanahe(Sha256: f74399cc0be275376dad23151e3d0c2e2a1c966e6db6a695a05ec1a30551c0ad)首先呼叫了OpenThread來得到另一個執行緒的控制代碼,然後呼叫QueueUserAPC,以LoadLibrary作為函式指標注入惡意DLL。

AtomBombing由enSilo首次提出,然後在Dridex V4中使用。正如之前博文中討論的,這種技術也依賴APC注入。然而它使用atom表來寫入到另一個程序的記憶體。

http://p9.qhimg.com/t019b085ae98c15f99a.png

0x08 通過SetWindowLong的視窗記憶體注入(EWMI)

EWMI依賴注入到資源管理器托盤視窗記憶體中,並在惡意軟體家族Gapz和PowerLoader中使用多次。當註冊一個視窗類時,應用程式能指定額外的記憶體位元組,稱為額外的視窗記憶體(EWM)。然而,在EWM中沒有太多的空間。為了規避這個限制,惡意軟體將程式碼寫入explorer.exe的共享段中,並使用SetWindowLong和SendNotifyMessage得到一個指向shellcode的函式指標,然後執行它。

當寫入共享段時,惡意軟體有兩個選項。它能建立一個共享段自己對映到另一個程序(如explorer)中,或者開啟一個已存在的共享段。前者有分配堆記憶體的開銷,而且還要呼叫NtMapViewOfSection等API,因此後者更常用。在惡意軟體將shellcode寫入共享段後,使用GetWindowLong和SetWindowLong來訪問並修改Shell_TrayWnd的額外的視窗記憶體。GetWindowLong是用於通過32位值作為偏移得到視窗類物件中額外視窗記憶體,同時使用SetWindowLong能改變指定偏移的值。通過完成這個,惡意軟體能改變視窗類中的函式指標,將它指向共享段的shellcode。

和上述的技術一樣,惡意軟體需要觸發寫入的程式碼。之前說,它是通過呼叫類似CreateRemoteThread,SetThreadContext,QueueUserAPC這些API來實現的。與之前不同的是,這種技術是通過使用SendNotifyMessage來觸發程式碼執行的。

一旦執行SendNotifyMessage,Shell_TrayWnd將接收到並將控制移交給SetWindowLong設定的地址。下圖,名為PowerLoader(Sha256: 5e56a3c4d4c304ee6278df0b32afb62bd0dd01e2a9894ad007f4cc5f873ab5cf)的惡意軟體使用了這種技術。

http://p1.qhimg.com/t0114751b13bb61774d.png

http://p4.qhimg.com/t01cf9411a4a4456c64.png

0x09 使用Shims注入

微軟提供了Shims給開發者,這主要是為了向後相容。Shims允許開發者不必重寫程式碼就能修復程式。通過利用shims,開發者告訴作業系統如何處理他們的應用程式。Shims本質是Hook API的方式。惡意軟體能利用shims實現注入和持久化。當載入二進位制時,Windows執行Shim引擎以檢查shim資料庫,以便使用合適的修復。

有很多修復可以利用,但是惡意軟體最喜歡的是一些安全相關的(如DisableNX, DisableSEH, InjectDLL等)。為了安裝一個shim資料庫,惡意軟體部署了多種方式。例如,常見的一種方式是執行sdbinst.exe,並將它指向惡意的sdb檔案。如下圖,一個廣告軟體“Search Protect by Conduit”(Sha256: 6d5048baf2c3bba85adc9ac5ffd96b21c9a27d76003c4aa657157978d7437a20),使用shim來實現了持久化和注入。它執行一個“InjectDLL”shim到谷歌chrome中載入vc32loader.dll。有一些現成的工具可以分析sdb檔案,下面是我使用python-sdb分析的結果。

http://p3.qhimg.com/t018af4fb21e51760f0.png

0x0A IAT hook和Inline hook(應用層rootkit)

IAT hook和inline hook通常也叫應用層rootkit。IAT hook使用用於改變匯入地址表的技術。當合法的程式呼叫位於DLL中API時,將會執行被替換的API。相反,在inline hook中,惡意程式修改API函式本身。如下圖,惡意軟體FinFisher(Sha256: f827c92fbe832db3f09f47fe0dcaafd89b40c7064ab90833a1f418f2d1e75e8e),IAT就hook了CreateWindowEx。

http://p9.qhimg.com/t019a0fb8ad70270301.png

0x0B 總結

本文中,我描述了惡意軟體用於隱藏自身行為的10種不同的技術。通常,惡意軟體直接注入shellcode到另一個程序中或者強制其他程序載入惡意DLL。如下表,我已經將不同的技術進行了分類,並提供了樣本,用於檢視在本文提到的每個注入技術。這可以幫助研究者用於在逆向時識別各種技術。

http://p4.qhimg.com/t01ccc88d73747ebc98.png

攻擊者和研究員一直在研究新的注入和隱蔽的技術。本文介紹了10種常見的技術,但是還有其他的,如COM劫持。防禦者任重道遠。